HTTP/MIRC Scripting Language

From Rosetta Code
HTTP/MIRC Scripting Language is part of HTTP. You may find other members of HTTP at Category:HTTP.

A simple implementation of the HTTP protocol in MIRC Scripting Language. The 'on SOCKREAD' event is structured that way so that it can be re-entered when more data arrives, without losing any information.

; /wget http://www.example.com/somefile.txt
alias wget {
  var %url = $1-
  var %id = wget. $+ $ctime

  ; A simple regular expression to parse the url:
  var %re = ^http://([^\s/]+)(.*)
  if ($regex(wget,%url,%re) !isnum 1-) {
    echo -ti2a * wget: Invalid url: %url
    return
  }

  var %hostport = $regml(wget,1)
  var %path = $regml(wget,2)

  ; Split on ":"
  var %host = $gettok(%hostport,1,58)
  var %port = $gettok(%hostport,2,58)

  ; Default values
  if (%port == $null) {
    %port = 80
  }
  if (%path == $null) {
    %path = /
  }

  ; Open a socket to the server, and mark it with some
  ; information we will need later
  sockopen %id %host %port
  sockmark %id %hostport %path
}

on *:SOCKOPEN:wget.*:{
  var %id = $sockname
  if ($sockerr) {
    echo -ti2a * wget: Error while connecting: $sock($sockname).wserr $&
      $sock($sockname).wsmsg
    sockclose %id
    halt
  }

  ; Take out the hostname and path which the socket has been marked with
  var %mark = $sock(%id).mark
  var %hostport = $gettok(%mark,1,32)
  var %path = $gettok(%mark,2-,32)

  ; Update the mark with a state name. (See below)
  sockmark %id statusline

  ; Send the request
  var %w = sockwrite -tn %id
  %w GET %path HTTP/1.0
  %w Host: %hostport
  %w Connection: Close
  %w $crlf
}

on *:SOCKREAD:wget.*:{
  var %id = $sockname
  if ($sockerr) {
    echo -ti2a * wget: Error while receiving: $sock($sockname).wserr $sock($sockname).wsmsg
    sockclose %id
    halt
  }

  ; Look at the current state
  var %state = $sock(%id).mark

  ; Read the first line
  var %line
  sockread %line

  ; Loop while more data is coming in
  while ($sockbr) {
    if (%state == statusline) {
      ; STATUSLINE: This state is the initial one.
      ; Examine the status line and take an appropriate action
      var %version = $gettok(%line,1,32)
      var %code = $gettok(%line,2,32)
      var %reason = $gettok(%line,3-,32)
      if (2?? iswm %code) {
        ; 2xx codes indicate it went ok
        %state = headers
        sockmark %id %state
      }
      elseif (3?? iswm %code) {
        ; 3xx codes indicate redirection
        %state = redirect
        sockmark %id %state
      }
      else {
        ; but anything else is treated as an error
        echo -ti2a * wget: Server error: %line
        sockclose %id
        halt
      }
    }
    elseif (%state == redirect) {
      ; REDIRECT: This state is entered when a 3xx status code is received.
      ; Find the 'Location' header, and issue a new request.
      if ($len(%line) == 0) {
        ; An empty line indicate the end of the headers
        echo -ti2a * wget: Server error: Got 3xx status code, but nowhere to redirect.
        sockclose %id
        halt
      }
      else {
        var %header = $gettok(%line,1,58)
        var %value = $gettok(%line,2-,58)
        if (%header == Location) {
          ; 'Location' header found. Issue a new request.
          wget %value
          sockclose %id
          halt
        }
      }
    }
    elseif (%state == headers) {
      ; HEADERS: This state is entered after the status line has been examined.
      ; Examine the headers, and look for a blank line.
      if ($len(%line) == 0) {
        ; An empty line indicate the end of the headers
        %state = data
        sockmark %id %state
      }
      else {
        var %header = $gettok(%line,1,58)
        var %value = $gettok(%line,2-,58)
        ; Do something with the headers
      }
    }
    elseif (%state == data) {
      ; DATA: This state is the final one.
      ; Read and display everything received
      echo -a %line
    }
    sockread %line
  }
}