HTTPd — File Browser

HTTPdv1.0 / HTTPdv1.0 / HTTPd / HTTPd.mrc

HTTPd.mrc — 87.12 KB — Download this file

/*
HTTP daemon for mIRC v7.61+

Version:  1.0
Coded by: Dazuz @ QuakeNet

Optional:
Geo Script.mrc    $GEOLOCATION is used when a connection is accepted.
*/

;This alias creates $scriptdirCube.ico file. Feel free to remove the alias, it won't break anything important.
alias httpd.createicon {
  set -l %icon $qt($scriptdirCube.ico)
  if (!$isfile(%icon)) {
    bset -t & 1 Y2BgBEIBAQYgUGDIYGFgEAOyNIBYACzCAJQFkQwMDiwMGOD///+MtMBrt+9oRMak6steN+U/MiZkDrq+zMPL/6c/PPSfGHOw6YNhdP3I5sD0Y9NHSD8II+vHpnco63/x8+v/vS/uwjGx+kH6YBhZPzZzkPXPO7sHRS8u/SDce2wTin6YGejm4NKHrheXOaTow2UOqfpIxaASgBIMAA==
    if ($decode(&,bm)) && ($decompress(&,bm1)) && ($sha1(&,1) == ae378536e1f7af22066cb722dd04739a5a7fe8a4) bwrite %icon 0 &
  }
}

on *:start:if (%httpd.startup) httpdstart

on *:load: {
  if ($version < 7.61) {
    echo $color(info) -at * Unsupported mIRC version, please update to $v2 or newer.
    unload -rs $qt($script)
  }
  else {
    echo $color(info) -at * HTTPd loaded! Type /HTTPD to open the config dialog.
    httpd.createicon
  }
}

on *:unload: {
  unset %httpd.*
  httpdstop -quiet -force
  .remove $qt($scriptdirCube.ico)
  if ($dialog(httpd)) dialog -c httpd
}

menu status,menubar {
  HTTPd
  .$+(HTTPd config,$chr(9),/httpd):httpd
  .-
  .$iif($sock(httpd.listen),$+(Stop the server,$chr(9),/httpdstop)):httpdstop
  .$iif(!$sock(httpd.listen),$+(Start the server,$chr(9),/httpdstart)):httpdstart
  .-
  .Uninstall:if ($input(Do you really want to uninstall HTTPd?,yqu,HTTPd)) unload -rs $qt($script)
}

menu @HTTPd {
  dclick:httpd
  $+(HTTPd config,$chr(9),/httpd):httpd
  -
  $+(Stop the server,$chr(9),/httpdstop)
  .Stop now:httpdstop
  -
  $iif($window(@HTTPd).sbstate $window(@HTTPd).tbstate == 0 0,$style(1)) Hide the window: {
    if ($window(@HTTPd).sbstate $window(@HTTPd).tbstate != 0 0) {
      window -w0 @HTTPd
      hadd httpd.config VisibleLogWindow 0
    }
    else {
      window -w3 @HTTPd
      hadd httpd.config VisibleLogWindow 1
    }
  }
  -
  Logging
  .$iif($window(@HTTPd).logfile,$style(1)) Save to a file: {
    if ($window(@HTTPd).logfile) .log off @HTTPd
    else .log on @HTTPd -f $qt($scriptdirHTTPd.log)
  }
  .-
  .$+($iif(!$isfile($scriptdirHTTPd.log),$style(2)),View log,$chr(9),$scriptdirHTTPd.log):logview $qt($scriptdirHTTPd.log)
  Statistics
  .$+(Started,$chr(9),$httpd.birth):httpd about
  .$+(Duration,$chr(9),$duration($calc($gmt -%c.httpd.birth))):httpd about
  .$+(Type,$chr(9),$iif($group(#httpd.localareanetwork) == on,Local Area Network,Wide Area Network)):httpd about
  .$+(Log lines,$chr(9),$bytes($line(@HTTPd,0)).suf):httpd about
  .-
  .$+($bytes(%c.httpd.id,b),$chr(9),total number of connections):httpd about
  .-
  .$+($bytes($sock(httpd.client.*,0),b),$chr(9),open connections):httpd about
  .-
  .$+($bytes($sock(httpd.client.*.method.*,0),b),$chr(9),waiting to receive method from):httpd about
  .$+($bytes($sock(httpd.client.*.header.*,0),b),$chr(9),waiting to receive header from):httpd about
  .$+($bytes($sock(httpd.client.*.post.*,0),b),$chr(9),waiting to receive post from):httpd about
  .$+($bytes($sock(httpd.client.*.multiheader.*,0),b),$chr(9),waiting to receive multipart header from):httpd about
  .$+($bytes($sock(httpd.client.*.multifile.*,0),b),$chr(9),waiting to receive multipart file from):httpd about
  .$+($bytes($sock(httpd.client.*.multidata.*,0),b),$chr(9),waiting to receive multipart data from):httpd about
  .$+($bytes($sock(httpd.client.*.default.*,0),b),$chr(9),processing):httpd about
  .$+($bytes($sock(httpd.client.*.data.*,0),b),$chr(9),sending data to):httpd about
  .$+($bytes($sock(httpd.client.*.file.*,0),b),$chr(9),sending a file to):httpd about
  .$+($bytes($sock(httpd.client.*.error.*,0),b),$chr(9),processing an error):httpd about
  -
  $+(Link,$chr(9),$httpd.link):url $httpd.link
  -
  Clear the window:clear @HTTPd
}

on *:close:@HTTPd:if ($hget(httpd.config,Logging)) .timer -iom 1 0 httpd.logwindow

alias httpd.birth return $asctime(%c.httpd.birth,yyyy-mm-dd HH:nn:ss)

alias -l httpd.sockerr {
  if ($window(@HTTPd)) echo 7 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),SOCKERR,$chr(9),$sockname,$chr(9),$1- ( $+ $sockerr $+ ): $sock($sockname).wsmsg)
  httpd.killclient
}

alias -l httpd.critical {
  if ($window(@HTTPd)) echo 4 -mi26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),CRITICAL,$chr(9),$sockname,$chr(9),$1 $+ : $error)
  reseterror
  httpd.killclient
}

#httpd.localareanetwork off
on *:socklisten:httpd.listen: {
  if ($sockerr) httpd.sockerr LAN Listen
  else {
    sockaccept httpd.accept
    if (127.?*.?*.?* iswm $sock(httpd.accept).ip) || (192.168.?*.?* iswm $v2) httpd.accept $v2
    else sockclose httpd.accept
  }
  :error
  if ($error) httpd.critical Listen
}
#httpd.localareanetwork end

#httpd.wideareanetwork on
on *:socklisten:httpd.listen: {
  if ($sockerr) httpd.sockerr WAN Listen
  else {
    sockaccept httpd.accept
    tokenize 1 $sock(httpd.accept).ip
    if (!$hfind(httpd.bans,$1,1,W)) && ($sock(httpd.client.*,0) < $hget(httpd.config,MaximumConnections)) && ($sock(httpd.client.?*.????*. $+ $1,0) < $hget(httpd.config,MaximumConnectionsPerIP)) httpd.accept $1
    else sockclose httpd.accept
  }
  :error
  if ($error) httpd.critical Listen
}
#httpd.wideareanetwork end

alias -l httpd.accept {
  inc %c.httpd.id
  tokenize 32 $+(httpd.client.,%c.httpd.id,.method.,$1) $1
  sockrename httpd.accept $1
  sockmark $1 $hget(httpd.config,MaximumHeaderSize)
  if ($window(@HTTPd)) echo 9 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),CONNECTION,$chr(9),$1,$chr(9),$iif($hget(geo),$geolocation($2)))
}

on *:sockread:httpd.client.*.method.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Method
  else {
    sockread %c.httpd.temp
    if ($sockbr > 8192) $httpd.error(414,Request-URI Too Long)
    elseif ($sock($sockname).rcvd >= $sock($sockname).mark) $httpd.error(431,Request Header Fields Too Large)
    else httpd.method %c.httpd.temp
  }
  :error
  if ($error) httpd.critical Method
}

alias -l httpd.method {
  if (HTTP/*.* !iswm $3) || ($4 != $null) $httpd.error(400,Bad Request,Malformed method ( $+ $bytes($sockbr).suf $+ ): $1-)
  elseif (!$istok($hget(httpd.config,AllowedHTTPMethods),$1,32)) $httpd.error(405,Method Not Allowed,Method ( $+ $bytes($sockbr).suf $+ ): $1-)
  else {
    hmake %c.httpd.name 5
    hadd %c.httpd.name $1-3
    sockrename $sockname $puttok($sockname,header,4,46)
    httpd.readheader
  }
}

on *:sockread:httpd.client.*.header.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Header
  else httpd.readheader
  :error
  if ($error) httpd.critical Header
}

alias -l httpd.readheader {
  sockread %c.httpd.temp
  while ($sockbr > 2) {
    if ($v1 > 8192) $httpd.error(431,Request Header Fields Too Large,$bytes($v1).suf)
    elseif (*?: ?* iswm %c.httpd.temp) hadd %c.httpd.name %c.httpd.temp
    else $httpd.error(400,Bad Request,Malformed header field ( $+ $bytes($sockbr).suf $+ ): %c.httpd.temp)
    sockread %c.httpd.temp
  }
  if ($sock($sockname).rcvd >= $sock($sockname).mark) $httpd.error(431,Request Header Fields Too Large)
  elseif ($sockbr == 2) httpd.headerend
}

alias -l httpd.headerend {
  if ($hget(%c.httpd.name,get)) httpd.process $v1
  elseif ($hget(%c.httpd.name,post)) httpd.postpreparation $hget(%c.httpd.name,Content-Length:)
  elseif ($hget(%c.httpd.name,head)) {
    hadd %c.httpd.name httpd.dataonly 1
    httpd.process $v1
  }
  elseif ($hget(%c.httpd.name,options)) httpd.optionsheader
  else $httpd.softerror(405,Method Not Allowed)
}

alias -l httpd.optionsheader {
  sockwrite -n $sockname HTTP/1.1 204 No Content
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Allow: $replacex($hget(httpd.config,AllowedHTTPMethods),$chr(32),$chr(44) $+ $chr(32))
  sockwrite $sockname $crlf
  sockrename $sockname $puttok($sockname,data,4,46)
}

alias -l httpd.postpreparation {
  sockmark $sockname $calc($1 +$sock($sockname).rcvd)
  if ($1 !isnum 0-) $httpd.error(411,Length Required)
  elseif (multipart/form-data;* iswm $hget(%c.httpd.name,Content-Type:)) httpd.multipartinit $1
  else httpd.postinit $1
}

alias -l httpd.multipartinit {
  set -l %folder $utfdecode($regsubex($gettok($gettok($hget(%c.httpd.name,post),1,32),1,63),/%(\w\w)/g,$chr($base(\t,16,10))))
  if (!$hget(httpd.config,AllowMultipartFormData)) $httpd.error(403,Forbidden,Multipart/form-data not allowed)
  elseif (!$hget(httpd.config,AllowmSLPages)) $httpd.error(403,Forbidden,Multipart/form-data: mSL pages are disallowed)
  elseif ($1 > $hget(httpd.config,MaximumMultipartSize)) $httpd.error(413,Payload Too Large,Multipart/form-data)
  elseif (!$isalias(httpd.upload. $+ %folder)) $httpd.error(403,Forbidden,Multipart/form-data not authorized for: $qt(%folder))
  elseif ($gettok($wildtok($hget(%c.httpd.name,Content-Type:),boundary=?*,1,32),2,61)) {
    hadd %c.httpd.name httpd.boundary $v1
    sockrename $sockname $puttok($sockname,multiheader,4,46)
    if ($sock($sockname).rq) {
      sockread $v1 &data
      httpd.multipartheader
    }
  }
  else $httpd.error(400,Bad Request,Missing boundary)
}

alias -l httpd.postinit {
  set -l %folder $utfdecode($regsubex($gettok($gettok($hget(%c.httpd.name,post),1,32),1,63),/%(\w\w)/g,$chr($base(\t,16,10))))
  if ($1 > $hget(httpd.config,MaximumBodySize)) $httpd.error(413,Payload Too Large,POST body)
  elseif (!$hget(httpd.config,AllowmSLPages)) $httpd.error(403,Forbidden,POST with a body: mSL pages are disallowed)
  elseif (!$isalias(httpd.post. $+ %folder)) $httpd.error(403,Forbidden,POST bodies not authorized for: $qt(%folder))
  else {
    sockrename $sockname $puttok($sockname,post,4,46)
    if ($sock($sockname).rq) httpd.post
  }
}

on *:sockread:httpd.client.*.post.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Post
  else httpd.post
  :error
  if ($error) httpd.critical Post
}

alias -l httpd.post {
  sockread $sock($sockname).rq &read $hget(%c.httpd.name,httpd.postdata,&stored)
  bcopy &stored -1 &read 1 -1
  hadd -b %c.httpd.name httpd.postdata &stored
  if ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.finishpost
}

alias -l httpd.finishpost {
  if ($hget(%c.httpd.name,httpd.postdata,&post)) {
    breplace &post 61 32 43 1
    set -l %x 1
    httpd.additem $gettok($bvar(&post,1,8192).text,1,38)
    while ($bfind(&post,%x,&).textcs) { %x = $v1 + 1 | httpd.additem $gettok($bvar(&post,%x,8192).text,1,38) }
    httpd.process $hget(%c.httpd.name,post)
  }
}

alias -l httpd.additem {
  if ($replacex($utfdecode($regsubex($gettok($2,1,38),/%(\w\w)/g,$chr($base(\t,16,10)))),$chr(32),$chr(1)) != $null) {
    bset -tc &string 1 $v1
    breplace &string 1 32
    hadd -b %c.httpd.name item. $+ $1 &string
  }
  else hadd %c.httpd.name item. $+ $1
}

on *:sockread:httpd.client.*.multiheader.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Multipart header
  elseif ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.postprocess
  else {
    sockread $sock($sockname).rq &read $hget(%c.httpd.name,httpd.multiheader,&data)
    bcopy &data -1 &read 1 -1
    httpd.multipartheader
  }
  :error
  if ($error) httpd.critical Multipart header
}

alias -l httpd.multipartheader {
  if ($hget(%c.httpd.name,httpd.multipartitems) >= $hget(httpd.config,MaximumMultiPartItems)) $httpd.error(400,Bad Request,Too many items in multipart request)
  elseif ($bfind(&data,1,%c.httpd.multicrlf).textcs) {
    set -l %end $v1 + 4
    bcopy -c &header 1 &data 1 $v1
    hdel %c.httpd.name httpd.leftover
    if ($bfind(&header,1,%c.httpd.multifile).text) {
      set -l %filename $replacex($gettok($bvar(&header,$v1,4096).text,2,34),$chr(124),_,\,_,/,_,:,_,*,_,?,_,<,_,>,_,",_,$chr(32),_)
      if ($bfind(&header,1,%c.httpd.name).text) hadd %c.httpd.name item. $+ $gettok($bvar(&header,$v1,4096).text,2,34) %filename
      set -l %sha1 $sha1($sockname $sock($sockname).rcvd)
      hinc %c.httpd.name httpd.multipartitems
      .fopen -o %c.httpd.name $qt($hget(httpd.config,CacheDirectory) $+ %sha1)
      hadd %c.httpd.name httpd.uploadedfiles $addtok($hget(%c.httpd.name,httpd.uploadedfiles),%sha1,32)
      hadd %c.httpd.name %sha1 %filename $qt($hget(httpd.config,CacheDirectory) $+ %sha1)
      sockrename $sockname $puttok($sockname,multifile,4,46)
      if ($bvar(&data,0) > %end) {
        bcopy -c &data 1 &data %end -1
        httpd.multipartfile
      }
    }
    elseif ($bfind(&header,1,%c.httpd.multiname).text) {
      hadd %c.httpd.name httpd.name item. $+ $gettok($gettok($bvar(&header,$v1,500).text,2,34),1,32)
      sockrename $sockname $puttok($sockname,multidata,4,46)
      if ($bvar(&data,0) > %end) {
        bcopy -c &data 1 &data %end -1
        httpd.multipartdata
      }
    }
    else $httpd.error(400,Bad Request,Missing item/file name)
  }
  else hadd -b %c.httpd.name httpd.multiheader &data
}

on *:sockread:httpd.client.*.multifile.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Multipart file
  elseif ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.postprocess
  else {
    sockread $sock($sockname).rq &data
    httpd.multipartfile
  }
  :error
  if ($error) httpd.critical Multipart file
}

alias -l httpd.multipartfile {
  if ($bfind(&data,1,$hget(%c.httpd.name,httpd.boundary)).textcs) httpd.multipartfileend
  else .fwrite -b %c.httpd.name &data
}

alias -l httpd.multipartfileend {
  sockrename $sockname $puttok($sockname,multiheader,4,46)
  bcopy -c &write 1 &data 1 $calc($v1 -5)
  bcopy -c &data 1 &data $v1 -1
  .fwrite -b %c.httpd.name &write
  .fclose %c.httpd.name
  if ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.postprocess
  else httpd.multipartheader
}

on *:sockread:httpd.client.*.multidata.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Multipart data
  elseif ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.postprocess
  else {
    sockread $sock($sockname).rq &read $hget(%c.httpd.name,httpd.temp,&data)
    bcopy &data -1 &read 1 -1
    httpd.multipartdata
  }
  :error
  if ($error) httpd.critical Multipart data
}

alias -l httpd.multipartdata {
  if ($bfind(&data,1,$hget(%c.httpd.name,httpd.boundary)).textcs) httpd.multipartdataend
  else hadd -b %c.httpd.name httpd.temp &data
}

alias -l httpd.multipartdataend {
  sockrename $sockname $puttok($sockname,multiheader,4,46)
  bcopy -c &store 1 &data 1 $calc($v1 -5)
  bcopy -c &data 1 &data $v1 -1
  hdel %c.httpd.name httpd.temp
  hadd -b %c.httpd.name $hget(%c.httpd.name,httpd.name) &store
  if ($sock($sockname).rcvd >= $sock($sockname).mark) httpd.postprocess
  else httpd.multipartheader
}

alias -l httpd.postprocess httpd.process $hget(%c.httpd.name,post)

alias -l httpd.process {
  sockrename $sockname %c.httpd.name
  tokenize 63 $1
  %c.httpd.url = $utfdecode($regsubex($1,/%(\w\w)/g,$chr($base(\t,16,10))))
  %c.httpd.folder = $gettok(%c.httpd.url,1,47)
  if ($hget(httpd.virtualfolders,%c.httpd.folder)) %c.httpd.path = $replacex($v1 $+ $gettok(%c.httpd.url,2-,47),/,\)
  else %c.httpd.path = $replacex($hget(httpd.config,RootDirectory) $+ $mid(%c.httpd.url,2-),/,\)
  if (*\ iswm %c.httpd.path) %c.httpd.file = %c.httpd.path $+ index.html
  else %c.httpd.file = %c.httpd.path
  if ($window(@HTTPd)) echo 3 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),REQUEST,$chr(9),$sockname,$chr(9),%c.httpd.url,$chr(9),$hget($sockname,User-Agent:))
  tokenize 38 $replacex($2,=,$chr(32),+,$chr(1))
  httpd.additem $*
  if ($hget(httpd.passwordfolders,%c.httpd.folder)) && (basic $v1 != $hget(%c.httpd.name,Authorization:)) httpd.authenticate
  elseif ($hget(httpd.config,icon. $+ $gettok(%c.httpd.path,-1,92),&h)) httpd.cachedicon
  elseif ($hget(httpd.config,AllowFileAccess)) && ($isfile(%c.httpd.file)) httpd.file
  elseif ($hget(httpd.config,AllowmSLPages)) && ($isalias(httpd.page. $+ %c.httpd.url)) httpd.page. $+ $gettok(%c.httpd.url,1,32)
  elseif ($hget(httpd.config,AllowDirectoryAccess)) && ($isdir(%c.httpd.path)) httpd.directory
  else $httpd.softerror(404,Not Found,%c.httpd.url)
}

alias -l httpd.authenticate {
  hadd %c.httpd.name Response 401 Unauthorized
  hadd %c.httpd.name WWW-Authenticate basic realm="Login required", charset="UTF-8"
  bset -t &h -1 $hget(httpd.config,401)
  httpd.senddata
}

alias -l httpd.directory {
  if (*/ iswm %c.httpd.url) {
    %c.httpd.modified = $calc($file(%c.httpd.path).mtime $timezone)
    if ($ctime($hget(%c.httpd.name,If-Modified-Since:)) == %c.httpd.modified) httpd.notmodified $v2
    else {
      hadd %c.httpd.name Response 200 OK
      hadd %c.httpd.name Last-Modified $asctime(%c.httpd.modified,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
      tokenize 3 $replacex(%c.httpd.url,$chr(32),)
      bset -t &h -1 $+(<!DOCTYPE html><html><head><title>Index of $1,</title><style>body{white-space:pre}table{white-space:pre;text-align:left}table tr.item:hover{background-color:#D7D7D7}table td{padding-right:25px}table td.right{text-align:right}</style></head><body><h2>Index of $1,</h2><table><tr><th></th><th>File</th><th>Size</th><th>Modified</th></tr><tr><th colspan="4"><hr width="100%"></th></tr>)
      noop $finddir(%c.httpd.path,*,0,1,d $replacex($parms,$chr(32),)) $findfile(%c.httpd.path,*,0,1,f $replacex($parms,$chr(32),))
      if ($finddirn $findfilen == 0 0) bset -t &h -1 <tr><th></th><td>No folders or files.</td></tr>
      if (%c.httpd.url != /) bset -t &h -1 <tr><th colspan="4"><hr width="100%"></th></tr></table><img src="directoryback.png"> <a href="..">Parent folder</a></body></html>
      else bset -t &h -1 <tr><th colspan="4"><hr width="100%"></th></tr></table></body></html>
      breplace &h 1 32
      httpd.senddata
    }
  }
  else httpd.movedpermanently
}

alias -l d bset -t &h -1 $+(<tr class="item"><th><img src="directoryfolder.png"></th><td><a href=",$regsubex($gettok($1,-1,92),/([^-.~\w])/g,% $+ $base($asc(\t),10,16)),/">,$gettok($1,-1,92),/</a></td><td class="right">-</td><td>,$asctime($calc($file($replacex($1,,$chr(32))).mtime $timezone),yyyy-mm-dd HH:nn:ss) UTC</td></tr>)

alias -l f bset -t &h -1 $+(<tr class="item"><th><img src="directoryfile.png"></th><td><a href=",$regsubex($nopath($1),/([^-.~\w])/g,% $+ $base($asc(\t),10,16)),">,$nopath($1),</a></td><td class="right">,$bytes($file($replacex($1,,$chr(32))).size).suf,</td><td>,$asctime($calc($file($replacex($1,,$chr(32))).mtime $timezone),yyyy-mm-dd HH:nn:ss) UTC</td></tr>)

alias -l httpd.movedpermanently {
  hadd %c.httpd.name Response 301 Moved Permanently
  hadd %c.httpd.name Location %c.httpd.url $+ /
  bset -t &h -1 $hget(httpd.config,301)
  httpd.senddata
}

alias -l httpd.cachedicon {
  if ($ctime($hget(%c.httpd.name,If-Modified-Since:)) == %c.httpd.birth) httpd.notmodified $v2
  else {
    sockwrite -n $sockname HTTP/1.1 200 OK
    sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
    sockwrite -n $sockname Last-Modified: $asctime(%c.httpd.birth,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
    sockwrite -n $sockname Cache-Control: private, max-age=3600
    sockwrite -n $sockname Content-Length: $decode(&h,bm)
    sockwrite -n $sockname Content-Type: image/png
    sockwrite $sockname $crlf
    if (!$hget(%c.httpd.name,httpd.dataonly)) sockwrite $sockname &h
    sockrename $sockname $puttok($sockname,data,4,46)
  }
}

alias -l httpd.notmodified {
  sockwrite -n $sockname HTTP/1.1 304 Not Modified
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Last-Modified: $asctime($1,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Cache-Control: private, max-age=3600
  sockwrite $sockname $crlf
  sockrename $sockname $puttok($sockname,data,4,46)
}

alias -l httpd.senddata {
  if ($hget(%c.httpd.name,Response)) sockwrite -n $sockname HTTP/1.1 $v1
  else sockwrite -n $sockname HTTP/1.1 200 OK
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  if ($hget(%c.httpd.name,Last-Modified)) {
    sockwrite -n $sockname Last-Modified: $v1
    sockwrite -n $sockname Cache-Control: private, max-age=3600
  }
  if ($hget(%c.httpd.name,Content-Type)) sockwrite -n $sockname Content-Type: $v1
  else sockwrite -n $sockname Content-Type: text/html; charset=utf-8
  if ($hget(%c.httpd.name,Location)) sockwrite -n $sockname Location: $v1
  if ($hget(%c.httpd.name,WWW-Authenticate)) sockwrite -n $sockname WWW-Authenticate: $v1
  if ($hget(httpd.config,CompressionStatus)) && ($bvar(&h,0) isnum 64- $hget(httpd.config,CompressionMaximumSize)) && ((gzip isin $hget(%c.httpd.name,Accept-Encoding:)) || (deflate isin $v2)) {
    set -l %type $v1
    if (($v1 == gzip) && ($compress(&h,bm3l $+ $hget(httpd.config,CompressionLevel)))) || ($compress(&h,bm2l $+ $hget(httpd.config,CompressionLevel))) sockwrite -n $sockname Content-Encoding: %type
  }
  sockwrite -n $sockname Content-Length: $bvar(&h,0)
  sockwrite $sockname $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) {
    if ($bvar(&h,0) > $calc($hget(httpd.config,MaximumChunkSize)-$sock($sockname).sq)) {
      sockwrite -b $sockname $v2 &h
      bcopy &s 1 &h $calc(1+$v2) -1
      hadd -b %c.httpd.name httpd.remainingdata &s
    }
    elseif ($bvar(&h,0) isnum 1-) sockwrite $sockname &h
  }
  sockrename $sockname $puttok($sockname,data,4,46)
}

on *:sockwrite:httpd.client.*.data.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr Data
  elseif (!$sock($sockname).sq) {
    if ($hget(%c.httpd.name,httpd.remainingdata,&data)) httpd.dataqueue
    else httpd.writeend
  }
  :error
  if ($error) httpd.critical Data
}

alias -l httpd.dataqueue {
  if ($v1 > $hget(httpd.config,MaximumChunkSize)) {
    sockwrite -b $sockname $v2 &data
    bcopy &remaining 1 &data $calc(1+$v2) -1
    hadd -b %c.httpd.name httpd.remainingdata &remaining
  }
  else {
    sockwrite $sockname &data
    hdel %c.httpd.name httpd.remainingdata
  }
}

alias -l httpd.writeend {
  if ($fopen(%c.httpd.name)) .fclose %c.httpd.name
  tokenize 32 $hget(%c.httpd.name,httpd.uploadedfiles)
  httpd.remove $*
  if ($hget(%c.httpd.name,connection:) == keep-alive) {
    hfree -w %c.httpd.name
    sockmark $sockname $calc($hget(httpd.config,MaximumHeaderSize)+$sock($sockname).rcvd)
    sockrename $sockname $puttok($sockname,method,4,46)
  }
  else {
    if ($window(@HTTPd)) echo 10 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),DISCONNECT,$chr(9),$sockname,$chr(9),Connection closed by server)
    httpd.killclient
  }
}

alias -l httpd.file {
  %c.httpd.filepath = $qt($shortfn(%c.httpd.file))
  %c.httpd.modified = $calc($file(%c.httpd.file).mtime $timezone)
  if ($ctime($hget(%c.httpd.name,If-Modified-Since:)) == %c.httpd.modified) httpd.notmodified $v2
  else httpd.filecontinue
}

alias -l httpd.filecontinue {
  %c.httpd.filesize = $file(%c.httpd.filepath).size
  %c.httpd.fileextension = $gettok(%c.httpd.file,-1,46)
  %c.httpd.startposition = 0
  %c.httpd.endposition = %c.httpd.filesize
  if ($gettok($gettok($hget(%c.httpd.name,Range:),2,61),1,44)) httpd.byterange
  else unset %c.httpd.byterange
  if (%c.httpd.filesize isnum 64- $hget(httpd.config,CompressionMaximumSize)) && ($hget(httpd.config,CompressionStatus)) && ($istok($hget(httpd.config,CompressionFileTypes),%c.httpd.fileextension,32)) && ((gzip isin $hget(%c.httpd.name,Accept-Encoding:)) || (deflate isin $v2)) httpd.sendcompressed $v1
  else httpd.sendfile
}

alias -l httpd.byterange {
  tokenize 45 $v1
  if ($1 isnum 0- %c.httpd.filesize) %c.httpd.startposition = $v1
  if ($2 isnum %c.httpd.startposition - %c.httpd.filesize) %c.httpd.endposition = $v1
  else %c.httpd.endposition = %c.httpd.filesize
  %c.httpd.byterange = $+(%c.httpd.startposition,-,$calc(%c.httpd.endposition -1),/,%c.httpd.filesize)
  %c.httpd.filesize = %c.httpd.endposition - %c.httpd.startposition
}

alias -l httpd.sendcompressed {
  bread %c.httpd.filepath %c.httpd.startposition %c.httpd.filesize &data
  if (%c.httpd.byterange) {
    sockwrite -n $sockname HTTP/1.1 206 Partial Content
    sockwrite -n $sockname Content-Range: bytes %c.httpd.byterange
  }
  else sockwrite -n $sockname HTTP/1.1 200 OK
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Last-Modified: $asctime(%c.httpd.modified,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Cache-Control: private, max-age=3600
  if (($1 == gzip) && ($compress(&data,bm3l $+ $hget(httpd.config,CompressionLevel)))) || ($compress(&data,bm2l $+ $hget(httpd.config,CompressionLevel))) sockwrite -n $sockname Content-Encoding: $1
  sockwrite -n $sockname Content-Length: $bvar(&data,0)
  if ($hget(httpd.mime,%c.httpd.fileextension)) sockwrite -n $sockname Content-Type: $v1
  sockwrite -n $sockname Accept-Ranges: bytes
  sockwrite $sockname $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) {
    if ($bvar(&data,0) > $calc($hget(httpd.config,MaximumChunkSize)-$sock($sockname).sq)) {
      sockwrite -b $sockname $v2 &data
      bcopy &remaining 1 &data $calc(1+$v2) -1
      hadd -b %c.httpd.name httpd.remainingdata &remaining
    }
    elseif ($bvar(&data,0) isnum 1-) sockwrite $sockname &data
  }
  sockrename $sockname $puttok($sockname,data,4,46)
}

alias -l httpd.sendfile {
  if (%c.httpd.byterange) {
    sockwrite -n $sockname HTTP/1.1 206 Partial Content
    sockwrite -n $sockname Content-Range: bytes %c.httpd.byterange
  }
  else sockwrite -n $sockname HTTP/1.1 200 OK
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Last-Modified: $asctime(%c.httpd.modified,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Cache-Control: private, max-age=3600
  sockwrite -n $sockname Content-Length: %c.httpd.filesize
  if ($hget(httpd.mime,%c.httpd.fileextension)) sockwrite -n $sockname Content-Type: $v1
  sockwrite -n $sockname Accept-Ranges: bytes
  sockwrite $sockname $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) {
    if (%c.httpd.filesize > $calc($hget(httpd.config,MaximumChunkSize)-$sock($sockname).sq)) {
      tokenize 32 $v2
      if ($fopen(%c.httpd.name)) .fclose %c.httpd.name
      .fopen %c.httpd.name %c.httpd.filepath
      .fseek %c.httpd.name %c.httpd.startposition
      sockwrite -b $sockname $fread(%c.httpd.name,$1,&data) &data
      sockmark $sockname %c.httpd.endposition
    }
    elseif (%c.httpd.filesize isnum 1-) {
      bread %c.httpd.filepath %c.httpd.startposition %c.httpd.filesize &data
      sockwrite $sockname &data
      sockmark $sockname
    }
  }
  sockrename $sockname $puttok($sockname,file,4,46)
}

on *:sockwrite:httpd.client.*.file.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($sockerr) httpd.sockerr File
  elseif (!$sock($sockname).sq) {
    if ($fopen(%c.httpd.name).pos < $sock($sockname).mark) httpd.filequeue
    else httpd.writeend
  }
  :error
  if ($error) httpd.critical File
}

alias -l httpd.filequeue sockwrite $sockname &data $calc($fread(%c.httpd.name,$hget(httpd.config,MaximumChunkSize),&data)+$v1)

on *:sockclose:httpd.client.*: {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($window(@HTTPd)) echo 10 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),DISCONNECT,$chr(9),$sockname,$chr(9),Connection closed by client)
  httpd.killclient
}

alias -l httpd.killclient {
  sockclose $sockname
  if ($fopen(%c.httpd.name)) .fclose %c.httpd.name
  tokenize 32 $hget(%c.httpd.name,httpd.uploadedfiles)
  httpd.remove $*
  hfree -w %c.httpd.name
}

alias -l httpd.remove .remove $qt($hget(httpd.config,CacheDirectory) $+ $1)

alias -l httpd.error {
  if ($window(@HTTPd)) echo 8 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),ERROR,$chr(9),$sockname,$chr(9),$1-2,$chr(9),$3)
  if ($fopen(%c.httpd.name)) .fclose %c.httpd.name
  httpd.removefiles $hget(%c.httpd.name,httpd.uploadedfiles)
  sockrename $sockname $puttok($sockname,error,4,46)
  sockwrite -n $sockname HTTP/1.1 $1-2
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Content-Type: text/html; charset=utf-8
  sockwrite -n $sockname Connection: close
  if ($hget(httpd.config,$1,&e)) && ($hget(httpd.config,CompressionStatus)) && ($bvar(&e,0) isnum 64- $hget(httpd.config,CompressionMaximumSize)) && ((gzip isin $hget(%c.httpd.name,Accept-Encoding:)) || (deflate isin $v2)) {
    set -l %type $v1
    if (($v1 == gzip) && ($compress(&e,bm3l $+ $hget(httpd.config,CompressionLevel)))) || ($compress(&e,bm2l $+ $hget(httpd.config,CompressionLevel))) sockwrite -n $sockname Content-Encoding: %type
  }
  sockwrite -n $sockname Content-Length: $bvar(&e,0)
  sockwrite $sockname $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) sockwrite $sockname &e
  hfree -w %c.httpd.name
  halt
}

alias -l httpd.softerror {
  if ($window(@HTTPd)) echo 8 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),WARNING,$chr(9),$sockname,$chr(9),$1-2,$chr(9),$3)
  if ($fopen(%c.httpd.name)) .fclose %c.httpd.name
  httpd.removefiles $hget(%c.httpd.name,httpd.uploadedfiles)
  sockrename $sockname $puttok($sockname,data,4,46)
  sockwrite -n $sockname HTTP/1.1 $1-2
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  sockwrite -n $sockname Content-Type: text/html; charset=utf-8
  if ($hget(httpd.config,$1,&e)) && ($hget(httpd.config,CompressionStatus)) && ($bvar(&e,0) isnum 64- $hget(httpd.config,CompressionMaximumSize)) && ((gzip isin $hget(%c.httpd.name,Accept-Encoding:)) || (deflate isin $v2)) {
    set -l %type $v1
    if (($v1 == gzip) && ($compress(&e,bm3l $+ $hget(httpd.config,CompressionLevel)))) || ($compress(&e,bm2l $+ $hget(httpd.config,CompressionLevel))) sockwrite -n $sockname Content-Encoding: %type
  }
  sockwrite -n $sockname Content-Length: $bvar(&e,0)
  sockwrite $sockname $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) sockwrite $sockname &e
}

alias -l httpd.removefiles httpd.remove $*

on *:sockwrite:httpd.client.*.error.*:if (!$sock($sockname).sq) sockclose $sockname

alias -l httpd.maintenance {
  if ($1) {
    if ($sock($1).ls > $hget(httpd.config,KeepAliveTime)) && ($sock($1).lr > $v2) httpd.keepalive $1
    else inc %c.httpd.sockindex
  }
  else %c.httpd.sockindex = 1
  if ($2) {
    if (httpd.client.?* iswm $2) && (!$sock($gettok($2,1-3,46) $+ .*)) httpd.abandonedhash $2
    else inc %c.httpd.hashindex
  }
  else %c.httpd.hashindex = 1
}

alias -l httpd.keepalive {
  if ($window(@HTTPd)) echo 6 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),DISCONNECT,$chr(9),$1,$chr(9),Idle exceeds $hget(httpd.config,KeepAliveTime) seconds)
  httpd.kill $1
}

alias -l httpd.abandonedhash {
  set -l %hash $1
  if ($window(@HTTPd)) echo 6 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),MAINTENANCE,$chr(9),$1,$chr(9),Abandoned hash table)
  sockclose $gettok($1,1-3,46) $+ .*
  if ($fopen($1)) .fclose $1
  tokenize 32 $hget($1,httpd.uploadedfiles)
  httpd.remove $*
  hfree -w %hash
}

alias -l httpd.kill {
  set -l %hashtable $puttok($1,default,4,46)
  sockclose $1
  if ($fopen(%hashtable)) .fclose %hashtable
  tokenize 32 $hget(%hashtable,httpd.uploadedfiles)
  httpd.remove $*
  hfree -w %hashtable
}

alias httpd.send {
  %c.httpd.name = $puttok($sockname,default,4,46)
  if ($hget(%c.httpd.name,Response)) sockwrite -n $1 HTTP/1.1 $v1
  else sockwrite -n $1 HTTP/1.1 200 OK
  sockwrite -n $1 Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  if ($hget(%c.httpd.name,Last-Modified)) {
    sockwrite -n $1 Last-Modified: $v1
    sockwrite -n $1 Cache-Control: private, max-age=3600
  }
  if ($hget(%c.httpd.name,Content-Type)) sockwrite -n $1 Content-Type: $v1
  else sockwrite -n $1 Content-Type: text/html; charset=utf-8
  if ($hget(%c.httpd.name,Location)) sockwrite -n $1 Location: $v1
  if ($hget(%c.httpd.name,WWW-Authenticate)) sockwrite -n $1 WWW-Authenticate: $v1
  if ($hget(%c.httpd.name,Refresh)) sockwrite -n $1 Refresh: $v1
  if ($hget(%c.httpd.name,Set-Cookie)) sockwrite -n $1 Set-Cookie: $v1
  if ($hget(httpd.config,CompressionStatus)) && ($bvar(&h,0) isnum 64- $hget(httpd.config,CompressionMaximumSize)) && ((gzip isin $hget(%c.httpd.name,Accept-Encoding:)) || (deflate isin $v2)) {
    set -l %type $v1
    if (($v1 == gzip) && ($compress(&h,bm3l $+ $hget(httpd.config,CompressionLevel)))) || ($compress(&h,bm2l $+ $hget(httpd.config,CompressionLevel))) sockwrite -n $sockname Content-Encoding: %type
  }
  sockwrite -n $1 Content-Length: $bvar(&h,0)
  sockwrite $1 $crlf
  if (!$hget(%c.httpd.name,httpd.dataonly)) {
    if ($bvar(&h,0) > $calc($hget(httpd.config,MaximumChunkSize)-$sock($1).sq)) {
      sockwrite -b $1 $v2 &h
      bcopy &s 1 &h $calc(1+$v2) -1
      hadd -b %c.httpd.name httpd.remainingdata &s
    }
    elseif ($bvar(&h,0) isnum 1-) sockwrite $1 &h
  }
  sockrename $1 $puttok($1,data,4,46)
}

alias httpd.chunkedheader {
  sockwrite -n $sockname HTTP/1.1 200 OK
  sockwrite -n $sockname Date: $asctime($gmt,ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT
  if ($hget(%c.httpd.name,Content-Type)) sockwrite -n $sockname Content-Type: $v1
  else sockwrite -n $sockname Content-Type: text/html; charset=utf-8
  sockwrite -n $sockname Transfer-Encoding: chunked
  if ($hget(%c.httpd.name,Set-Cookie)) sockwrite -n $sockname Set-Cookie: $v1
  sockwrite $sockname $crlf
  if ($hget(%c.httpd.name,httpd.dataonly)) {
    sockrename $sockname $puttok($sockname,data,4,46)
    return 0
  }
  else return 1
}

alias httpd.sendchunked {
  if ($hget($1,httpd.remainingdata,&chunked)) {
    bcopy &chunked -1 &h 1 -1
    hadd -b $1 httpd.remainingdata &chunked
  }
  else {
    if ($bvar(&h,0) > $calc($hget(httpd.config,MaximumChunkSize)-$sock($1).sq)) {
      sockwrite -n $1 $base($v2,10,16)
      sockwrite -b $1 $v2 &h
      sockwrite $1 $crlf
      bcopy &s 1 &h $calc(1+$v2) -1
      hadd -b $1 httpd.remainingdata &s
    }
    else {
      sockwrite -n $1 $base($bvar(&h,0),10,16)
      sockwrite $1 &h
      sockwrite $1 $crlf
    }
  }
  bunset &h &chunked
}

on *:sockwrite:httpd.client.*.default.*: {
  if ($sockerr) httpd.sockerr Chunked
  elseif (!$sock($sockname).sq) {
    if ($hget($sockname,httpd.remainingdata,&data)) httpd.chunkqueue
    elseif ($hget($sockname,httpd.chunkend)) httpd.chunkend $sockname
  }
  :error
  if ($error) httpd.critical Chunked
}

alias -l httpd.chunkqueue {
  if ($v1 > $hget(httpd.config,MaximumChunkSize)) {
    sockwrite -n $sockname $base($v2,10,16)
    sockwrite -b $sockname $v2 &data
    sockwrite $sockname $crlf
    bcopy &remaining 1 &data $calc(1+$v2) -1
    hadd -b $sockname httpd.remainingdata &remaining
  }
  else {
    sockwrite -n $sockname $base($bvar(&data,0),10,16)
    sockwrite $sockname &data
    sockwrite $sockname $crlf
    hdel $sockname httpd.remainingdata
  }
}

alias -l httpd.chunkend {
  set -l %sockname $1
  if ($fopen(%sockname)) .fclose %sockname
  tokenize 32 $hget(%sockname,httpd.uploadedfiles)
  httpd.remove $*
  hfree -w %sockname
  if ($hget(%sockname,connection:) == keep-alive) {
    sockwrite %sockname $+(0,$crlf,$crlf)
    sockmark %sockname $calc($hget(httpd.config,MaximumHeaderSize)+$sock(%sockname).rcvd)
    sockrename %sockname $puttok(%sockname,method,4,46)
  }
  else sockclose %sockname
}

alias httpd.stopchunked {
  hadd $1 httpd.chunkend 1
  if ($hget($1,httpd.remainingdata,&test)) hadd $1 httpd.chunkend 1
  else httpd.chunkend $1
}

alias httpd.resetchunk sockwrite -n $1 0

dialog -l httpd {
  title "HTTPd settings - /httpd"
  icon $scriptdirCube.ico
  size -1 -1 298 217
  option dbu
  list 1, 2 2 70 200, size
  button "Apply", 2, 145 203 50 12, disable default
  button "OK", 3, 195 203 50 12, disable ok
  button "Cancel", 4, 245 203 50 12, cancel
  link "", 5, 3 206 70 8
  box "General settings description", 10, 75 2 220 28
  text "Here you can turn the server on and off, decide whether or not it should start on mIRC startup and change the folder settings.", 11, 79 12 212 15

  box "Status", 100, 75 31 220 79, hide
  check "Enable server", 101, 81 41 45 10, hide
  check "Start server on mIRC startup", 102, 81 51 82 10, hide
  text "Listen port:", 103, 81 63 35 8, hide right
  edit "", 104, 118 62 50 10, hide limit 5 center
  text "The available port range is 40-65545, default being 80.", 105, 119 73 165 8, hide
  text "Bind to IP:", 106, 81 83 35 8, hide right
  edit "", 107, 118 82 50 10, hide limit 15 center
  text "This allows you to bind the server to a specific network adapter. Leave this empty, unless you know what you're doing.", 108, 119 93 165 15, hide
  box "Directories", 109, 75 111 220 65, hide
  text "Root folder:", 110, 81 122 35 8, hide right
  edit "", 111, 118 121 140 10, hide read autohs limit 8192
  button "Browse", 112, 259 121 30 10, hide
  button "Open", 118, 259 131 30 10, hide disable
  text "Depending on permissions, the root folder and all of its contents will be exposed to the internet.", 113, 119 132 137 15, hide
  text "Cache folder:", 114, 81 149 35 8, hide right
  edit "", 115, 118 148 140 10, hide read autohs limit 8192
  button "Browse", 116, 259 148 30 10, hide
  button "Open", 119, 259 158 30 10, hide disable
  text "Temporary files will be stored in the cache folder. Note: cache and root folders should be on the same drive.", 117, 119 159 137 15, hide
  text "Already in use", 120, 169 63 40 8, hide center
  box "Logging", 121, 75 177 220 23, hide
  check "Enable logging", 122, 81 187 45 10, hide
  check "Hide the log window", 123, 141 187 59 10, hide

  box "Permissions", 200, 75 31 220 167, hide
  check "Allow connections from Wide Area Network (internet)", 201, 81 41 189 10, hide
  text "If disallowed, only connections from Local Area Network will be accepted.", 202, 90 51 200 8, hide
  check "Allow file access", 203, 81 61 189 10, hide
  text "If disallowed, clients will not be able to access any files.", 204, 90 71 200 8, hide
  check "Allow directory access", 205, 81 81 189 10, hide
  text "If disallowed, clients will not be able to list files and folders in directories, but can access files with direct links, if file access is allowed.", 206, 90 91 200 15, hide
  check "Allow mSL pages", 207, 81 108 189 10, hide
  text "When allowed, mSL pages will be processed. For more information, look inside the 'HTTPd pages.mrc' script file.", 208, 90 118 200 15, hide
  check "Allow multipart/form-data encoding type", 209, 81 135 189 10, hide
  text "When allowed, mSL pages and accept uploads. For more information, check 'HTTPd pages.mrc' file. Note: this requires POST method.", 210, 90 145 200 15, hide
  text "Allowed HTTP methods:", 211, 81 162 57 8, hide
  check "GET", 212, 90 171 34 10, hide
  check "POST", 213, 126 171 34 10, hide
  check "OPTIONS", 215, 198 171 34 10, hide
  check "HEAD", 214, 162 171 34 10, hide
  text "GET is required for normal function. POST is for submitting information, like multipart/form-data. HEAD and OPTIONS are information requests.", 216, 90 181 200 15, hide

  box "Compression", 300, 75 31 220 103, hide
  check "Enable compression (gzip/deflate)", 301, 81 41 92 10, hide
  text "Maximum size:", 302, 81 53 35 8, hide right
  combo 303, 119 52 50 200, hide size drop
  text "The larger the file the longer it will take to compress. Large files will cause freezes.", 304, 90 64 200 8, hide
  text "File types:", 305, 81 76 35 8, hide right
  edit "", 306, 118 75 172 10, hide autohs limit 8192
  text "Only the listed file types will be compressed. Compression does not benefit all file types, and can in some cases have a negative impact on the size.", 307, 90 86 200 15, hide
  text "Comp. level:", 308, 81 105 35 8, hide right
  combo 309, 119 104 50 200, hide size drop
  text "Higher compression levels offer smaller end results with the expense of CPU time. Higher levels cost more and offer smaller improvements.", 310, 90 116 200 15, hide

  box "Limitations", 400, 75 31 220 168, hide
  text "Connections:", 413, 81 42 35 8, hide right
  combo 414, 119 41 55 200, hide size drop
  text "Per IP:", 415, 177 42 35 8, hide right
  combo 416, 215 41 55 200, hide size drop
  text "The maximum number of simultaneous connections overall, and per IP address.", 417, 90 53 200 8, hide
  text "Chunk size:", 401, 81 65 35 8, hide right
  combo 402, 119 64 85 200, hide size drop
  text "When set between 8193 and 16384 bytes, the maximum upload speed will be between 256 and 512 kB/s. 8192 bytes or less will result in higher speeds.", 403, 90 76 200 15, hide
  text "Keep-Alive:", 404, 81 95 35 8, hide right
  combo 405, 119 94 85 200, hide size drop
  text "Keep-Alive determines the maximum time a client can stay connected without sending or receiving data. High limit allows pipelining, but may clog up the server.", 406, 90 106 200 15, hide
  text "Header size:", 407, 81 125 35 8, hide right
  combo 408, 119 124 85 200, hide size drop
  text "The maximum amount of data a client can send in a header.", 409, 90 136 200 8, hide
  text "POST size:", 410, 81 148 35 8, hide right
  combo 411, 119 147 85 200, hide size drop
  text "The maximum amount of data a client can send in a POST body.", 412, 90 159 200 8, hide
  text "Item limit:", 418, 81 171 35 8, hide right
  combo 419, 119 170 55 200, hide size drop
  text "Maximum size:", 420, 177 171 35 8, hide right
  combo 421, 215 170 55 200, hide size drop
  text "The maximum number of items, and the maximum total size of said items allowed in a single multipart/form-data request.", 422, 90 182 200 15, hide

  box "Icons", 500, 75 31 220 86, hide
  text "favicon.ico", 501, 81 41 40 8, hide right
  button "Browse", 502, 81 51 40 12, hide
  icon 503, 124 41 30 30,  $mircexe, 0, hide noborder
  text "Parent folder", 504, 171 41 40 8, hide right
  button "Browse", 505, 171 51 40 12, hide
  icon 506, 214 41 30 30,  $mircexe, 0, hide noborder
  text "Folder", 507, 81 81 40 8, hide right
  button "Browse", 508, 81 91 40 12, hide
  icon 509, 124 81 30 30,  $mircexe, 0, hide noborder
  text "File", 510, 171 81 40 8, hide right
  button "Browse", 511, 171 91 40 12, hide
  icon 512, 214 81 30 30,  $mircexe, 0, hide noborder

  box "Status codes", 600, 75 31 220 171, hide
  list 601, 79 41 212 157, hide size

  box "MIME types", 700, 75 31 220 171, hide
  list 701, 79 41 170 157, hide sort size extsel
  button "Add", 702, 252 41 37 12, hide
  button "Edit", 703, 252 53 37 12, hide disable
  button "Delete", 704, 252 65 37 12, hide disable
  text "", 705, 250 189 43 8, hide center

  box "Virtual folders", 800, 75 31 220 171, hide
  list 801, 79 41 170 157, hide sort size extsel
  button "Add", 802, 252 41 37 12, hide
  button "Edit", 803, 252 53 37 12, hide disable
  button "Delete", 804, 252 65 37 12, hide disable
  text "", 805, 250 189 43 8, hide center
  check "Enable", 806, 252 80 29 10, hide

  box "Password folders", 900, 75 31 220 171, hide
  list 901, 79 41 170 157, hide sort size extsel
  button "Add", 902, 252 41 37 12, hide
  button "Edit", 903, 252 53 37 12, hide disable
  button "Delete", 904, 252 65 37 12, hide disable
  text "", 905, 250 189 43 8, hide center
  check "Enable", 906, 252 80 29 10, hide

  box "Banned IP addresses", 1000, 75 31 220 171, hide
  edit "", 1001, 79 41 212 157, multi return autohs autovs vsbar hide

  box "About", 1100, 75 31 220 171, hide
  edit "", 1101, 79 41 212 157, multi return autohs autovs vsbar hide readonly
}

alias httpd {
  set -u1 %c.httpd.section $1
  if ($dialog(httpd)) {
    if ($1) httpd.selecttab
    else dialog -c httpd
  }
  else dialog -m httpd httpd
}

alias httpd.integritycheck {
  if ($sock(httpd.listen)) {
    if (!$window(@HTTPd)) && ($hget(httpd.config,Logging)) httpd.logwindow
    if (%c.httpd.id !isnum 0-) %c.httpd.id = 0
    if (%c.httpd.birth !isnum 0-) %c.httpd.birth = $gmt
    if (%c.httpd.sockindex !isnum 1-) %c.httpd.sockindex = 1
    if (%c.httpd.hashindex !isnum 1-) %c.httpd.hashindex = 1
    if (!$timer(httpd.maintenance)) .timerhttpd.maintenance -io 0 1 $!httpd.maintenance($sock(httpd.client.*,%c.httpd.sockindex),$hget(%c.httpd.hashindex))
    %c.httpd.multiname = $chr(32) $+ name=
    %c.httpd.multifile = $chr(32) $+ filename=
    %c.httpd.multicrlf = $str($crlf,2)
  }
}

on *:dialog:httpd:*:*: {
  if ($devent == init) {
    didtok httpd 1 44 General,Permissions,Limitations,Banned IP addresses,Compression,Virtual folders,Password folders,Status codes,MIME types,Icons,About
    %httpd.ids = 100-117
    %httpd.icons = 1
    %httpd.scriptdir = $scriptdir
    %httpd.iconfile = $qt(%httpd.scriptdir $+ temp.png)
    hfree -w httpd.temp.*
    httpd.integritycheck
    set -l %configfile $qt(%httpd.scriptdir $+ HTTPd.db)
    if (!$isfile(%configfile)) {
      write %configfile
      hmake httpd.temp.config
      httpd.setstatuscodes httpd.temp.config
      httpd.checkconfig httpd.temp.config
      hsave -i httpd.temp.config %configfile Config
      hload -im httpd.temp.mime %configfile MIME
      httpd.checkmime httpd.temp.mime
      hsave -i httpd.temp.mime %configfile MIME
      noop $input($+(Default config loaded!,$str($crlf,2),Note: the default config is very conservative when it comes to limits and permissions,$chr(44) you might want to adjust them.),iao,HTTPd)
    }
    else {
      hload -im httpd.temp.config %configfile Config
      httpd.checkconfig httpd.temp.config
      hload -im httpd.temp.mime %configfile MIME
      httpd.checkmime httpd.temp.mime
    }
    if ($sock(httpd.listen)) did -c httpd 101
    if (%httpd.startup) did -c httpd 102
    did -a httpd 104 $hget(httpd.temp.config,ListenPort)
    did -a httpd 107 $hget(httpd.temp.config,BindToIP)
    did -a httpd 111 $hget(httpd.temp.config,RootDirectory)
    did $iif($isdir($did(111)),-e,-b) httpd 118
    did -a httpd 115 $hget(httpd.temp.config,CacheDirectory)
    did $iif($isdir($did(115)),-e,-b) httpd 119
    if ($hget(httpd.temp.config,Logging)) did -c httpd 122
    if (!$hget(httpd.temp.config,VisibleLogWindow)) did -c httpd 123
    if ($group(#httpd.wideareanetwork) == on) did -c httpd 201
    if ($hget(httpd.temp.config,AllowFileAccess)) did -c httpd 203
    if ($hget(httpd.temp.config,AllowDirectoryAccess)) did -c httpd 205
    if ($hget(httpd.temp.config,AllowmSLPages)) did -c httpd 207
    if ($hget(httpd.temp.config,AllowMultipartFormData)) did -c httpd 209
    tokenize 32 $hget(httpd.temp.config,AllowedHTTPMethods)
    if ($istok($1-,GET,32)) did -c httpd 212
    if ($istok($1-,POST,32)) did -c httpd 213
    if ($istok($1-,HEAD,32)) did -c httpd 214
    if ($istok($1-,OPTIONS,32)) did -c httpd 215
    if ($hget(httpd.temp.config,CompressionStatus)) did -c httpd 301
    did $iif($did(301).state,-e,-b) httpd 302-310
    didtok httpd 303 44 4 KB,8 KB,16 KB,32 KB,64 KB,128 KB,256 KB,512 KB,1 MB,2 MB (default),4 MB,8 MB,16 MB,32 MB,64 MB,128 MB,256 MB,512 MB
    if ($didwm(303,$httpd.bytessuf($hget(httpd.temp.config,CompressionMaximumSize)) ??*)) did -c httpd 303 $v1
    else did -c httpd 303 10
    did -a httpd 306 $hget(httpd.temp.config,CompressionFileTypes)
    didtok httpd 309 44 1 (lowest),2,3,4,5,6 (default),7,8,9 (highest)
    if ($didwm(309,$hget(httpd.temp.config,CompressionLevel) $+ *)) did -c httpd 309 $v1
    else did -c httpd 309 6
    didtok httpd 402 44 1024 bytes,2048 bytes,3072 bytes,4096 bytes,5120 bytes,6144 bytes,7168 bytes,8192 bytes (high speed),8193 bytes (low speed),9216 bytes,10240 bytes,11264 bytes,12288 bytes,13312 bytes,14336 bytes,15360 bytes,16384 bytes (recommended)
    if ($didwm(402,$hget(httpd.temp.config,MaximumChunkSize) bytes*)) did -c httpd 402 $v1
    else did -c httpd 402 17
    didtok httpd 405 44 1 second,2 seconds,3 seconds,4 seconds,5 seconds (default),15 seconds,30 seconds,1 minute,2 minutes,4 minutes,8 minutes,16 minutes,32 minutes
    tokenize 1 $hget(httpd.temp.config,KeepAliveTime)
    if ($1 < 60) tokenize 1 $1 $iif($1 == 1,second,seconds)
    elseif ($1 < 3600) tokenize 1 $iif($calc($1 /60) == 1,$v1 minute,$v1 minutes)
    else tokenize 1 $iif($calc($1 /3600) == 1,$v1 hour,$v1 hours)
    if ($didwm(405,$1)) did -c httpd 405 $v1
    else did -c httpd 405 5
    didtok httpd 408 44 256 B,512 B,1 KB (default),2 KB,4 KB,8 KB,16 KB,32 KB,64 KB,128 KB,256 KB,512 KB,1 MB,2 MB,4 MB,8 MB,16 MB,32 MB
    if ($didwm(408,$httpd.bytessuf($hget(httpd.temp.config,MaximumHeaderSize)))) did -c httpd 408 $v1
    else did -c httpd 408 3
    didtok httpd 411 44 256 B,512 B,1 KB,2 KB (default),4 KB,8 KB,16 KB,32 KB,64 KB,128 KB,256 KB,512 KB,1 MB,2 MB,4 MB,8 MB,16 MB,32 MB,64 MB,128 MB,256 MB
    if ($didwm(411,$httpd.bytessuf($hget(httpd.temp.config,MaximumBodySize)))) did -c httpd 411 $v1
    else did -c httpd 411 4
    didtok httpd 414 44 1,2,4,8,16 (default),32,64,128,256,512,1024,2048,4096,8192,16384,32768
    if ($didwm(414,$hget(httpd.temp.config,MaximumConnections) $+ *)) did -c httpd 414 $v1
    else did -c httpd 414 5
    didtok httpd 416 44 1,2,4 (default),8,16,32,64,128,256,512,1024
    if ($didwm(416,$hget(httpd.temp.config,MaximumConnectionsPerIP) $+ *)) did -c httpd 416 $v1
    else did -c httpd 416 3
    didtok httpd 419 44 1,2,4 (default),8,16,32,64,128,200
    if ($didwm(419,$hget(httpd.temp.config,MaximumMultipartItems) $+ *)) did -c httpd 419 $v1
    else did -c httpd 419 3
    didtok httpd 421 44 256 B,512 B,1 KB,2 KB,4 KB,8 KB,16 KB,32 KB,64 KB,128 KB,256 KB,512 KB (default),1 MB,2 MB,4 MB,8 MB,16 MB,32 MB,64 MB,128 MB,256 MB,512 MB,1 GB,2 GB,4 GB,8 GB,16 GB
    if ($didwm(421,$httpd.bytessuf($hget(httpd.temp.config,MaximumMultipartSize)))) did -c httpd 421 $v1
    else did -c httpd 421 12
    did -a httpd 601 301 $hget(httpd.temp.config,301)
    did -a httpd 601 400 $hget(httpd.temp.config,400)
    did -a httpd 601 401 $hget(httpd.temp.config,401)
    did -a httpd 601 403 $hget(httpd.temp.config,403)
    did -a httpd 601 404 $hget(httpd.temp.config,404)
    did -a httpd 601 405 $hget(httpd.temp.config,405)
    did -a httpd 601 411 $hget(httpd.temp.config,411)
    did -a httpd 601 413 $hget(httpd.temp.config,413)
    did -a httpd 601 414 $hget(httpd.temp.config,414)
    did -a httpd 601 431 $hget(httpd.temp.config,431)
    did -a httpd 705 $hfind(httpd.temp.mime,*,0,w,did -a httpd 701 $1 $hget(httpd.temp.mime,$1)) MIME type(s)
    hload -im httpd.temp.virtualfolders %configfile VirtualFolders
    did -a httpd 805 $hfind(httpd.temp.virtualfolders,*,0,w,did -a httpd 801 $1 $hget(httpd.temp.virtualfolders,$1)) folder(s)
    if ($hget(httpd.temp.config,VirtualFoldersStatus)) did -c httpd 806
    hload -im httpd.temp.passwordfolders %configfile PasswordFolders
    did -a httpd 905 $hfind(httpd.temp.passwordfolders,*,0,w,did -a httpd 901 $1 $decode($hget(httpd.temp.passwordfolders,$1),m)) folder(s)
    if ($hget(httpd.temp.config,PasswordFoldersStatus)) did -c httpd 906
    hload -im httpd.temp.bans %configfile Bans
    noop $hfind(httpd.temp.bans,*,0,w,did -a httpd 1001 $1 $hget(httpd.temp.bans,$1))
    did -i httpd 1101 1 HTTP daemon for mIRC v7.61+
    did -i httpd 1101 2
    did -i httpd 1101 3 Version: $chr(9) 1.0
    did -i httpd 1101 4 Coded by: Dazuz
    did -i httpd 1101 5 IRC: $chr(9) #DScript @ QuakeNet
    set -l %x 6
    while (%x <= 22) {
      did -i httpd 1101 %x
      inc %x
    }
    tokenize 32 httpd.temp.mime httpd.temp.passwordfolders httpd.temp.virtualfolders httpd.temp.bans
    hfree -w $*
    did -e httpd 2,3
    httpd.selecttab
    if ($sock(httpd.listen)) {
      did -a httpd 5 $httpd.link
      .timerhttpd.title -io 0 1 httpd.title
      httpd.title
    }
  }
  elseif ($devent == sclick) {
    if ($did == 1) httpd.loadtab $did(1).seltext
    elseif ($did isnum 2-3) httpd.savesettings
    elseif ($did == 5) && ($did(5)) url $did(5)
    elseif ($did == 6) window -a @HTTPd
    elseif ($did == 112) && ($sdir($did(111),Select the root folder for your HTTPd,Select)) {
      did -ra httpd 111 $v1
      did $iif($isdir($did(111)),-e,-b) httpd 118
    }
    elseif ($did == 116) && ($sdir($did(115),Select the cache folder for your HTTPd,Select)) {
      did -ra httpd 115 $v1
      did $iif($isdir($did(115)),-e,-b) httpd 119
    }
    elseif ($did == 118) run explorer $did(111)
    elseif ($did == 119) run explorer $did(115)
    elseif ($did == 301) did $iif($did(301).state,-e,-b) httpd 302-310
    elseif ($did == 502) noop $httpd.changeicon(favicon,icon.favicon.ico,503,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAh0lEQVQ4jWNgoBWYs6bkPzImWePBM0v/P3h2+P+DZ4f/7zgylbBByBq//Xj1/9uPV3ADCBqErhGXAegGoRhw+m7V/9N3qwgagDVckA1ANgiXRqIMgGFsGgepAesPlJFvwM4dG+CC6Abh0rxzxwbUtLBzx4b/2AzCphFDMz6DiNaIyyCSNZIKABDm5ZSqYaAfAAAAAElFTkSuQmCC)
    elseif ($did == 505) noop $httpd.changeicon(parent folder icon,icon.directoryback.png,506,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAadJREFUOI2lUj1rVEEUPXd2YTEbfXPn7Nu4BITAg1iolZ0BkVSCiGQbLazSpLIRLO3Uv6CCWtgIYhewUDCVIXYWlrHQVdAk83SLKOjOtTDGbDabKDndzIHzNQPsE5VhBMkztdHR7Pv6+qfdBNxOl0peNeCZpHR2rwTVvlNR1LQsbyOlExB5JIDsJbCZIM/zw74sFwQ4UK/XpwB0zGw8y7IJ7FLVAQDJk72UXjmz+bi2drHT6XwTkTcicqpSrS541a6qPid5eSC1NhqXQgifSV4Y5hJCOBRCaKvqi0C+Jjn5lyTfKnkf/9B3Q2zWq37M87wAADSbzbFAvvTk41arNbLV1Xt/PMuyCRRFrS81OefJRWy6/l7/LlI6JiLnY4wflLxhKc0K0DXnxhzwDmZPf1Yqd7orK8ueXJKUrss25WsGXHFmMwBmAHRjjDc3hj5qZu0kMifAAzFbNpHTA719o3FOer17AN6LyJMY460+E9VMRB6aWc+cmxz4iV9WV+cBTItzwUR+bOfLsvwaY2wbMI6Ujgxdm+TBraPuwE8HcsDgf1D98xL7wi9Jm4cdiOtZ0AAAAABJRU5ErkJggg==)
    elseif ($did == 508) noop $httpd.changeicon(folder icon,icon.directoryfolder.png,509,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAIJJREFUKJHtjjEKwkAQRd+sBJTcJ+AtZC8gHk3TewohBvYE4g3EyqRS51splsmmsfDV894fS7vYYlR84c6xWu+XDMBSHQVgNhty/0F6ImhIdVR/PWss3eWktF09rDtsVM6LUetvbv1dIVcGKBcFIdsGCPi0AEz84B/4lYC7t9m2e/MCLz9aJ6xNQ98AAAAASUVORK5CYII=)
    elseif ($did == 511) noop $httpd.changeicon(file icon,icon.directoryfile.png,512,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAMlJREFUOI2d0zFqQkEYBOBPsfEGBlJKytjbWKYMiIW5SiRgSDyJjYWNJ5CAF4hobRsPIIKIWCzGh+z6fE61uzPMDv/slpzxhA9UxTHEJMH9C2oJrosl2pdEObOu4u/KBZ94uTQpx7VRNPGDAV6LGkwxw06Y01tMNC6QZlQ0QRKVyNkz3hP6L6GNqwZzoba7EzygldBPsc4zOGCfMDjckmCtQCMxg4bQdQx9LPIMftG5NUH2HWyFAebhEZvTppQh6uhJf+cTNvjGCo5Fhx7hZo7d6QAAAABJRU5ErkJggg==)
    elseif ($did == 701) did $iif($did(httpd,701).seltext,-e,-b) httpd 703,704
    elseif ($did == 702) httpd.addmime
    elseif ($did == 703) httpd.editmime
    elseif ($did == 704) && ($input(Do you really want to delete the selected $iif($did(701,0).sel == 1,entry?,entries?),yqba,HTTPd)) {
      while ($did(701,1).sel) did -d httpd 701 $v1
      did -b httpd 703,704
      did -ra httpd 705 $bytes($did(701).lines,b) MIME type(s)
    }
    elseif ($did == 801) did $iif($did(801).sel,-e,-b) httpd 803,804
    elseif ($did == 802) httpd.addvirtualfolder
    elseif ($did == 803) httpd.addvirtualfolder $did(801).seltext
    elseif ($did == 804) && ($input(Do you really want to delete the selected $iif($did(801,0).sel == 1,entry?,entries?),yqba,HTTPd)) {
      while ($did(801,1).sel) did -d httpd 801 $v1
      did -b httpd 803,804
      did -ra httpd 805 $bytes($did(801).lines,b) folder(s)
    }
    elseif ($did == 901) did $iif($did(901).sel,-e,-b) httpd 903,904
    elseif ($did == 902) httpd.addpasswordfolder
    elseif ($did == 903) httpd.addpasswordfolder $did(901).seltext
    elseif ($did == 904) && ($input(Do you really want to delete the selected $iif($did(901,0).sel == 1,entry?,entries?),yqba,HTTPd)) {
      while ($did(901,1).sel) did -d httpd 901 $v1
      did -b httpd 903,904
      did -ra httpd 905 $bytes($did(901).lines,b) folder(s)
    }
  }
  elseif ($devent == dclick) {
    if ($did == 601) && ($did(601).seltext) noop $dialog(httpd.statuscode,httpd.statuscode,-4)
    elseif ($did == 701) {
      if ($did(701).sel) httpd.editmime
      else httpd.addmime
    }
    elseif ($did == 801) httpd.addvirtualfolder $did(801).seltext
    elseif ($did == 901) httpd.addpasswordfolder $did(901).seltext
  }
  elseif ($devent == edit) && ($did == 104) httpd.portcheck
  elseif ($devent == close) {
    if ($dialog(httpd.statuscode)) dialog -c httpd.statuscode
    .timerhttpd.title off
    .remove %httpd.iconfile
    unset %httpd.ids %httpd.icons %httpd.scriptdir %httpd.iconfile
    hfree -w httpd.temp.*
    httpd.integritycheck
  }
}

alias -l httpd.portcheck {
  tokenize 32 $did(httpd,104) $did(httpd,107)
  if ($1 !isnum 40-65545) did -ra httpd 120 Invalid port
  elseif (($portfree($1)) && (!$2)) || ($portfree($1,$2)) || ($sock(httpd.listen).port == $1) did -r httpd 120
  else did -ra httpd 120 Already in use
}

dialog -l httpd.statuscode {
  title "HTTPd"
  icon $scriptdirCube.ico
  size -1 -1 208 54
  option dbu
  box "", 1, 4 3 200 32
  edit "", 2, 7 13 194 10, autohs limit 8192
  button "Cancel", 3, 164 38 40 12, cancel
  button "OK", 4, 124 38 40 12, default ok
  button "Default", 5, 84 38 40 12
  text "", 6, 79 40 4 8, hide
  text "", 7, 8 25 192 8
}

on *:dialog:httpd.statuscode:*:*: {
  if ($devent == init) {
    tokenize 32 $did(httpd,601).seltext
    did -a httpd.statuscode 6 $1
    dialog -t httpd.statuscode HTTPd - Edit $1 status code
    did -a httpd.statuscode 1 Enter the changed $1 status code
    did -a httpd.statuscode 2 $2-
    did -f httpd.statuscode 2
    httpd.statuscodeedit
  }
  elseif ($devent == sclick) {
    if ($did == 4) did -o httpd 601 $did(httpd,601).sel $did(6) $did(2)
    elseif ($did == 5) {
      did -ra httpd.statuscode 2 $httpd.defaultstatuscodes($did(6))
      httpd.statuscodeedit
    }
  }
  elseif ($devent == edit) && ($did == 2) httpd.statuscodeedit
}

alias -l httpd.statuscodeedit {
  tokenize 1 $len($did(httpd.statuscode,2))
  did -ra httpd.statuscode 7 $bytes($1,b) out of 8,192 characters used ( $+ $calc(8192-$1) left, $round($calc(($1 /8192)*100),2) $+ % used)
}

alias -l httpd.selecttab {
  if ($matchtok(permissions|security|secure|rules|access policy,%c.httpd.section,1,124)) httpd.loadtab permissions
  elseif ($matchtok(compression|compress,%c.httpd.section,1,124)) httpd.loadtab compression
  elseif ($matchtok(limitations|limits|restrictions,%c.httpd.section,1,124)) httpd.loadtab limitations
  elseif ($matchtok(icons|pictures|images,%c.httpd.section,1,124)) httpd.loadtab icons
  elseif ($matchtok(status codes|httpd|error codes,%c.httpd.section,1,124)) httpd.loadtab status codes
  elseif ($matchtok(mime types|extensions,%c.httpd.section,1,124)) httpd.loadtab mime types
  elseif ($matchtok(virtual folders|folder links,%c.httpd.section,1,124)) httpd.loadtab virtual folders
  elseif ($matchtok(password folders|passworded folders,%c.httpd.section,1,124)) httpd.loadtab password folders
  elseif ($matchtok(ip address bans|access policy|deny|denied,%c.httpd.section,1,124)) httpd.loadtab banned ip addresses
  elseif ($matchtok(about|statistics|stats|information|help,%c.httpd.section,1,124)) httpd.loadtab about
  else httpd.loadtab general
  unset %c.httpd.section
}

alias -l httpd.title {
  if ($sock(httpd.listen)) dialog -t httpd HTTPd settings - /httpd - Server running! - $sock(httpd.client.*,0) connection(s)
  else dialog -t httpd HTTPd settings - /httpd
  if ($did(httpd,1).seltext == about) {
    if ($sock(httpd.listen)) {
      did -o httpd 1101 8 The server is ONLINE, and has been for $duration($calc($gmt -%c.httpd.birth)) $+ .
      did -o httpd 1101 9 There has been $bytes(%c.httpd.id,b) connection(s) since $asctime(%c.httpd.birth,yyyy-mm-dd HH:nn:ss.)
      did -o httpd 1101 10 Connections from Wide Area Network are $iif($group(#httpd.localareanetwork) == on,NOT accepted.,accepted.)
      did -o httpd 1101 12 $+($bytes($sock(httpd.client.*,0),b),$chr(9),open connections)
      did -o httpd 1101 14 $+($bytes($sock(httpd.client.*.method.*,0),b),$chr(9),waiting to receive method from)
      did -o httpd 1101 15 $+($bytes($sock(httpd.client.*.header.*,0),b),$chr(9),waiting to receive header from)
      did -o httpd 1101 16 $+($bytes($sock(httpd.client.*.post.*,0),b),$chr(9),waiting to receive post from)
      did -o httpd 1101 17 $+($bytes($sock(httpd.client.*.multiheader.*,0),b),$chr(9),waiting to receive multipart header from)
      did -o httpd 1101 18 $+($bytes($sock(httpd.client.*.multifile.*,0),b),$chr(9),waiting to receive multipart file from)
      did -o httpd 1101 19 $+($bytes($sock(httpd.client.*.multidata.*,0),b),$chr(9),waiting to receive multipart data from)
      did -o httpd 1101 20 $+($bytes($sock(httpd.client.*.default.*,0),b),$chr(9),processing)
      did -o httpd 1101 21 $+($bytes($sock(httpd.client.*.data.*,0),b),$chr(9),sending data to)
      did -o httpd 1101 22 $+($bytes($sock(httpd.client.*.file.*,0),b),$chr(9),sending a file to)
      did -o httpd 1101 23 $+($bytes($sock(httpd.client.*.error.*,0),b),$chr(9),processing an error)
    }
    else {
      did -o httpd 1101 8 The server is OFFLINE.
      did -o httpd 1101 10
      did -o httpd 1101 12
      did -o httpd 1101 14
      did -o httpd 1101 15
      did -o httpd 1101 16
      did -o httpd 1101 17
      did -o httpd 1101 18
      did -o httpd 1101 19
      did -o httpd 1101 20
      did -o httpd 1101 21
      did -o httpd 1101 22
      did -o httpd 1101 23
    }
  }
}

alias -l httpd.addpasswordfolder {
  if ($input($+(To what folder would you like to add a password?,$str($crlf,2),Note: this can be used for virtual folders,$chr(44) just enter the name of the virtual folder.,$str($crlf,2),$httpd.link $+ <FOLDER>/),eqa,HTTPd,$1) isalnum) {
    set -l %f $v1
    if (%f != $1) && ($didwm(httpd,901,%f *)) {
      did -c httpd 901 $v1
      noop $input($qt(%f) already exists!,oha,HTTPd)
    }
    elseif ($input($+(Enter login details in the following format:,$crlf,USERNAME:PASSWORD),eqa,HTTPd,$2-)) {
      set -l %d $v1
      if ($numtok(%d,58) == 2) {
        if ($1-) did -co httpd 901 $did(httpd,901).sel %f %d
        else did -ca httpd 901 %f %d
        did -e httpd 903,904
        did -ra httpd 905 $bytes($did(httpd,901).lines,b) folder(s)
      }
      elseif ($v1) noop $input(Invalid name.,oha,HTTPd)
    }
  }
  elseif ($v1) noop $input(Invalid name.,oha,HTTPd)
}

alias -l httpd.addvirtualfolder {
  if ($sdir($iif($1-,$2,$did(httpd,111)),Select a folder you want to create a link to)) {
    set -l %d $v1
    if ($input($+(What would you like to call the link? Note: the name can only contain letters and/or numbers.,$str($crlf,2),$httpd.link $+ /<NAME>),eqa,HTTPd,$iif($1-,$1,$gettok(%d,-1,92))) isalnum) {
      set -l %n $v1
      if (%n != $1) && ($didwm(httpd,801,%n *)) {
        did -c httpd 801 $v1
        noop $input($qt(%n) already exists!,oha,HTTPd)
      }
      else {
        if ($1-) did -co httpd 801 $did(httpd,801).sel %n %d
        else did -ca httpd 801 %n %d
        did -e httpd 803,804
        did -ra httpd 805 $bytes($did(httpd,801).lines,b) folder(s)
      }
    }
    else noop $input(Invalid name.,oha,HTTPd)
  }
}

alias -l httpd.addmime {
  if ($input($+(Enter a new MIME entry:,$crlf,$crlf,Format: <extension> <content>),eqa,HTTPd)) {
    set -l %m $v1
    if ($numtok(%m,32) != 2) || ($numtok($gettok(%m,2,32),47) != 2) noop $input(Invalid format.,oha,HTTPd)
    elseif ($didwm(701,$gettok(%m,1,32) *)) did -c httpd 701 $v1 $input(There is already an entry for the file type: $gettok(%m,1,32),oha,HTTPd)
    else {
      did -ca httpd 701 %m
      did -e httpd 703,704
      did -ra httpd 705 $bytes($did(httpd,701).lines,b) MIME type(s)
    }
  }
}

alias -l httpd.editmime {
  if ($input($+(Enter the changed MIME entry:,$crlf,$crlf,Format: <extension> <content>),eqa,HTTPd,$did(httpd,701).seltext)) {
    set -l %m $v1
    set -l %o $gettok($did(httpd,701).seltext,1,32)
    if ($numtok(%m,32) != 2) || ($numtok($gettok(%m,2,32),47) != 2) noop $input(Invalid format.,oha,HTTPd)
    elseif ($gettok(%m,1,32) != %o) && ($didwm(httpd,701,$gettok(%m,1,32) *)) did -c httpd 701 $v1 $input(There is already an entry for the file type: $gettok(%m,1,32),oha,HTTPd)
    else did -co httpd 701 $did(httpd,701).sel %m
  }
}

alias -l httpd.changeicon {
  if ($sfile(%httpd.scriptdir $+ *.png,Select the $1 (.PNG),Select)) {
    bread $qt($v1) 0 $file($v1).size &i
    if ($gettok($v1,-1,46) != png) || ($encode(&i,bm) > 8000) noop $input(The icon file must be less than ~6 KB and in PNG format.,oha,HTTPd)
    else hadd -b httpd.temp.config $2 &i
  }
  else hadd httpd.temp.config $2 $4
  noop $httpd.icon($3,$hget(httpd.temp.config,$2))
}

alias -l httpd.icon {
  bset -ct &i 1 $2
  bwrite -c %httpd.iconfile 0 -1 &i $decode(&i,bm)
  did -g httpd $1 %httpd.iconfile
  .remove %httpd.iconfile
}

alias -l httpd.bytessuf return $replacex($replacex($bytes($1).suf,kb,_KB,mb,_MB,gb,_GB,tb,_TB,b,_B),_,$chr(32))

alias -l httpd.bytes tokenize 32 $1 | return $calc($1 $replacex($2,kb,*1024,mb,*1024*1024,gb,*1024*1024*1024,tb,*1024*1024*1024*1024,b,*1))

alias -l httpd.loadtab {
  did -h httpd %httpd.ids
  if ($didwm(httpd,1,$1-)) did -c httpd 1 $v1
  if ($1 == general) {
    %httpd.ids = 100-123
    did -ra httpd 10 General settings description
    did -ra httpd 11 Here you can turn the server on and off, decide whether or not it should start on mIRC startup and change the folder settings.
    httpd.portcheck
  }
  elseif ($1 == permissions) {
    %httpd.ids = 200-216
    did -ra httpd 10 Permissions description
    did -ra httpd 11 Here you can change client permissions. These settings can have major impact on security.
  }
  elseif ($1 == compression) {
    %httpd.ids = 300-310
    did -ra httpd 10 Compression description
    did -ra httpd 11 Compression allows you to save bandwidth by sacrificing CPU time.
  }
  elseif ($1 == limitations) {
    %httpd.ids = 400-422
    did -ra httpd 10 Limitations description
    did -ra httpd 11 Here you can set limits to what a client and the server can do.
    did -ra httpd 422 The maximum number of items, and the maximum total size of said items allowed in a single multipart/form-data request. Multipart/form-data is currently $iif($did(httpd,209).state,allowed.,disallowed.)
  }
  elseif ($1 == icons) {
    %httpd.ids = 500-512
    did -ra httpd 10 Icons description
    did -ra httpd 11 These are the default icons the server uses. They must be in .PNG format and smaller than ~6 KB.
    if (%httpd.icons) {
      noop $httpd.icon(503,$hget(httpd.temp.config,icon.favicon.ico))
      noop $httpd.icon(506,$hget(httpd.temp.config,icon.directoryback.png))
      noop $httpd.icon(509,$hget(httpd.temp.config,icon.directoryfolder.png))
      noop $httpd.icon(512,$hget(httpd.temp.config,icon.directoryfile.png))
    }
    unset %httpd.icons
  }
  elseif ($1- == status codes) {
    %httpd.ids = 600-601
    did -ra httpd 10 Status codes description
    did -ra httpd 11 These are the HTTP status codes the server uses. You can edit them by double clicking the one you want to edit. Note: you can leave these error codes blank.
  }
  elseif ($1- == mime types) {
    %httpd.ids = 700-705
    did -ra httpd 10 MIME types description
    did -ra httpd 11 These are the known MIME types of files. They are sent along with files in Content-Type header to instruct the client how to handle the files.
  }
  elseif ($1- == virtual folders) {
    %httpd.ids = 800-806
    did -ra httpd 10 Virtual folders description
    did -ra httpd 11 Virtual folders allow you to create links to content outside of the root folder, and shortcuts to content in your root folder.
  }
  elseif ($1- == password folders) {
    %httpd.ids = 900-906
    did -ra httpd 10 Password folders description
    did -ra httpd 11 Password folders allow you to protect contents of a folder with a password. Note: this is insecure, do not trust this.
  }
  elseif ($1- == Banned IP addresses) {
    %httpd.ids = 1000,1001
    did -ra httpd 10 Banned IP addresses description
    did -ra httpd 11 Each line represents a ban, starting with an IP address, which is followed by an optional note. *? wildcards are allowed. Example: 192.168.?.* An example
  }
  elseif ($1- == About) {
    %httpd.ids = 1100,1101
    did -ra httpd 10 About description
    did -ra httpd 11 Basic information about the HTTPd.
    httpd.title
  }
  did -v httpd %httpd.ids
}

alias -l httpd.savesettings {
  set -l %configfile $qt(%httpd.scriptdir $+ HTTPd.db)
  %httpd.startup = $did(httpd,102).state
  hadd httpd.temp.config ListenPort $did(httpd,104)
  hadd httpd.temp.config BindToIP $did(httpd,107)
  hadd httpd.temp.config RootDirectory $did(httpd,111)
  hadd httpd.temp.config CacheDirectory $did(httpd,115)
  if ($did(httpd,201).state) {
    .enable #httpd.wideareanetwork
    .disable #httpd.localareanetwork
  }
  else {
    .disable #httpd.wideareanetwork
    .enable #httpd.localareanetwork
  }
  hadd httpd.temp.config Logging $did(httpd,122).state
  hadd httpd.temp.config VisibleLogWindow $iif($did(httpd,123).state,0,1)
  hadd httpd.temp.config AllowFileAccess $did(httpd,203).state
  hadd httpd.temp.config AllowDirectoryAccess $did(httpd,205).state
  hadd httpd.temp.config AllowmSLPages $did(httpd,207).state
  hadd httpd.temp.config AllowMultipartFormData $did(httpd,209).state
  hadd httpd.temp.config AllowedHTTPMethods $iif($did(httpd,212).state,GET) $iif($did(httpd,213).state,POST) $iif($did(httpd,214).state,HEAD) $iif($did(httpd,215).state,OPTIONS) 
  hadd httpd.temp.config MaximumMultipartItems $gettok($did(419),1,32)
  hadd httpd.temp.config MaximumMultipartSize $httpd.bytes($did(421))
  hadd httpd.temp.config CompressionStatus $did(httpd,301).state
  hadd httpd.temp.config CompressionMaximumSize $httpd.bytes($did(httpd,303))
  hadd httpd.temp.config CompressionFileTypes $did(httpd,306)
  hadd httpd.temp.config CompressionLevel $gettok($did(httpd,309),1,32)
  hadd httpd.temp.config MaximumChunkSize $gettok($did(httpd,402),1,32)
  hadd httpd.temp.config KeepAliveTime $httpd.seconds($did(httpd,405))
  hadd httpd.temp.config MaximumHeaderSize $httpd.bytes($did(httpd,408))
  hadd httpd.temp.config MaximumBodySize $httpd.bytes($did(httpd,411))
  hadd httpd.temp.config MaximumConnections $gettok($did(httpd,414),1,32)
  hadd httpd.temp.config MaximumConnectionsPerIP $gettok($did(httpd,416),1,32)
  filter -ik httpd 601 httpd.codefilter
  hadd httpd.temp.config VirtualFoldersStatus $did(httpd,806).state
  hadd httpd.temp.config PasswordFoldersStatus $did(httpd,906).state
  httpd.checkconfig httpd.temp.config
  hsave -i httpd.temp.config %configfile Config
  if ($hget(httpd.config)) {
    hdel -w httpd.config *
    hload -i httpd.config %configfile Config
  }
  if ($sock(httpd.listen)) {
    if ($hget(httpd.config,Logging)) {
      if ($window(@HTTPd)) {
        if ($hget(httpd.config,VisibleLogWindow)) window -w3 @HTTPd
        else window -w0 @HTTPd
      }
      else httpd.logwindow
    }
    else window -c @HTTPd
  }
  hmake httpd.temp.mime
  filter -ik httpd 701 httpd.mimefilter
  httpd.checkmime httpd.temp.mime
  hsave -i httpd.temp.mime %configfile MIME
  if ($hget(httpd.mime)) {
    hfree -w httpd.mime
    hload -im httpd.mime %configfile MIME
  }
  hmake httpd.temp.virtualfolders
  filter -ik httpd 801 httpd.virtualfolderfilter
  hsave -i httpd.temp.virtualfolders %configfile VirtualFolders
  if ($sock(httpd.listen)) {
    hfree -w httpd.virtualfolders
    if ($hget(httpd.temp.config,VirtualFoldersStatus)) hload -im httpd.virtualfolders %configfile VirtualFolders
  }
  hmake httpd.temp.passwordfolders
  filter -ik httpd 901 httpd.passwordfolderfilter
  hsave -i httpd.temp.passwordfolders %configfile PasswordFolders
  if ($sock(httpd.listen)) {
    hfree -w httpd.virtualfolders
    if ($hget(httpd.temp.config,PasswordFoldersStatus)) hload -im httpd.passwordfolders %configfile PasswordFolders
  }
  hmake httpd.temp.bans
  filter -ik httpd 1001 httpd.bansfilter
  hsave -i httpd.temp.bans %configfile Bans
  if ($sock(httpd.listen)) {
    hfree -w httpd.bans
    hload -im httpd.bans %configfile Bans
    noop $hfind(httpd.bans,*,0,w,httpd.checkban $1)
  }
  tokenize 32 httpd.temp.mime httpd.temp.passwordfolders httpd.temp.virtualfolders httpd.temp.bans
  hfree -w $*
  if ($did(httpd,101).state) {
    if ($sock(httpd.listen)) {
      tokenize 32 httpd.passwordfolders httpd.virtualfolders httpd.mime httpd.config
      hfree -w $*
      hload -im httpd.config %configfile Config
      httpd.checkconfig httpd.config
      hload -im httpd.mime %configfile MIME
      httpd.checkmime httpd.mime
      if ($hget(httpd.config,VirtualFoldersStatus)) hload -im httpd.virtualfolders %configfile VirtualFolders
      if ($hget(httpd.config,PasswordFoldersStatus)) hload -im httpd.passwordfolders %configfile PasswordFolders
      sockclose httpd.listen
      socklisten $iif($hget(httpd.config,BindToIP),-d $v1) httpd.listen $hget(httpd.config,ListenPort)
    }
    else httpdstart -quiet -force
  }
  else httpdstop -quiet -force
  if ($sock(httpd.listen)) {
    did -a httpd 5 $httpd.link
    .timerhttpd.title -io 0 1 httpd.title
    httpd.title
  }
  else {
    .timerhttpd.title off
    did -r httpd 5
    httpd.title
  }
}
;$sock(httpd.listen)$sock(httpd.listen)$sock(httpd.listen)$sock(httpd.listen)$sock(httpd.listen)
alias -l httpd.checkban while ($sock(httpd.client.?*.????*. $+ $1,1)) httpd.kill $v1

alias -l httpd.codefilter hadd httpd.temp.config $1

alias -l httpd.mimefilter hadd httpd.temp.mime $1

alias -l httpd.virtualfolderfilter hadd httpd.temp.virtualfolders $1

alias -l httpd.passwordfolderfilter tokenize 32 $1 | hadd httpd.temp.passwordfolders $1 $encode($2-,m)

alias -l httpd.bansfilter hadd httpd.temp.bans $1

alias -l httpd.seconds tokenize 32 $1 | return $iif(sec isin $2,$1,$calc(60*$1))

alias -l httpd.checkconfig {
  if (!$isdir($hget($1,CacheDirectory))) {
    set -l %cachedir $scriptdircache\
    if (!$isdir(%cachedir)) mkdir $qt(%cachedir)
    hadd $1 CacheDirectory %cachedir
  }
  noop $findfile($hget($1,CacheDirectory),????????????????????????????????????????,0,1,.remove $qt($parms))
  if (!$isdir($hget($1,RootDirectory))) {
    set -l %rootdir $scriptdirwww\
    if (!$isdir(%rootdir)) mkdir $qt(%rootdir)
    hadd $1 RootDirectory %rootdir
  }
  if ($hget($1,ListenPort) !isnum 1-65535) hadd $1 ListenPort 80
  if ($hget($1,Logging) !isnum 0-1) hadd $1 Logging 1
  if ($hget($1,VisibleLogWindow) !isnum 0-1) hadd $1 VisibleLogWindow 1
  if ($hget($1,CompressionStatus) !isnum 0-1) hadd $1 CompressionStatus 1
  if ($hget($1,CompressionLevel) !isnum 1-9) hadd $1 CompressionLevel 6
  if ($hget($1,CompressionMaximumSize) !isnum 65-) hadd $1 CompressionMaximumSize 2048000
  if (!$hget($1,CompressionFileTypes)) hadd $1 CompressionFileTypes txt log css xml html htm js
  if ($hget($1,AllowFileAccess) !isnum 0-1) hadd $1 AllowFileAccess 1
  if ($hget($1,AllowDirectoryAccess) !isnum 0-1) hadd $1 AllowDirectoryAccess 1
  if ($hget($1,AllowmSLPages) !isnum 0-1) hadd $1 AllowmSLPages 0
  if ($hget($1,AllowMultipartFormData) !isnum 0-1) hadd $1 AllowMultipartFormData 0
  if (!$hget($1,AllowedHTTPMethods)) hadd $1 AllowedHTTPMethods GET HEAD OPTIONS
  if ($hget($1,MaximumMultipartItems) !isnum 1-200) hadd $1 MaximumMultipartItems 4
  if ($hget($1,MaximumMultipartSize) !isnum 1-) hadd $1 MaximumMultipartSize 524288
  if ($hget($1,MaximumChunkSize) !isnum 512-16384) hadd $1 MaximumChunkSize 16384
  if ($hget($1,MaximumHeaderSize) !isnum 256-) hadd $1 MaximumHeaderSize 1024
  if ($hget($1,MaximumBodySize) !isnum 1-) hadd $1 MaximumBodySize 2048
  if ($hget($1,KeepAliveTime) !isnum 1-) hadd $1 KeepAliveTime 5
  if ($hget($1,MaximumConnections) !isnum 1-) hadd $1 MaximumConnections 16
  if ($hget($1,MaximumConnectionsPerIP) !isnum 1-) hadd $1 MaximumConnectionsPerIP 4
  if ($hget($1,VirtualFoldersStatus) !isnum 0-1) hadd $1 VirtualFoldersStatus 0
  if ($hget($1,PasswordFoldersStatus) !isnum 0-1) hadd $1 PasswordFoldersStatus 0
  if (!$hget($1,icon.directoryfolder.png)) hadd $1 icon.directoryfolder.png iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAIJJREFUKJHtjjEKwkAQRd+sBJTcJ+AtZC8gHk3TewohBvYE4g3EyqRS51splsmmsfDV894fS7vYYlR84c6xWu+XDMBSHQVgNhty/0F6ImhIdVR/PWss3eWktF09rDtsVM6LUetvbv1dIVcGKBcFIdsGCPi0AEz84B/4lYC7t9m2e/MCLz9aJ6xNQ98AAAAASUVORK5CYII=
  if (!$hget($1,icon.directoryfile.png)) hadd $1 icon.directoryfile.png iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAMlJREFUOI2d0zFqQkEYBOBPsfEGBlJKytjbWKYMiIW5SiRgSDyJjYWNJ5CAF4hobRsPIIKIWCzGh+z6fE61uzPMDv/slpzxhA9UxTHEJMH9C2oJrosl2pdEObOu4u/KBZ94uTQpx7VRNPGDAV6LGkwxw06Y01tMNC6QZlQ0QRKVyNkz3hP6L6GNqwZzoba7EzygldBPsc4zOGCfMDjckmCtQCMxg4bQdQx9LPIMftG5NUH2HWyFAebhEZvTppQh6uhJf+cTNvjGCo5Fhx7hZo7d6QAAAABJRU5ErkJggg==
  if (!$hget($1,icon.directoryback.png)) hadd $1 icon.directoryback.png iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAadJREFUOI2lUj1rVEEUPXd2YTEbfXPn7Nu4BITAg1iolZ0BkVSCiGQbLazSpLIRLO3Uv6CCWtgIYhewUDCVIXYWlrHQVdAk83SLKOjOtTDGbDabKDndzIHzNQPsE5VhBMkztdHR7Pv6+qfdBNxOl0peNeCZpHR2rwTVvlNR1LQsbyOlExB5JIDsJbCZIM/zw74sFwQ4UK/XpwB0zGw8y7IJ7FLVAQDJk72UXjmz+bi2drHT6XwTkTcicqpSrS541a6qPid5eSC1NhqXQgifSV4Y5hJCOBRCaKvqi0C+Jjn5lyTfKnkf/9B3Q2zWq37M87wAADSbzbFAvvTk41arNbLV1Xt/PMuyCRRFrS81OefJRWy6/l7/LlI6JiLnY4wflLxhKc0K0DXnxhzwDmZPf1Yqd7orK8ueXJKUrss25WsGXHFmMwBmAHRjjDc3hj5qZu0kMifAAzFbNpHTA719o3FOer17AN6LyJMY460+E9VMRB6aWc+cmxz4iV9WV+cBTItzwUR+bOfLsvwaY2wbMI6Ujgxdm+TBraPuwE8HcsDgf1D98xL7wi9Jm4cdiOtZ0AAAAABJRU5ErkJggg==
  if (!$hget($1,icon.favicon.ico)) hadd $1 icon.favicon.ico iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAh0lEQVQ4jWNgoBWYs6bkPzImWePBM0v/P3h2+P+DZ4f/7zgylbBByBq//Xj1/9uPV3ADCBqErhGXAegGoRhw+m7V/9N3qwgagDVckA1ANgiXRqIMgGFsGgepAesPlJFvwM4dG+CC6Abh0rxzxwbUtLBzx4b/2AzCphFDMz6DiNaIyyCSNZIKABDm5ZSqYaAfAAAAAElFTkSuQmCC
}

alias -l httpd.defaultstatuscodes {
  if ($1 == 301) return <!DOCTYPE html><html><head><title>301 Moved Permanently</title></head><body><h2>301 Moved Permanently</h2><p>Give me a second, it's somewhere over here.<p></body></html>
  elseif ($1 == 400) return <!DOCTYPE html><html><head><title>400 Bad Request</title></head><body><h2>400 Bad Request</h2><p>I'd do anything for you, but I won't do that.<p></body></html>
  elseif ($1 == 401) return <!DOCTYPE html><html><head><title>401 Unauthorized</title></head><body><h2>401 Unauthorized</h2><p>Hello! I am a server, who are you?<p></body></html>
  elseif ($1 == 403) return <!DOCTYPE html><html><head><title>403 Forbidden</title></head><body><h2>403 Forbidden</h2><p>No means no.<p></body></html>
  elseif ($1 == 404) return <!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h2>404 Not Found</h2><p>This is not what you're looking for.<p></body></html>
  elseif ($1 == 405) return <!DOCTYPE html><html><head><title>405 Method Not Allowed</title></head><body><h2>405 Method Not Allowed</h2><p>Sorry, I don't bend that way.<p></body></html>
  elseif ($1 == 411) return <!DOCTYPE html><html><head><title>411 Length Required</title></head><body><h2>411 Length Required</h2><p>I must know more.<p></body></html>
  elseif ($1 == 413) return <!DOCTYPE html><html><head><title>413 Payload Too Large</title></head><body><h2>413 Payload Too Large</h2><p>That's what she said.<p></body></html>
  elseif ($1 == 414) return <!DOCTYPE html><html><head><title>414 Request-URI Too Long</title></head><body><h2>414 Request-URI Too Long</h2><p>That's what she said.<p></body></html>
  elseif ($1 == 431) return <!DOCTYPE html><html><head><title>431 Request Header Fields Too Large</title></head><body><h2>431 Request Header Fields Too Large</h2><p>That's what he said.<p></body></html>
}

alias -l httpd.checkmime {
  if (!$hget($1,0)) {
    bset -t &m -1 hta application/htaisp application/x-internet-signupcrd application/x-mscardfilepmc application/x-perfmonspc application/x-pkcs7-certificatessv4crc application/x-sv4crcbin application/octet-streamclp application/x-msclipmny application/x-msmoneyp7r application/x-pkcs7-certreqrespevy application/envoyp7s application/pkcs7-signatureeps application/postscriptsetreg application/set-registration-initiationxlm application/vnd.ms-excelp7b application/x-cpiocpio application/x-dvidvi application/x-pkcs7-certificatesdoc application/msworddot application/mswordp7c application/pkcs7-mimeps application/postscriptwps application/vnd.ms-workscsh application/x-cshiii application/x-iphonepmw application/x-perfmonman application/x-troff-manhdf application/x-hdfmvb application/x-msmediaviewtexi application/x-texinfosetpay application/set-payment-initiationstl application/vndms-pkistlmdb application/x-msaccessoda application/odahlp application/winhlpnc application/x-netcdf
    bset -t &m -1 sh application/x-shshar application/x-shartcl application/x-tclms application/x-troff-msods application/oleobjectaxs application/olescriptxla application/vnd.ms-excelmpp application/vnd.ms-projectdir application/x-directorsit application/x-stuffitcrl application/pkix-crlai application/postscriptxls application/vnd.ms-excelwks application/vnd.ms-worksins application/x-internet-signuppub application/x-mspublisherwri application/x-mswritespl application/futuresplashhqx application/mac-binhex40p10 application/pkcs10xlc application/vnd.ms-excelxlt application/vnd.ms-exceldxr application/x-directorjs text/javascriptm13 application/x-msmediaviewtrm application/x-msterminalpml application/x-perfmonme application/x-troff-mewcm application/vnd.ms-workslatex application/x-latexm14 application/x-msmediaviewwmf application/x-msmetafilecer application/x-x509-ca-certzip application/x-zip-compressedp12 application/x-pkcs12pfx application/x-pkcs12
    bset -t &m -1 der application/x-x509-ca-certpdf application/pdfxlw application/vnd.ms-exceltexinfo application/x-texinfop7m application/pkcs7-mimepps application/vnd.ms-powerpointdcr application/x-directorgtar application/x-gtarsct text/scriptletfif application/fractalsexe application/octet-streamppt application/vnd.ms-powerpointsst application/vndms-pkicertstorepko application/vndms-pkipkoscd application/x-msscheduletar application/x-tarroff application/x-trofft application/x-troffprf application/pics-rulesrtf application/rtfpot application/vnd.ms-powerpointwdb application/vnd.ms-worksbcpio application/x-bcpiodll application/x-msdownloadpma application/x-perfmonpmr application/x-perfmontr application/x-troffsrc application/x-wais-sourceacx application/internet-property-streamcat application/vndms-pkiseccatcdf application/x-cdftgz application/x-compressedsv4cpio application/x-sv4cpiotex application/x-texustar application/x-ustarcrt application/x-x509-ca-cert
    bset -t &m -1 ra audio/x-pn-realaudiomid audio/midau audio/basicsnd audio/basicwav audio/wavaifc audio/aiffm3u audio/x-mpegurlram audio/x-pn-realaudioaiff audio/aiffrmi audio/midaif audio/x-aiffmp3 audio/mpeggz application/x-gzipz application/x-compresstsv text/tab-separated-valuesxml text/xml323 text/h323htt text/webviewhtmlstm text/htmlhtml text/htmlxsl text/xmlhtm text/htmlcod image/cis-codief image/iefpbm image/x-portable-bitmaptiff image/tiffppm image/x-portable-pixmaprgb image/x-rgbdib image/bmpjpeg image/jpegcmx image/x-cmxpnm image/x-portable-anymapjpe image/jpegjfif image/pjpegtif image/tiffjpg image/jpegxbm image/x-xbitmapras image/x-cmu-rastergif image/gifmp4 video/mp4mp4a audio/mp4weba audio/webmwma audio/x-ms-wmampga audio/mpegoga audio/oggogg audio/oggaac audio/x-aacwmv video/x-ms-wmvqt video/quicktimempeg video/mpegasf video/x-ms-asfogv video/oggavi video/x-msvideoflv video/x-flvm4v video/x-m4vmpg video/mpegwebm video/webm
    bset -t &m -1 jpgv video/jpegmov video/quicktimepng image/pngwebp image/webpico image/x-iconbmp image/bmptxt text/plainlog text/plainmrc text/plain
    set -l %x 1
    hadd $1 $gettok($bvar(&m,1,200).text,1,1)
    while ($bfind(&m,%x,1)) { %x = $v1 + 1 | hadd $1 $gettok($bvar(&m,%x,200).text,1,1) }
  }
}

alias -l httpd.setstatuscodes {
  hadd $1 301 $httpd.defaultstatuscodes(301)
  hadd $1 400 $httpd.defaultstatuscodes(400)
  hadd $1 401 $httpd.defaultstatuscodes(401)
  hadd $1 403 $httpd.defaultstatuscodes(403)
  hadd $1 404 $httpd.defaultstatuscodes(404)
  hadd $1 405 $httpd.defaultstatuscodes(405)
  hadd $1 411 $httpd.defaultstatuscodes(411)
  hadd $1 413 $httpd.defaultstatuscodes(413)
  hadd $1 414 $httpd.defaultstatuscodes(414)
  hadd $1 431 $httpd.defaultstatuscodes(431)
}

alias httpdstart {
  set -l %params $1-
  if ($sock(httpd.listen)) && (-force !isin %params) echo $color(info) -at * HTTPd is already running.
  else {
    httpdstop -quiet -force
    %c.httpd.id = 0
    %c.httpd.birth = $gmt
    %c.httpd.sockindex = 1
    %c.httpd.hashindex = 1
    %c.httpd.multiname = $chr(32) $+ name=
    %c.httpd.multifile = $chr(32) $+ filename=
    %c.httpd.multicrlf = $crlf $+ $crlf
    tokenize 32 httpd.passwordfolders httpd.virtualfolders httpd.mime httpd.config httpd.bans
    hfree -w $*
    set -l %configfile $qt($scriptdirHTTPd.db)
    if (!$isfile(%configfile)) {
      write %configfile
      hload -im httpd.config %configfile Config
      httpd.setstatuscodes httpd.config
      httpd.checkconfig httpd.config
      hsave -i httpd.config %configfile Config
      hload -im httpd.mime %configfile MIME
      httpd.checkmime httpd.mime
      hsave -i httpd.mime %configfile MIME
    }
    else {
      hload -im httpd.config %configfile Config
      httpd.checkconfig httpd.config
      hload -im httpd.mime %configfile MIME
      httpd.checkmime httpd.mime
    }
    if ($hget(httpd.config,VirtualFoldersStatus)) hload -im httpd.virtualfolders %configfile VirtualFolders
    if ($hget(httpd.config,PasswordFoldersStatus)) hload -im httpd.passwordfolders %configfile PasswordFolders
    hload -im httpd.bans %configfile Bans
    socklisten $iif($hget(httpd.config,BindToIP),-d $v1) httpd.listen $hget(httpd.config,ListenPort)
    if ($hget(httpd.config,Logging)) httpd.logwindow
    .timerhttpd.maintenance -io 0 1 $!httpd.maintenance($sock(httpd.client.*,%c.httpd.sockindex),$hget(%c.httpd.hashindex))
    if (-quiet !isin %params) echo $color(info) -st * HTTPd started: $httpd.link
    if ($window(@HTTPd)) echo 10 -i26 @HTTPd $+($asctime(yyyy-mm-dd HH:nn:ss),$chr(9),START,$chr(9),$httpd.link)
    if ($dialog(httpd)) {
      did -a httpd 5 $httpd.link
      .timerhttpd.title -io 0 1 httpd.title
      httpd.title
    }
  }
  elseif (-quiet !isin $1-) echo $color(info) -at * HTTPd is already running.
}

alias -l httpd.logwindow {
  window -hj5000k0mzM $+ $iif($hget(httpd.config,VisibleLogWindow),w3,w0) -t26,43,93,138 @HTTPd $qt($scriptdirCube.ico)
  titlebar @HTTPd - Server log
}

on *:exit: {
  if ($sock(httpd.listen)) {
    unset %c.httpd.*
    if ($hget($1,CacheDirectory)) noop $findfile($v1,????????????????????????????????????????,0,0,.remove $qt($parms))
  }
}

alias httpdstop {
  set -l %params $1-
  if ($sock(httpd.listen)) || (-force isin %params) {
    if ($hget($1,CacheDirectory)) noop $findfile($v1,????????????????????????????????????????,0,0,.remove $qt($parms))
    tokenize 32 httpd.passwordfolders httpd.virtualfolders httpd.mime httpd.config httpd.bans
    hfree -w $*
    .fclose httpd.*
    sockclose httpd.*
    unset %c.httpd.*
    .timerhttpd.maintenance off
    window -c @HTTPd
    if (-quiet !isin %params) echo $color(info) -at * HTTPd stopped.
    if ($dialog(httpd)) {
      .timerhttpd.title off
      did -r httpd 5
      httpd.title
    }
  }
  elseif (-quiet !isin %params) echo $color(info) -at * HTTPd is not running.
}

alias httpd.link return $+(http://,$iif($ip,$v1,127.0.0.1),$iif(($sock(httpd.listen).port) && ($v1 != 80),: $+ $v1),/)