### http.irc .8.0 ### HTTP implemented in epic4's scripting language ### by Zachary White (skullY on EFnet and FEFnet) /* General program flow bind some port, make the default 6667. Store each in some variable that can be set from within the client. Upon connection, note the IP and port. Set the status variable to note that the connection has happened, we are just waiting for the client request. When the client sends the HTTP request, note all the pertinent info, then figure out what to do. If they don't have an authentication header, then return the proper noauth code. username should be set by client, and must not be the same as the user's nick or system username. Same for the passwd. Maybe run the passwd against a dictionary and do basic checks like that? If the client doesn't present a cookie, try to set one, and note that the client didn't return the cookie. If the client tries to connect again and doesn't return the cookie, deny the client. I need some sort of auth to prevent spoofed requests, and this is about the best I can come up with short of SSL. Maybe some javascript that implements blowfish or idea or something..... Requests and commands: GET's should only be made to update the irc frame, and it should happen once every 5 or 6 seconds. Any more than that and you're a freak and should be using a real client, not a web browser. -All text submission should be done on a POST method. Initially, there -will be two "scripts" to post to. /SAY which will put anything you type -into the channel, and /DO which will run a command in a hopefully sane -mannor. So as to avoid anything really bad happening to an owned client, -we should $encode() the input of both upon reading, and $decode() it when -using it, being careful not to further evaluate it. +All text submissions should be done by the POST method. The script submits +to /CMD and the submit type will determine what it does. So as to avoid +anything really bad happening to an owned client, we should $encode() the +input and then $decode() when using it, being careful not to further eval +it. The Web Browser should be broken up into 3 frames. The bottom one where all the commands and text entry happens, the top one where all output goes, and a small middle bar that acts like a status bar. *evil grin* Possible commands, and their arguments: WHO NAMES WHOIS KICK [reason] OP [nick1] [nick...] DEOP [nick1] [nick...] MOP MDOP JOIN LEAVE AWAY [reason] IGNORE SAY Connection status: 1 Waiting for request 2 Request recieved, send reply 3 Closing connection */ ### Variables eval assign HTTP_PORT $listen(6667) @ connection_num=0 ### Arrays # This is the array that holds the display. It holds the last 11 items to be # printed to the display. eval : $setitem(message 0 ~) $setitem(message 1 ~) $setitem(message 2 ~) $setitem(message 3 ~) $setitem(message 4 ~) $setitem(message 5 ~) $setitem(message 6 ~) $setitem(message 7 ~) $setitem(message 8 ~) $setitem(message 9 ~) $setitem(message 10 ~) # This is for holding client infos. The array index number is the FD, and # the data inside the element determines the status of the connection. # ~ FD isn't in use # hostname Connection made, no request yet # hostname URI Protocol Connection made, request made eval : $setitem(client 0 ~) $setitem(client 1 ~) $setitem(client 2 ~) $setitem(client 3 ~) $setitem(client 4 ~) $setitem(client 5 ~) $setitem(client 6 ~) $setitem(client 7 ~) $setitem(client 8 ~) $setitem(client 9 ~) $setitem(client 10 ~) # This array stores the client headers that we'll be keeping track of. Can # be searched through with $matchitem() eval : $setitem(client_headers 0 referer: display_header) $setitem(client_headers 1 via: display_header) $setitem(client_headers 2 authorization: check_basicauth) $setitem(client_headers 3 cookie: :) $setitem(client_headers 4 host: :) $setitem(client_headers 5 user-agent: display_header) # This array stores the possible GET requests. Can use $matchitem to find the # document and return what our request should be. eval : $setitem(documents 0 / http_send_slash) $setitem(documents 1 /window http_send_window) $setitem(documents 2 /status http_send_status) $setitem(documents 3 /input http_send_input) /* Needed /ons: on connection 6667 { Note file descripter assign to status of 1 } */ eval on ^dcc_raw "% % N $HTTP_PORT" { eval :$setitem(client $0 $1) xecho -banner HTTP connection from $1 } /* on data 6667 { if hostname:port = status1 { check request against possible URLs { command_to_serve_that_url }{ command_to_serve 404 } }{ elsif hostname:port = status2 # data should not be coming in right now. Ignore it }{ # Data should especially not be coming in now. } } */ on dcc_raw -"% % D %" on ^dcc_raw "% % D *" { if ([$tolower($3)]==[get]) { http_get $0 $1 $encode($4-) }{ http_header $0 $1 $encode($3-) } } /* on {public,public_other,msg,notice} * { add_message_to_stack with formatted message } Aliases: */ # Passed: A message to add to the stack alias add_message_to_stack { eval : $delitem(message 0) eval : $setitem(message 10 $*) } # Passed: fd remotehost $decode(URI protocol/version) alias http_get { xecho -banner HTTP Request from $1 for $leftw(1 $decode($2)) eval : $setitem(client $0 $getitem(client $0) $leftw(1 $decode($2))) } # Passed: FD hostname $encode(header) alias http_header { # This should search the referer array, and if it finds a match, do something # with the information if ([$2]) { local array_search $matchitem(client_headers $tolower($leftw(1 $decode($2))) *) if (array_search >= 0) { eval $restw(1 $getitem(client_headers $array_search)) $* } : #xecho -banner $1 sent the following header: $decode($2) }{ http_send_request $0 $1 $encode($restw(1 $getitem(client $0))) } } # Passed: FD hostname $encode(header) alias check_basicauth { xecho -banner $decode($2) if ([$rightw(1 $decode($2))]==[c2t1bGx5OnlvdXJtb20=]) { assign AUTH[$0] 1 }{ http_auth_require $* } } # Passed: FD hostname $encode(request) alias http_send_request { local request $matchitem(documents $decode($2) *) if (request < 0) { http_send_404 $* } elsif ( AUTH[$0] ) { eval $rightw(1 $getitem(documents $request)) $* }{ http_auth_required $* } # if ([$tolower($strip(/ $2))]=[]) { # http_send_slash $* # } elsif ([$tolower($strip(/ $2))]=[window]) { # http_send_window $* # } elsif ([$tolower($strip(/ $2))]=[status]) { # http_send_status $* # } elsif ([$tolower($strip(/ $2))]=[input]) { # http_send_input $* # }{ # http_send_404 $* # } } # Passed: FD hostname $encode(request) alias http_auth_required { xecho -banner Sending HTTP authentication required headers to $1 after processing request for $decode($2) on FD $0 dcc raw $0 $1 HTTP/1.0 401 WHAT YOU SAY dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Server: ircII $J (http.irc .8.0) dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 401 Authorization Required dcc raw $0 $1 dcc raw $0 $1

Authorization Required

dcc raw $0 $1 This server could not verify that you dcc raw $0 $1 are authorized to access the document dcc raw $0 $1 requested. Either you supplied the wrong dcc raw $0 $1 credentials (e.g., bad password), or your dcc raw $0 $1 browser doesn't understand how to supply dcc raw $0 $1 the credentials required.

dcc raw $0 $1


dcc raw $0 $1
ircII $J (http.irc .8.0) Server
dcc raw $0 $1 dcc close raw $0 } # Passed: FD hostname $encode(request) alias http_send_slash { xecho -banner Sending HTTP request $decode($2) to $1 on FD $0 dcc raw $0 $1 HTTP/1.0 200 ALL YOUR REQUEST ARE BELONG TO US dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Age: 0 dcc raw $0 $1 Server: ircII $J (http.irc .8.0) #dcc raw $0 $1 Set-Cookie: foo=bar dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 IRC to HTTP Gateway dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 Sorry, I'd love to make this work without using frames, but it needs frames for now. dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 dcc close raw $0 assign -AUTH[$0] } # Passed: FD hostname $encode(request) alias http_send_window { xecho -banner Sending HTTP request $decode($2) to $1 on FD $0 dcc raw $0 $1 HTTP/1.0 200 ALL YOUR REQUEST ARE BELONG TO US dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Age: 0 dcc raw $0 $1 Server: ircII $J (http.irc .8.0) #dcc raw $0 $1 Set-Cookie: foo=bar dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 IRC to HTTP Gateway dcc raw $0 $1 dcc raw $0 $1 This is the text window dcc raw $0 $1 dcc raw $0 $1 dcc close raw $0 assign -AUTH[$0] } # Passed: FD hostname $encode(request) alias http_send_status { xecho -banner Sending HTTP request $decode($2) to $1 on FD $0 dcc raw $0 $1 HTTP/1.0 200 ALL YOUR REQUEST ARE BELONG TO US dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Age: 0 dcc raw $0 $1 Server: ircII $J (http.irc .8.0) ##dcc raw $0 $1 Set-Cookie: foo=bar dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 IRC to HTTP Gateway dcc raw $0 $1 dcc raw $0 $1 This is the status window dcc raw $0 $1 dcc raw $0 $1 dcc close raw $0 assign -AUTH[$0] } # Passed: FD hostname $encode(request) alias http_send_input { xecho -banner Sending HTTP request $decode($2) to $1 on FD $0 dcc raw $0 $1 HTTP/1.0 200 ALL YOUR REQUEST ARE BELONG TO US dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Age: 0 dcc raw $0 $1 Server: ircII $J (http.irc .8.0) #dcc raw $0 $1 Set-Cookie: foo=bar dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 IRC to HTTP Gateway dcc raw $0 $1 dcc raw $0 $1 This is the input window dcc raw $0 $1 dcc raw $0 $1 dcc close raw $0 assign -AUTH[$0] } # Passed: FD hostname $encode(request) alias http_send_404 { xecho -banner Sending HTTP request $decode($2) to $1 on FD $0 dcc raw $0 $1 HTTP/1.0 404 SOMEONE SET US UP THE BOMB dcc raw $0 $1 Cache-control: no-cache dcc raw $0 $1 Pragma: no-cache dcc raw $0 $1 Connection: close dcc raw $0 $1 Date: $strftime(%a, %d %b %Y %X GMT) dcc raw $0 $1 Warning: 199 This is an in progress HTTP implementation dcc raw $0 $1 Age: 0 dcc raw $0 $1 Server: ircII $J (http.irc .8.0) #dcc raw $0 $1 Set-Cookie: foo=bar dcc raw $0 $1 Content-Type: text/html dcc raw $0 $1 dcc raw $0 $1 dcc raw $0 $1 IRC to HTTP Gateway dcc raw $0 $1 dcc raw $0 $1 Error: 404 $decode($2) is not avalible from this server. dcc raw $0 $1 dcc raw $0 $1 dcc close raw $0 assign -AUTH[$0] } # Passed: $encode(header) alias display_header { xecho -banner $strip( $decode($0)) } /* # Passed: channel/nick and all pertitent client info alias http_who { on who { store in list } who wait format and send to client in a javascript popup window } # Passed: channel/nick alias http_names { # I think there's an epic function for this. That makes it easy add_message_to_stack $names_list } # Passed: nick alias http_whois { - # Set /on hooks for all the whois types - on whois hooks + # No need to be so complex. Just whois the nick and let the regular + # whois /on's dump it into the array. whois nick - wait - foreach_on_whois_input { - add_message_to_stack - } } # Passed: $encode(nick channel reason) alias http_kick { //kick $decode($nick $channel $reason) } # Passed: channel nick0 alias http_op { //mode $channel +ooo $1 $2 $3 if ($4) { http_op $4- } } # Passed: channel nick0 alias http_deop { //mode $channel -ooo $1 $2 $3 if ($4) { http_deop $4- } } # Passed: $encode(channel ) alias http_join { join $decode($0) } # Passed: $encode(channel) alias http_leave { leave $decode($0) } # Passed: $encode(reason) alias http_away { away $decode($0) } # Passed: $encode(mask type) alias http_ignore { ignore $decode($0) } */