MotionWS 2 — File Browser
MotionWS2v2.0 / MotionWS2v2.0 / MotionWS2.mrc
MotionWS2.mrc — 79.55 KB — Download this file
/*
**
**
** MotionWS 2
**
** You break it, you buy it :)
**
**
*/
;######################################## Menus ########################################
Menu menubar,status,@motionws {
MotionWS-2
. $iif($mws.isrunning,$style(2)) Start:mws.start
. $iif(!$mws.isrunning,$style(2)) Stop:mws.stop
. $iif(!$mws.isrunning,$style(2)) Restart:mws.restart
.-
.Help: run $mws.quote($scriptdirdocs\help.html)
.-
.Configure
..Main:mws.config
..Virtual folders:mws.vfolders
..CGI:mws.managecgi
.Connections:mws.connections
.Unload:mws.unload
.-
.Check for updates:mws.updatecheck
}
;######################################## Public aliases ########################################
;## Returns version info
Alias MWS.Version return 2.0
;## Returns BETA if this is a beta build
Alias MWS.Beta return BETA
;## Returns build number
Alias MWS.build {
var %f = $+(",$scriptdir,\build,")
return $gettok($read(%f,n,$lines(%f)),1,32)
}
;## Saves hashtables and unloads the webserver
Alias MWS.Unload {
mws.stop
mws.savetables
mws.echo MotionWS build $mws.build have been unloaded. To remove this addon completely, delete the directory $scriptdir
mws.echo Your files and settings will still be intact if you wish to reload MotionWS
hfree -w mws.*
.timer -m 1 1 unload -rs $mws.quote($script)
}
;## Starts the webserver
Alias MWS.Start {
if ($mws.isrunning) { mws.echo MWS is already running | return }
if ($version < 6.12) {
mws.echo This build only works with mIRC v6.12 and above. You are currently using $version $+ .
return
}
;## Load hashtables
mws.pbar 1 100 Loading hashtables
mws.loadtables
;## Check some initial settings, and use default settings if they are invalid/don't exist.
mws.pbar 10 100 Checking log files
if (!$mws.gs(logfile)) { .disable #mws.debuglog | mws.dbg No logfile specified, debug logging disabled }
if (!$mws.gs(httplogfile)) { .disable #mws.httplog | mws.dbg No HTTP logfile specified, HTTP logging disabled }
if (!$mws.gs(htdocs)) { mws.ps htdocs $+($scriptdir,htdocs) | mws.dbg No Htdocs directory specified, using default }
;## Check temp, data and htdocs directory
mws.pbar 20 100 Checking directories
MWS.Checkdirs
;## Check previous exit
mws.pbar 30 100 Looking for exit
MWS.CheckExit
mws.ps Exit bad
;## Save the hashtables
mws.pbar 40 100 Temporary saving hashtables
mws.savetables
;## Check CGI executables
mws.pbar 50 100 Checking CGI executables
mws.checkcgi
;## Echo some info, map the vfolder for icons/errorpages/css, and start socklistening
mws.pbar 60 100 Starting webserver
mws.dbg Starting webserver..
mws.dbg Version info: $+($mws.version,/,$mws.build,/,$version,/Win-,$os) $mws.paran(Now sporting $lines($script) lines of code)
mws.dbg Webserver using $nopath($mws.ht.filename($mws.ht.settings)) $mws.paran($file($mws.ht.filename($mws.ht.settings)).size $+ b)
mws.dbg Mapping needed virtual folders...
MWS.CheckVirtual
mws.dbg DLL: $mid($dll($mws.dll.zip,DLLInfo, .),5)
mws.dbg Attempting socklistening..
if (!$mws.socklisten) {
;## Socklistening successfull, webserver online
mws.dbg Webserver ready!
mws.pd isrunning $true
}
else {
;## Socklistening failed, webserver not online
mws.dbg -e Webserver startup failed!
mws.pd isrunning $false
}
mws.pbar 100 100 Done
if ($1 == -c) {
mws.updatecheck
}
elseif ($mws.gs(checkforupdateonstart) == true) {
mws.updatecheck
}
mws.pbar -c
}
;## Stops the webserver
Alias MWS.Stop {
if (!$mws.isrunning) { mws.echo MWS Webserver is not running | return }
;## Loop through open file streams to count them
var %i = 1, %t = $fopen(0), %tfs = 0, %tf = 0, %ts = 0
while (%i <= %t) {
if (mws.* iswm $fopen(%i)) { inc %tfs }
inc %i
}
;## Count temporary files and sockets
var %tf = $findfile($mws.tempdir,*,0,0,.remove $mws.quote($1-)), %ts = $sock(mws.*,0)
;## Close sockets
sockclose mws.*
MWS.ps Exit ok
;## Save hashtables
MWS.savetables
;## Echo some info before file streams are closed
MWS.Dbg Webserver stopped $mws.paran(TotalFilestreams= $+ %tfs $+ ; TotalTempfiles= $+ %tf $+ ; TotalSockets= $+ %ts $+ ;)
;## Close filestreams and timers
.fclose mws.*
.timermws* off
mws.pd isrunning $false
}
;## Restarts the webserver
Alias MWS.Restart {
if ($mws.isrunning) {
MWS.Stop
MWS.Start
}
else {
mws.echo MWS Webserver is not running, can't stop
mws.start
}
}
;## Stops the webserver, saves hashtables, and outputs "mIRC exiting" to debug buffer
Alias MWS.Exit {
MWS.Stop
MWS.Dbg mIRC exiting
}
;## Opens the configuration dialog
Alias MWS.setup { mws.config }
Alias MWS.config {
if (!$dialog(mws.config)) { dialog -m mws.config mws.config }
}
Alias mws.vfolders {
if (!$dialog(mws.vfolders)) { dialog -m mws.vfolders mws.vfolders }
}
Alias MWS.managecgi {
if (!$dialog(mws.cgi)) { dialog -m mws.cgi mws.cgi }
}
;## Settings manipulation commands
;## /MWS.ChangeHtdocs <dir>
;## Changes the htdocs directory, also in run-time
Alias Mws.ChangeHtdocs {
var %dir = $1-
if (!$mws.isrunning) {
mws.loadtables
}
mws.ps Htdocs %dir
if (!$mws.isrunning) {
mws.savetables
}
}
;## /MWS.Changeport <port number>
;## Changes listening port to the specified port number, also in run-time
Alias MWS.ChangePort {
var %port = $1, %sockname = $mws.listenname
if (%port !isnum) {
mws.dbg -e Invalid port number, could not change port
return
}
if (!$mws.isrunning) {
;## If MWS is not running, we load the tables, put the new port number into the hashtable, and save the tables again
mws.loadtables
mws.ps ListenPort %port
mws.savetables
return $true
}
else {
mws.ps ListenPort %port
var %oldport = $sock(%sockname).port
sockclose %sockname
if ($portfree(%port)) {
socklisten %sockname %port
mws.dbg Port changed to %port
return $true
}
else {
mws.dbg -e Could not change port, port %port not free. Going back to using port %oldport
socklisten %sockname %oldport
}
}
}
;## /MWS.ChangeDebugLog <filename>
;## Changes the debug logging file to the filename specified
Alias MWS.ChangeDebugLog { mws.ps Logfile $1- }
;## /MWS.ChangeHtaccess <filename>
;## Changes the htaccess filename to the filename specified
Alias MWS.ChangeHtaccess { mws.ps Htaccess $1 }
;## /MWS.ChangeDefGet <true|false>
;## Changes the default folder download property
Alias MWS.ChangeDefGet { mws.ps DefGet $1 }
;## /MWS.ChangeDefList <true|false>
;## Change the default folder listing property
Alias MWS.ChangeDefList { mws.ps DefList $1 }
;## /MWS.SetMaxCPS <Maximum characters/bytes per second>
;## Sets the maximum upload bandwidth usage in CPS (bytes/sec)
Alias MWS.SetMaxCPS { mws.ps MaxCPS $1 }
;## /MWS.ChangeDateFormat <dateformat>
;## Changes the date format used in directory listing
Alias MWS.ChangeDateFormat { mws.ps DateFormat $1 }
;######################################## Casual Events ########################################
On *:Exit: {
MWS.Exit
}
On *:Load: {
var %wasrunning = $mws.gd(wasrunning), %updated = $mws.gd(updated)
if (%updated) {
mws.echo MWS has been updated! Now using build $mws.build
if (%wasrunning) { mws.start }
else {
mws.echo Use /mws.start to start MWS
}
mws.pd wasrunning $false
mws.pd updated $false
}
else {
mws.echo -s Use /mws.config to configure MotionWS v $+ $mws.version $+ .
}
}
;######################################## Socket events ########################################
On *:socklisten:$($mws.listenname): {
var %socknameok = $true, %sockname
;## Check if sockname exists
while (%socknameok) {
%sockname = $MWS.CreateSockname
if (!$sock(%sockname)) { %socknameok = $false }
}
;## Accept socket
sockaccept %sockname
;## Check for errors
if ($sockerr) {
mws.dbg -e Recieved socket error from %sockname $mws.paran(Sockerr: $sockerr - Winsock msg: $sock(%sockname).wsmsg) - Type: Listen/Connect
return
}
;## Output debug info and wait for data
mws.dbg Connection recieved, using socket name %sockname $+ , IP: $sock(%sockname).ip
}
On *:sockread:mws.*: {
;## Error check
if ($sockerr) {
mws.dbg -e Recieved socket error from %sockname $mws.paran(Sockerr: $sockerr - Winsock msg: $sock(%sockname).wsmsg) - Type: Sockread
return
}
var %sockname = $sockname, %read = $true, %handle, %filename
;## Loop and read data from socket
while (%read) {
sockread &data
;## Set filenames
%filename = $mws.quote($mws.gettempfilename(%sockname,-nRecvd).filename)
%handle = $mws.gettempfilename(%sockname,-nRecvd).name
;## Check if file handle is already open. If not, open it.
if (!$mws.isfileopen(%handle)) { .fopen $iif(!$exists($mws.quote(%filename)),-n) %handle $mws.quote(%filename) }
;## Set file pointer to end of file, write incoming data
.fseek %handle $file(%filename).size
.fwrite -b %handle &data
.fclose %handle
;## Avoid duplicate header checks, and consequently, responses
if ($mws.gd($sockname $+ .gotheader) != $true) {
;## If header have been recieved, parse it
if ($mws.headercheck(%sockname)) {
mws.pd $sockname $+ .gotheader $true
mws.rawparse %sockname
return
}
}
if ($sockbr == 0) { %read = $false }
}
}
;## Executes cleanup alias
On *:sockclose:mws.*: {
mws.sockclose $sockname
}
;######################################## Local aliases ########################################
;## This alias executes the cleanup alias whenever a mws socket is closed manually
Alias -l sockclose {
if ($1) {
mws.sockclose $1
sockclose $1
}
}
;######################################## Core aliases ########################################
;## Loads hashtables
Alias MWS.LoadTables {
if (!$hget($mws.ht.settings)) { hmake $mws.ht.settings 100 }
hload -oi $mws.ht.settings $mws.quote($mws.ht.filename($mws.ht.settings)) Settings
if (!$hget($mws.ht.vfolders)) { hmake $mws.ht.vfolders 100 }
hload -oi $mws.ht.vfolders $mws.quote($mws.ht.filename($mws.ht.vfolders)) Folders
if (!$hget($mws.ht.cgi)) { hmake $mws.ht.cgi 100 }
hload -oi $mws.ht.cgi $mws.quote($mws.ht.filename($mws.ht.cgi)) CGI
if (!$hget($mws.ht.inHeaders)) { hmake $mws.ht.inHeaders 100 }
if (!$hget($mws.ht.outHeaders)) { hmake $mws.ht.outHeaders 100 }
if (!$hget($mws.ht.Dynamic)) { hmake $mws.ht.Dynamic 100 }
if (!$hget($mws.ht.Mime)) { hmake $mws.ht.Mime 100 }
hload -oi $mws.ht.mime $mws.quote($mws.ht.filename($mws.ht.mime)) Mime-Types
}
;## Saves hashtables
Alias MWS.SaveTables {
if ($hget($mws.ht.settings)) {
hsave -oi $mws.ht.settings $mws.quote($mws.ht.filename($mws.ht.settings)) Settings
hsave -oi $mws.ht.vfolders $mws.quote($mws.ht.filename($mws.ht.vfolders)) Folders
hsave -oi $mws.ht.cgi $mws.quote($mws.ht.filename($mws.ht.cgi)) CGI
}
}
;## Checks if the previous exit was forceful
Alias MWS.CheckExit {
if ($mws.gs(Exit) == bad) {
mws.dbg -w MotionWS was not shut down properly last time, some settings might have been lost
}
}
;## Checks virtual folders
Alias MWS.CheckVirtual {
if (!$mws.getvirtualfolder(/mws2_data)) {
mws.addvirtualfolder -g /mws2_data $mws.datadir $+ \ $+ webdata
}
if (!$exists($mws.getvirtualfolder(/mws2_data))) {
mws.addvirtualfolder -g /mws2_data $mws.datadir $+ \ $+ webdata
}
}
;## Starts listening on the configured socket
Alias MWS.Socklisten {
var %port = $mws.gs(Listenport)
;## Close the socket in case it already exists
sockclose $MWS.ListenName
;## Check for port availability
if (!$portfree(%port)) { mws.dbg -f Port %port not free, unable to listen for connections | return err }
;## Start listening
socklisten $MWS.ListenName $mws.gs(Listenport)
mws.dbg Now listening for connections on port %port
}
;## Checks that all needed directories exists, should be self-explainatory
Alias MWS.CheckDirs {
mws.dbg Checking directories...
var %basedir = $scriptdir $+ \
if (!$isdir($mws.datadir)) { mws.dbg -f Data directory does not exist. Reinstall required. Errors might follow | return }
else { mws.dbg > Data directory OK }
if (!$isdir($mws.tempdir)) {
mws.dbg > Temp directory does not exist, creating..
.mkdir $mws.quote($mws.tempdir)
mws.dbg > Temp directory created, directory OK
}
else { mws.dbg > Temp directory OK }
if (!$isdir($mws.htdocsdir)) {
mws.dbg > Htdocs directory does not exist, creating..
.mkdir $mws.quote($mws.htdocsdir)
mws.dbg > Htdocs directory created, directory OK
}
else { mws.dbg > Htdocs directory OK }
}
;## Checks all cgi executables as given in the CGI hashtable
Alias MWS.CheckCGI {
mws.dbg Check CGI executables...
var %ht = $mws.ht.cgi, %i = 1, %t = $hget(%ht,0).item, %item, %data, %execs
while (%i <= %t) {
%item = $hget(%ht,%i).item
%data = $hget(%ht,%item)
if (%data !isin %execs) {
%execs = %execs %data
if (!$exists($mws.quote(%data))) {
mws.dbg -w CGI Executable $mws.quote(%data) does not exists
}
else {
mws.dbg > $nopath(%data) OK
}
}
inc %i
}
}
/*
* This alias parses the raw data sent from the client. Each header is loaded into the InHeader hashtable, and
* a secondary parsing alias is called when this has been completed.
*/
Alias MWS.RawParse {
var %sockname = $1, %filename = $mws.quote($mws.gettempfilename(%sockname,-nRecvd).filename), %len = $file(%filename).size, %handle = $mws.gettempfilename(%sockname,-nRecvd).name
if (!$mws.isfileopen(%handle)) {
;## File does not have a stream opened, open a stream
.fopen $iif(!$exists($mws.quote(%filename)),-n) %handle $mws.quote(%filename)
}
;## Loop through file
var %i = 1, %t = $lines(%filename), %line
while (%i <= %t) {
.fseek -l %handle %i
%line = $fread(%handle)
if (!%line) {
;## Blank line, all headers have been loaded, secondary parsing can be done
mws.dbg Loaded headers from %sockname $+ , parsing..
.fclose %handle
mws.parse %sockname
break
}
;## Load headers into header hashtable here
;echo REQUEST -> %sockname %line
mws.inheader %sockname %line
inc %i
}
if ($mws.isfileopen(%handle)) { .fclose %handle }
}
Alias MWS.Parse {
;## First of all, load headers into a hashtable
var %sockname = $1, %filename = $mws.quote($mws.gettempfilename(%sockname,-nRecvd).filename), %handle = $mws.gettempfilename(%sockname,-nRecvd).name
;## All headers are now loaded into a hashtable, and can be effectively parsed
;## First, get the requested url and translate it
var %req = $mws.inheader(%sockname,_request_)
if (GET*HTTP/1.? iswm %req) {
;## It's a GET request, get url
var %url = $gettok(%req,2,32)
mws.dbg Got url -> %url Method: Get
mws.pd %sockname $+ .method Get
mws.translate %sockname %url
}
elseif (HEAD*HTTP/1.? iswm %req) {
;## It's a HEAD request, get url
var %url = $gettok(%req,2,32)
mws.dbg Got url -> %url Method: Get
mws.pd %sockname $+ .method Head
mws.translate %sockname %url
}
elseif (POST*HTTP/1.? iswm %req) {
;## It's a POST request, get url
var %url = $gettok(%req,2,32)
mws.dbg Got url -> %url Method: Post
mws.pd %sockname $+ .method Post
mws.translate %sockname %url
}
else {
;## Error in HTTP request
mws.dbg Client sendt a bad request, or no request at all $mws.paran(%req)
mws.response %sockname 400
}
}
;## Checks to see if the header have been recieved, and that all of the message-body have been recieved
alias MWS.headercheck {
var %sockname = $1, %filename = $mws.quote($mws.gettempfilename(%sockname,-nRecvd).filename), %len = $file(%filename).size, %handle = $mws.gettempfilename(%sockname,-nRecvd).name
;## Load file into a binary variable and scan for a double $crlf, which means "end-of-header", which again
;## means that the header can be parsed
bread %filename 0 %len &data
;## Scan for the double crlf offset
var %offset = $bfind(&data,1,13 10 13 10)
if (%offset) {
;## All the headers have been recieved, let's see if we got the whole message body (if there is a message-body)
if (!$mws.isfileopen(%handle)) {
;## File does not have a stream opened, open a stream
.fopen $iif(!$exists($mws.quote(%filename)),-n) %handle $mws.quote(%filename)
}
var %i = 1, %t = $lines(%filename), %line, %lof, %conlen
while (%i <= %t) {
;## Get the content-length value
.fseek -l %handle %i
%line = $fread(%handle)
if ($gettok(%line,1,58) == Content-length) {
;## Do stuff to determine if message body have been recieved or not, then return either $true or $false
var %content-length = $gettok(%line,2,32)
%offset = $calc(%offset + 3)
%lof = $file(%filename).size
%conlen = $calc(%lof - %offset)
if (%conlen >= %content-length) {
mws.dbg POST data applies, stripping from recieved data and moving into new file
;## copy the message body into another file
;## Create write filename
var %wfilename = $mws.quote($mws.gettempfilename(%sockname,-nPostData).filename)
write -c %wfilename
;## Read post data into variable
bread %filename %offset %conlen &postdata
;## Cut off the original file
btrunc %filename %offset
;## Write post data to new file
bwrite %wfilename -1 -1 &postdata
return $true
}
else { break }
}
inc %i
}
;## Close filestream
.fclose %handle
return $true
}
return $false
}
Alias MWS.ListFolder {
/*
* def: MWS.ListFolder(%sockname,-n%N)
* %N:
* - Additional naming for the file, can be either alphanumerical or numerical values
* %sockname:
* - The sockname of the current connection
*/
;## Set initial variables
var %sockname = $1, %vfolder = $2, %folder = $mws.quote($3-), %win = $+(@,%sockname), %ticks = $ticks, %name, %filename, %indexof = $+(/,$mws.fixslashes($nopath(%vfolder)))
;## Create window
window -c %win
window -lsh %win 0 0 0 0
;## Search directory
var %x = $findfile(%folder,*,0,1,aline %win $nopath($1-) : $bytes($file($1-).size).suf : $file($1-).mtime), %x = $finddir(%folder,*,0,1,aline %win $+($chr(33),dir,$chr(33),$nopath($1-)))
var %i = 1, %t = $line(%win,0), %curfile, %curdata, %fullpath, %filesize, %modified, %isdir, %dateformat = $mws.gs(DateFormat)
;## Get filenames
%name = $MWS.GetTempFilename(%sockname,-nDirList).name
%filename = $MWS.Quote($MWS.GetTempFilename(%sockname,-nDirList).filename)
;## Check if filehandle already exists (not likely) and close it
if ($MWS.IsFileOpen(%name)) { .fclose %name }
;## Open file stream
.fopen -n %name %filename
;## Create html/table beginning
.fwrite -tn %name <html><head><title>Index of $mws.rawurldecode(%indexof) $+ </title></head><link rel="stylesheet" type="text/css" href="/mws2_data/Stylesheet.css"><body><h2>Index of $mws.rawurldecode(%indexof) $+ </h2><table>
.fwrite -tn %name <tr><td></td><td class="DirListFilename">File</td><td class="DirListFileSize">Size</td><td> </td><td class="DirListFileModified">Modified</td></tr>
.fwrite -tn %name <tr><td colspan="5"><hr width="100%"></td></tr>
if (%vfolder != /) { .fwrite -tn %name $+(<tr><td><img src="/mws2_data/icons/back.jpg"></td><td class="DirListFilename" width="60%"><a href=",$nofile(%vfolder),"><b>Parent Folder</b></a></td><td></td><td></td></tr>) }
;## Check if it's the htaccess file
var %afile = $mws.gs(AccessFile), %line
;## Loop and dump html into binvar &data
while (%i <= %t) {
%isdir = $false | %line = $line(%win,%i) | %curfile = $gettok(%line,1,58)
if (%curfile == %afile) { inc %i | continue }
%filesize = $gettok(%line,2,58) | %modified = $asctime($remove($gettok(%line,3,58),$chr(32)), %dateformat)
if ($gettok(%line,1,33) == dir) { var %curfile = $gettok(%line,2,33), %isdir = $true }
if (%isdir) { .fwrite -tn %name $+(<tr><td><img src="/mws2_data/icons/folder.jpg"></td><td class="DirListFilename" width="60%"><a href=",%vfolder,$iif(%vfolder != /,/),%curfile,/">,%curfile,/</a></td><td>-</td><td></td><td>-</td></tr>) }
else { .fwrite -tn %name $+(<tr><td><img src="/mws2_data/icons/file.jpg"></td><td class="DirListFilename" width="60%"><a href=",%vfolder,$iif(%vfolder != /,/),%curfile,">,%curfile,</a></td><td class="DirListFileSize">,%filesize,</td><td> </td><td class="DirListFileModified" align="right" nowrap>,%modified,</td></tr>) }
inc %i
}
var %ttime = $calc(($ticks - %ticks) / 1000)
.fwrite -tn %name <tr><td colspan="5"><hr width="100%"></td></tr>
.fwrite -tn %name <tr><td colspan="5" class="DirListServerInfo"> $mws.serverreply on port $mws.gs(ListenPort) </td></tr>
.fwrite -tn %name <tr><td colspan="5" class="DirListServerInfo">Page built in %ttime $+ s</td></tr>
.fwrite -tn %name </table></body></html>
mws.dbg Directory list time: %ttime Objects: %t
;## Pass on arguments to the MWS.SendTempFile alias which will pass it further on to the socket sending code
MWS.SendTempFile %sockname -nDirList
;## Echo debug info and finish up
window -c %win
}
Alias MWS.WriteTempFile {
/*
* def: $MWS.WriteTempFile(%sockname, [-n%N], %data)
* %N:
* - Additional naming for the file, can be either alphanumerical or numerical values
* %sockname:
* - The sockname of the current connection
* %data
* - The data to be stored in the file
*/
;## Set some initial variables
var %sockname = $1, %N = $2, %data, %name, %filename
if (-n* iswm %N) { %data = $3- } | else { %data = $2- }
;## Generate filenames
%name = $mws.gettempfilename(%sockname,%N).name
%filename = $mws.gettempfilename(%sockname,%N).filename
;## Check parameters
if (!$2) { mws.dbg -f Not enough parameters for temporary file writing | return $false }
;## Quote filename for spaced directory compatability
%filename = $mws.quote(%filename)
;## Check if the file handle is already active, and if the filename matches
if (!$mws.isfileopen(%name)) {
if ($exists(%filename)) {
mws.dbg Temporary file already exists with no handle, trying deletion (not likely to work, file probably locked by error)
.remove %filename
mws.dbg File removed, continuing..
}
mws.dbg Opening temporary file %filename $mws.paran(%name) for writing..
.fopen -n %name %filename
}
else {
;## Here's the filename matching check
if ($mws.quote($fopen(%name).fname) != %filename) { mws.dbg -f File handle already in use for a different file | return }
else { mws.dbg File already open, continuing.. }
}
;## We're set to go, write data, check $ferr, and return $true or $false, depending on success or failure
mws.dbg File ready, writing data..
.fwrite %name %data
if ($ferr) { mws.dbg -e File writing for temporary file %filename $mws.paran(%name) failed $mws.paran($ferr) $+ , Closing file handle and returning script processing | .fclose %name | return $false }
else { return $true }
;## The MWS.SendTempFile alias will close the file handler, for security precautions.
}
Alias MWS.SendTempFile {
;## The SocketSending alias must take care of temp file deletion, as this alias does NOT do so
;## Set some initial variables
var %sockname = $1, %N = $2, %name, %filename
;## Generate filenames
%name = $mws.gettempfilename(%sockname,%N).name
%filename = $mws.gettempfilename(%sockname,%N).filename
;## Quote filename for spaced directory compatability
%filename = $mws.quote(%filename)
;## Check if file handle exists
if (!$mws.isfileopen(%name)) {
mws.dbg -e Could not send temporary file, file handle %name does not exists
}
else {
mws.dbg Sending temporary file %filename to socket $mws.quote(%sockname) using handle $mws.quote(%name)
.fclose %name
mws.sendfile %sockname %filename
}
}
Alias MWS.GetTempFilename {
;## Set some initial variables
var %sockname = $1, %N = $2
;## Generate filenames
if (-n* iswm %N) { %N = $mid(%N,3) | var %name = $+(%sockname,.,%N,.tmp), %filename = $+($mws.tempdir,\,%sockname,.,%N,.tmp) }
else { var %name = $+(%sockname,.tmp), %filename = $+($mws.tempdir,\,%sockname,.tmp) }
;## Return values
if ($prop == name) { return %name }
if ($prop == filename) { return %filename }
}
Alias MWS.Debug { mws.dbg $1- }
Alias MWS.Dbg {
var %d, %data
if ($1 == -f) { %d = Debug/FATAL ERROR: | %data = $2- }
elseif ($1 == -e) { %d = Debug/ERROR: | %data = $2- }
elseif ($1 == -w) { %d = Debug/WARNING: | %data = $2- }
else { %d = Debug: | %data = $1- }
if ($isalias(mws._dbg)) { mws._dbg %d %data }
if ($isalias(mws.dbg.log)) { mws.dbg.log %d %data }
}
;## Turn this group on to enable debugging
#MWS.Debug on
Alias -l mws._dbg {
window @MotionWS
echo @MotionWS $1-
}
#MWS.Debug end
;## Turn this group on to enable debug logging
#MWS.DebugLog off
Alias -l mws.dbg.log {
var %file = $MWS.gs(logfile), %handle = mws.logfile
if (!%file) { return }
if (!$mws.isfileopen(%handle)) { .fopen $iif(!$exists($mws.quote(%file)),-n) %handle $mws.quote(%file) }
.fseek -l %handle $calc($lines(%file) + 1)
.fwrite -n %handle $1-
.timermwslog 1 2 .fclose %handle
}
#MWS.DebugLog end
#MWS.HttpLog off
Alias -l mws.http.log {
var %file = $MWS.gs(httplogfile), %handle = mws.httplogfile
if (!$mws.isfileopen(%handle)) { .fopen $iif(!$exists(%file),-n) %handle $mws.quote(%file) }
.fseek -l %handle $calc($lines(%file) + 1)
.fwrite -n %handle $1-
.timermwshttplog 1 2 .fclose %handle
}
#MWS.DebugLog end
;## Checks if a file handle already exists
Alias MWS.IsFileOpen {
if ($fopen($1)) { return $true }
else { return $false }
}
Alias MWS.Method { return $mws.gd($1 $+ .method) }
Alias MWS.ServerReply { return $+(MotionWS/,$mws.version) }
Alias MWS.DateReply { return $asctime($ctime, ddd $+ $chr(44) dd mmm yyyy HH:nn:ss) GMT }
Alias MWS.Quote { var %r = $remove($1-,") | return $+(",%r,") }
Alias MWS.Paran { return $+($chr(40),$1-,$chr(41)) }
Alias MWS.Datadir return $+($scriptdir,data)
Alias MWS.Htdocsdir return $mws.gs(htdocs)
Alias MWS.Tempdir return $+($scriptdir,temp)
Alias MWS.Docsdir return $+($scriptdir,docs)
Alias MWS.Webdir return $+($scriptdir,data\webdata)
Alias MWS.Ht.Settings { return mws.settings }
Alias MWS.Ht.CGI { return mws.cgi }
Alias MWS.Ht.Vfolders { return mws.vfolders }
Alias MWS.Ht.InHeaders { return mws.inHeaders }
Alias MWS.Ht.OutHeaders { return mws.outHeaders }
Alias MWS.Ht.Dynamic { return mws.Dynamic }
Alias MWS.Ht.Mime { return mws.Mime }
Alias MWS.Ht.All { return mws.* }
Alias MWS.dll.zip { return $+($scriptdir,dll\zip\munzip.dll) }
Alias MWS.isrunning {
if ($mws.gd(isrunning) == $true) && ($sock($mws.listenname).status == listening) { return $true }
else { return $false }
}
Alias MWS.echo { echo -s $+(MWS/,$mws.version,:) $1- }
;## Get settings
Alias MWS.gs { return $hget($mws.ht.settings,$1-) }
Alias MWS.ps { hadd $mws.ht.settings $1 $2- }
;## Get dynamic
Alias MWS.gd { return $hget($mws.ht.dynamic,$1-) }
Alias MWS.pd { hadd $mws.ht.dynamic $1 $2- }
;## Get vfolder
Alias MWS.gf { return $hget($mws.ht.vfolders,$1-) }
Alias MWS.pf { hadd $mws.ht.vfolders $1 $2- }
;## Get cgi
Alias MWS.gc { return $hget($mws.ht.cgi,$1-) }
Alias MWS.pc { hadd $mws.ht.cgi $1 $2- }
;## Get mime-type
Alias MWS.gm {
var %d = $1-, %mime, %return
if ($left(%d,1) != .) { %mime = $+(.,%d) }
else { %mime = %d }
%return = $hget($mws.ht.mime,%mime)
if (!%return) { %return = text/plain }
return %return
}
;## Save query string
Alias MWS.pq {
var %s = $1, %qs = $2-
mws.pd $+(%s,querystring) %qs
}
;## Get query string or data
Alias MWS.gq {
var %s = $1, %d = $2-, %qs, %item, %part, %data
%qs = $mws.gd($+(%s,querystring))
if (!$prop) { return %qs }
var %i = 1, %t = $numtok(%qs,38)
while (%i <= %t) {
%part = $gettok(%qs,%i,38)
%item = $gettok(%part,1,61)
%data = $gettok(%part,2,61)
if ($prop == item) && (%d == %item) {
return %data
}
inc %i
}
}
Alias MWS.ListenName { return MWS.Listen }
Alias MWS.CreateSockname { var %sockname = $+(mws.,$r(1,9),$r(1,9),$r(1,9),$r(1,9),$r(1,9)) | return %sockname }
Alias MWS.Htdocs { return $mws.gs(htdocs) }
Alias MWS.ht.filename { return $+($scriptdir,\,Data\,$1-,.ini) }
Alias MWS.FixSlashes {
var %d = $1-, %i = 1, %t = 20
while (%i <= %t) {
%d = $replace(%d,$str(\,%t),/)
%d = $replace(%d,$str(/,%t),/)
dec %t
}
while ($right(%d,1) == /) {
%d = $mid(%d,1,-1)
}
return %d
}
Alias MWS.GetVirtualFolder {
;## $MWS.GetVirtualFolder(vfolder)
;## Returns the folder to which the virtual folder is mapped
;## Properties:
;## .Get - returns true if the folder can be downloaded from
;## .List - returns true if the folder contents can be listed
;## .Username - returns username if the folder is password protected
;## .Password - returns password if the folder is password protected
;## .IsPwd - returns true if the folder is password protected
var %f = $1-, %data = $MWS.gf(%f), %i = 1, %t = $numtok(%data,124), %item, %ispwd, %username, %password
while (%i <= %t) {
%item = $gettok(%data,%i,124)
var % $+ $gettok(%item,1,61) $gettok(%item,2,61)
inc %i
}
if (%username) { %ispwd = true }
if ($prop == list) { return %list }
if ($prop == get) { return %get }
if ($prop == ispwd) { return %ispwd }
if ($prop == username) { return %username }
if ($prop == password) { return %password }
elseif (!$prop) { return %rfolder }
}
Alias MWS.DeleteVirtualFolder {
var %tbl = $mws.ht.vfolders
if ($hget(%tbl,$1)) {
hdel %tbl $1
mws.dbg Removed folder $1 from the virtual folder database
}
else {
mws.dbg -e Could not remove folder $1 from the virtual folder database, did not exist
}
}
Alias MWS.AddVirtualFolder {
;## /mws.addvirtual folder -lg <virtual folder> <system folder>
;## -l: Folder can be listed
;## -g: Files can be downloaded from this folder
;## Replace any spaces with %20 to add spaced directories
;## Set variables
if ($1 == /?) || ($1 == -?) || ($1 == ?) { echo Usage: /mws.addvirtual folder -lg <virtual folder> <system folder> | return }
if (-* iswm $1) {
var %switch = $1, %vfolder = $2, %rfolder = $3-
}
else {
var %vfolder = $1, %rfolder = $2-
}
var %get, %list, %pprotect, %username, %password
;## Sorting the switches out..
if (-*l* iswm %switch) { %list = true }
else { %list = false }
if (-*g* iswm %switch) { %get = true }
else { %get = false }
if (-*p* iswm %switch) {
%pprotect = true
%username = $2
%password = $3
%vfolder = $4
%rfolder = $5-
if (!$4) && (!$5-) { mws.dbg -e Username and password not given, virtual folder could not be added | return }
}
;## Check for illegal characters
if ($chr(32) isin %vfolder) || ($chr(58) isin %vfolder) || ($chr(42) isin %vfolder) || ($chr(63) isin %vfolder) || ($chr(34) isin %vfolder) || ($chr(60) isin %vfolder) || ($chr(62) isin %vfolder) || ($chr(124) isin %vfolder) {
mws.dbg -e Virtual folder contained one or more illegal characters, folder could not be added (Ascii $chr(35) $+ $asc($ifmatch) $+ )
return
}
;## Check for existing rfolder
if (!$isdir(%rfolder)) {
mws.dbg Warning: Given system folder does not exist (will continue)
}
;## Check if vfolder is /, that cannot be added
if (%vfolder == /) {
mws.dbg -e You can not map / as a virtual folder
return
}
;## Fix slash errors
%vfolder = / $+ %vfolder
while ($right(%vfolder,1) == /) {
%vfolder = $mid(%vfolder,1,-1)
}
%vfolder = $mws.fixslashes(%vfolder)
;## Check if vfolder already exists
if ($mws.getvirtualfolder(%vfolder)) {
mws.dbg Warning: Virtual folder already exists, previous entry will be overwritten $mws.paran($+($mws.getvirtualfolder(%vfolder).list,:,$mws.getvirtualfolder(%vfolder).get,:,%vfolder,-->,$mws.getvirtualfolder(%vfolder)))
}
;## Add the folder in the hashtable
mws.dbg Mapping virtual folder %vfolder to physical folder %rfolder with permissions: list= $+ %list get= $+ %get $iif(%pprotect,$mws.paran(Using password: yes),$mws.paran(Using password: no))
mws.pf %vfolder $+(list=,%list,|get=,%get,$iif(%pprotect,|username= $+ %username $+ |password= $+ %password),|rfolder=,%rfolder)
}
;## Adds and retrieves headers from the client into a hashtable
;## /mws.inheader %sockname %header
;## Use $mws.header(%sockname,_request_) to retrieve the request-line
Alias MWS.InHeader {
var %sockname = $1, %tbl = $mws.ht.inheaders, %key = $+(%sockname,.,$2), %data = $3-, %all = $2-
if (!$isid) {
if (GET*HTTP/1.? iswm %all) {
hadd %tbl $+(%sockname,.,_request_) %all
}
if (HEAD*HTTP/1.? iswm %all) {
hadd %tbl $+(%sockname,.,_request_) %all
}
if (POST*HTTP/1.? iswm %all) {
hadd %tbl $+(%sockname,.,_request_) %all
}
else {
hadd %tbl %key %data
}
}
else {
return $hget(%tbl,%key)
}
}
;## Adds/retrieves a header to the response header that should be returned to the client
;## /mws.outheader %sockname %header %header data
;## $mws.outheader(%sockname,header/_response_)
Alias MWS.OutHeader {
var %sockname = $1, %tbl = $mws.ht.outheaders, %key = $+(%sockname,.,$2), %data = $3-, %all = $2-
if (!$isid) {
if (HTTP/1.? * iswm %all) {
hadd %tbl $+(%sockname,.,_response_) %all
}
else {
hadd %tbl %key %data
}
}
else {
return $hget(%tbl,%key)
}
}
;## Aliases for encoding and decoding urls. Written by Techster.
;## These aliases can be found on mircscripts.org.
;## Mws.rawurldecode have been altered to deal with "%24", "%5C" and "+".
;## Taken from MotionWS1
Alias Mws.rawurlencode { var %encode = $1- | while ($regex($eval(%encode,1), /([^a-zA-Z0-9_\-\.\\\/])/)) { var %t = $regsub($eval(%encode,1), /([^a-zA-Z0-9_\-\.\\\/])/, $+(,$base($asc($regml(1)),10,16,2)), %encode) } | return $replace(%encode, , %) }
Alias Mws.rawurldecode { var %decode = $replace($eval($1-,1), +, $eval(%20,0)), %decode = $replace($eval(%decode,1), $eval(%5C,0), ), %decode = $replace($eval(%decode,1), $eval(%24,0), $eval($,0)) | while ($regex($eval(%decode,1), /\%([a-fA-F0-9]{2})/)) { var %t = $regsub($eval(%decode,1), /\%([a-fA-F0-9]{2})/, $chr($base($regml(1),16,10)), %decode) } | return $replace(%decode, $eval(%20,0), +,,\) }
Alias mws.sockclose {
;## Clean up files, hashtables, file streams
;## Set some variables
var %sockname = $1, %x, %wc, %i, %t, %tf = 0, %ticks = $ticks, %script
;## Check if the socket is related to MotionWS
if (mws.* iswm %sockname) && (%sockname != $mws.listenname) && (%sockname != mws.*) && ($sock(%sockname)) {
%wc = $+(*,%sockname,*)
mws.dbg Cleaning up after socket %sockname $+ ..
;## Delete hashtable entries
hdel -w $mws.ht.inheaders %wc
hdel -w $mws.ht.outheaders %wc
hdel -w $mws.ht.dynamic %wc
;## Loop through file streams and get the total number, and close any that's related to the socket
%i = 1, %t = $fopen(0)
while (%i <= %t) {
if (%wc iswm $fopen(%i)) { inc %tf }
inc %i
}
.fclose %wc
;## Loop through scripts and search for mws.*
%i = 1 | %t = $script(0)
while (%i <= %t) {
%script = $script(%i)
if (mws.*.tmp iswm $nopath(%script)) {
.unload -rs $mws.quote(%script)
}
inc %i
}
;## Shut down CGI wait timer
.timermws.cgi. $+ %sockname off
;## Delete temporary files related to the socket
%x = $findfile($mws.tempdir,%wc,0,1,.timer 1 1 .remove $mws.quote($1-))
mws.dbg Cleanup finished for socket %sockname $mws.paran(Filestreams= $+ %tf $+ ; Tempfiles= $+ %x) in $calc(($ticks - %ticks) / 1000) $+ s
}
}
Alias MWS.Translate {
;## Translate a requested folder into a physical folder or file that can be listed or sent.
;## If none of these options are available, an error-message should be output
;## Set some initial variables
var %s = $1, %ovfolder = $2, %vfolder = $mws.rqstring($2), %qs = $mws.gqstring($2), %file, %rfolder, %sockname = %s, %username, %password, %realm, %get, %list
mws.pq %s %qs
;## Format url
%vfolder = $mws.fixslashes(%vfolder)
if (!%vfolder) { %vfolder = / }
;## Loop through %vfolder, and find first mapped folder.
var %t = 1, %i = $numtok(%vfolder,47), %checkfolder, %extrafolder, %ismapped = $false
while (%i >= %t) {
%checkfolder = $mws.fixslashes(/ $+ $gettok(%vfolder,1- $+ %i,47)) | %extrafolder = $gettok(%vfolder,$calc(%i + 1) $+ -,47)
if ($mws.GetVirtualFolder(%checkfolder)) {
;## We found a mapped folder, set %rfolder to the appropriate values
%rfolder = $mws.GetVirtualFolder(%checkfolder) $+ \ $+ %extrafolder
%ismapped = $true
break
}
dec %i
}
if (!%ismapped) {
;## Could not find a mapped folder, add the whole schebang to the htdocs
%rfolder = $+($mws.htdocs,\,%vfolder)
}
;## If the requested folder is "/", then set the %rfolder to $mws.htdocs
if (%vfolder == /) { %rfolder = $mws.htdocs }
;## Fix any slashes in the physical folder string
%rfolder = $mws.fixbackslashes(%rfolder)
;## If the rfolder starts with a \, then it's a LAN computer, and we must add another \ at the beginning
if ($mid(%rfolder,1,1) == \) { %rfolder = $+(\,%rfolder) }
;## Fix %XX's
%rfolder = $mws.rawurldecode(%rfolder)
;## Get folder properties, listing/downloading/username/password
if (%ismapped) {
%list = $MWS.GetVirtualFolder(%checkfolder).list
%get = $MWS.GetVirtualFolder(%checkfolder).get
%username = $MWS.GetVirtualFolder(%checkfolder).username
%password = $MWS.GetVirtualFolder(%checkfolder).password
}
;## The folder is a subfolder within the htdocs folder, check for htaccess
else {
%list = $MWS.GetHtaccess(%rfolder).list
%get = $MWS.GetHtaccess(%rfolder).get
%username = $MWS.GetHtaccess(%rfolder).username
%password = $MWS.GetHtaccess(%rfolder).password
}
;## Set default values
var %deflist = false, %defget = false
if (!%list) { %list = $mws.gs(DefList) | %deflist = true }
if (!%get) { %get = $mws.gs(DefGet) | %defget = true }
mws.dbg Extracted properties: Vfolder: %vfolder - Rfolder: %rfolder - $mws.paran($+(List=,%list,;,Get=,%get,;,User=,%username,;,Realm=,%realm) - Default values: $+(%deflist,/,%defget))
mws.dbg Vfolder type: $iif(%ismapped,map/virtual,phys/real)
;## Exploit fix
if (%vfolder == /..) || (%vfolder == ../) || (%vfolder == ..) || (/.. isin %vfolder) {
mws.dbg Possible exploit detected, giving 401 error
mws.response %s 401
return
}
;## Exploit fix 2
if (%rfolder == /..) || (%rfolder == ../) || (%rfolder == ..) || (/.. isin %rfolder) {
mws.dbg Possible exploit detected, giving 401 error
mws.response %s 401
return
}
;## Check the requested url
;## If it's a directory, a / must be appended to the end if it doesn't exist
;## Then the client must be redirected to the new url
if ($isdir(%rfolder)) {
if ($mid(%ovfolder,-1) != /) {
%ovfolder = $+(%ovfolder,/)
mws.outheader %s Location: %ovfolder
mws.response %s 302
return
}
}
;## Check for directoryindex
if ($isdir(%rfolder)) {
var %di = $mws.gs(DirectoryIndex), %i = 1, %t = $numtok(%di,44), %cdi
while (%i <= %t) {
%cdi = $mws.fixbackslashes($+(%rfolder,\,$gettok(%di,%i,44)))
if ($exists(%cdi)) { %rfolder = %cdi | break }
inc %i
}
}
if (%username) {
mws.dbg Authentication required for the requested file/folder...
var %auth = $mws.inheader(%s,Authorization:)
var %usrpass = $decode($gettok(%auth,2,32),m)
var %susername = $gettok(%usrpass,1,58), %spassword = $gettok(%usrpass,2,58)
if (%susername != %username) || (%spassword != %password) {
mws.dbg Authentication failed!
mws.outheader %s WWW-Authenticate: Basic realm="MotionWS $+ $mws.version $+ "
mws.response %s 401
return
}
mws.dbg Authentication successfull, continuing...
}
if ($isdir(%rfolder)) {
;## The requested url is a directory
mws.dbg Requested URL -> directory (Exists: yes)
if (%list == true) {
mws.response %s 200
mws.outheader %s Content-Type: text/html
mws.listfolder %sockname %vfolder %rfolder
}
elseif (%list != true) {
mws.response %s 401
}
}
elseif ($isfile(%rfolder)) {
;## The requested url is a file
mws.dbg Requested URL -> file (Exists: yes)
if (%get == true) {
if ($nopath(%rfolder) == $mws.gs(AccessFile)) {
mws.response %s 401 %rfolder
}
else {
mws.response %s 200 %rfolder
;## Check if it's mhtml
if ($gettok($remove(%rfolder,"),-1,46) == mhtml) {
var %ticks = $ticks
%rfolder = $Mws.mhtml(%s,%rfolder)
.fclose mws.mhtml*
if (%rfolder == $false) {
mws.response %s 500
}
mws.dbg Mhtml executed in $calc(($ticks - %ticks) / 1000) $+ s
}
;## Check if it's a extension to send through CGI
elseif (($mws.gc($gettok($remove(%rfolder,"),-1,46))) && ($mws.gs(CGI) == true)) {
mws.cgi %s $gettok($remove(%rfolder,"),-1,46) %ovfolder %rfolder
return
;## /mws.cgi <sockname> <type> <vfolder> <rfolder>
}
else {
mws.sendfile %s %rfolder
}
}
}
elseif (%get != true) {
mws.response %s 401
}
}
else {
;## The requested url does not exist
mws.dbg Requested URL -> unknown (Exists: no)
mws.response %s 404
}
}
Alias MWS.Response {
;## /Mws.response <sockname> <code> [filename]
var %sockname = $1, %code = $2, %filename = $3-,%ext = $gettok(%filename,$numtok(%filename,46),46), %resp = $mws.codetable(%code)
mws.pd $+(%sockname,respcode) %code
mws.dbg Response: %resp
if (%code == 400) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\400.html)
}
if (%code == 401) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\401.html)
}
if (%code == 403) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\403.html)
}
if (%code == 404) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\404.html)
}
if (%code == 500) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\500.html)
}
if (%code == 200) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: $mws.gm(%ext)
if ($isfile(%rfolder)) { mws.outheader %sockname Content-length: $file(%rfolder).size }
}
if (%code == 302) {
mws.outheader %sockname _response_ %resp
mws.outheader %sockname Content-type: text/html
mws.sendfile %sockname $+($mws.webdir,\errorpages\302.html)
}
}
;## Returns http response code
Alias MWS.CodeTable {
var %j = $1
goto $1
:200 | return HTTP/1.1 200 Ok
:302 | return HTTP/1.1 302 Found
:400 | return HTTP/1.1 400 Bad request
:401 | return HTTP/1.1 401 Unauthorized
:403 | return HTTP/1.1 403 Forbidden
:404 | return HTTP/1.1 404 Not found
:500 | return HTTP/1.1 500 Internal server error
:%j | return Unknown
}
;## Returns info from htaccess files
Alias MWS.GetHtaccess {
var %f = $1-, %f2, %line, %1, %2
;## Check if htaccess can be appended
if ($isfile($+(%f,\htaccess))) {
%f = $+(%f,\htaccess)
}
;## Try removing files, then append htaccess
elseif ($isfile($+($nofile(%f),\htaccess))) {
%f = $+($nofile(%f),\htaccess)
}
;## htaccess didn't exist
else { return $false }
%f = $mws.quote(%f)
;## htaccess exists, open file stream
.fclose HTAccess*
.fopen HTAccess %f
;## Loop and read lines
var %i = 1, %t = $lines(%f)
while (%i <= %t) {
%line = $fread(HTAccess)
if ($mid(%line,1,1) == $chr(59)) { continue }
%1 = $gettok(%line,1,32) | %2 = $gettok(%line,2,32)
if ($prop == %1) { .fclose HTAccess | return %2 }
inc %i
}
.fclose HTAccess
return
}
;## Fixes backslashes
Alias MWS.FixBackSlashes {
var %d = $1-, %i = 1, %t = 20
%d = $replace(%d,/,\)
while (%i <= %t) {
%d = $replace(%d,$str(/,%t),\)
%d = $replace(%d,$str(\,%t),\)
dec %t
}
while ($right(%d,1) == \) {
%d = $mid(%d,1,-1)
}
return %d
}
;## Returns url without query string
Alias MWS.rqstring {
return $gettok($1-,1,63)
}
;## Returns query string, without url
Alias MWS.gqstring {
return $gettok($1-,2,63)
}
Alias MWS.SendFile {
;## /mws.sendfile %sockname [-bN] filename
var %filename, %sockname = $1, %offset, %chunk = 8192, %maxbuf = 16384, %filesize, %maxcps = $mws.gs(MaxCPS), %curcps
if (-b* iswm $2) {
%offset = $mid($2,3)
%filename = $mws.quote($3-)
}
else {
%offset = 0
%filename = $mws.quote($2-)
;## Add some headers
mws.outheader %sockname Content-length: $file(%filename).size
mws.outheader %sockname Date: $mws.datereply
mws.outheader %sockname Server: $mws.serverreply
mws.outheader %sockname Connection: Close
mws.outheader %sockname Accept-Ranges: bytes
if ($mws.gs(GZIP) == true) {
;## Check for Gzip acceptance
var %gclient = $mws.inheader(%sockname,Accept-Encoding:), %gserver = $mws.outheader(%sockname, Content-Encoding:)
if (gzip isin %gclient) && (!%gserver) {
var %gkey = %sockname $+ .gzip
mws.pd %gkey true
;mws.outheader %sockname Content-encoding: gzip
}
}
/*
if ($mws.inheader(%sockname,Range:)) {
;## Check for content-range
var %rline = $gettok($mws.inheader(%sockname,Range:),2,61), %rstart = $gettok(%rline,1,45), %rlen = $gettok(%rline,2,45)
if (!%rlen) { %rlen = $calc($file(%filename).size - 1) }
mws.dbg User-Agent requesting specific range, starts at %rstart bytes, length %rlen bytes
if (%rstart > 0) { %offset = %rstart }
if (%rlen > 0) { mws.pd Rangelen. $+ %sockname $calc(%rlen + 1) }
mws.outheader %sockname Content-Range: bytes $+($iif(%rstart,%rstart,0),-,$iif(%rlen,%rlen,0),/,$file(%filename).size)
mws.outheader %sockname _response_ HTTP/1.1 206 Partial content
hdel -w $mws.ht.outheaders $+(%sockname,.Content-length:*)
}
*/
;## Send the headers
mws.SendHeaders %sockname %filename
;## Output to http log
if ($isalias(mws.http.log)) {
mws.http.log $sock(%sockname).ip - - $asctime($ctime,[dd/mmm/yyyy:HH:nn:ss zz]) $mws.quote($mws.inheader(%sockname,_request_)) $mws.gd($+(%sockname,respcode)) $file(%filename).size
}
;## Stop here if it was a head request
if ($mws.method(%sockname) == head) {
.timer -m 1 20 sockclose %sockname
return
}
}
%filesize = $file(%filename).size
if (!$exists(%filename)) { mws.dbg -e Filename for sockwriting did not exist (likely not a problem) File: %filename Sock: $sock(%sockname) | sockclose %sockname | return }
var %sending = $true
;## var %gkey = %sockname $+ .gzip
;## Some vars for gzip encoding
;## if ($mws.gd(%gkey) == true) {
;## var %usegzip = 1, %greturn
;## }
while (%sending) {
;## CPS check
%curcps = $mws.totcps
var %rlen = $mws.gd(Rangelen. $+ %sockname)
if (%curcps > %maxcps) && (%maxcps > 0) {
%sending = $false
break
}
if (!$sock(%sockname)) { mws.dbg -e Socket %sockname does not exist anymore, aborting filesend (No problem) | return }
if ((%offset >= %filesize) || (%offset >= %rlen)) { Mws.FinishSend %sockname | return }
if ((%rlen > 0) && (%rlen != $null)) {
;## %rlen represents where to stop reading data
if ($calc(%offset + %chunk) > %rlen) {
%chunk = $calc(%rlen - %offset)
}
}
if ($calc($sock(%sockname).sq + %chunk) > %maxbuf) {
%sending = $false
break
}
else {
bread %filename %offset %chunk &data
sockwrite %sockname &data
%offset = $calc(%offset + %chunk)
}
}
sockmark %sockname $+(-b,%offset) %filename
;timer $+ %sockname -m 1 30 Mws.sendfile %sockname $+(-b,%offset) %filename
}
On *:sockwrite:mws.*: {
if ($sockerr) || ($sockname == $mws.ListenName) { mws.dbg File sending / sockwrite error $sockerr (Most likely no problem) | return }
if ($sock($sockname).sq == 0) {
;timer $+ %sockname off
Mws.sendfile $sockname $sock($sockname).mark
}
}
;## Sends http headers to the given socket
Alias MWS.SendHeaders {
var %sockname = $1, %filename = $2-, %item
if (!$sock(%sockname)) { mws.dbg -e Socket %sockname did not exist when trying to send headers | return }
var %i = 1, %t = $hget($mws.ht.outheaders,0).item, %sheader, %sdata
sockwrite -n %sockname $mws.outheader(%sockname,_response_)
hdel -w $mws.ht.outheaders $+(%sockname,._response_*)
while (%i <= %t) {
%item = $hget($mws.ht.outheaders,%i).item
if (%sockname isin %item) {
%sheader = $mid(%item,$calc($len(%sockname) + 2))
%sdata = $hget($mws.ht.outheaders,%item)
if (Set-cookie:.* iswm %sheader) {
%sheader = $gettok(%sheader,1,46)
}
sockwrite -n %sockname %sheader %sdata
}
inc %i
}
sockwrite -n %sockname
}
;## Loop while the buffer is not empty and then close the connection
Alias MWS.FinishSend {
var %sockname = $1
if ($sock(%sockname).sq > 0) {
.timer -m 1 1 mws.finishsend %sockname
}
else {
sockclose %sockname
}
}
;## Returns total CPS in use by MotionWS
alias mws.totcps {
var %i = 1, %t = $sock(mws.*,0), %sock, %tcps
while (%i <= %t) {
%sock = $sock(mws.*,%i)
if (%sock == $mws.listenname) { inc %i | continue }
%tcps = $calc(%tcps + ($sock(%sock).sent / $sock(%sock).to))
inc %i
}
return %tcps
}
Alias MWS.rb { return $chr(125) }
Alias MWS.lb { return $chr(123) }
;## Parses an mhtml file
Alias MWS.Mhtml {
var %rec = $false, %s, %file, %reclevel
;## Check for recursion
if ($1 == -r) { %rec = $true | %s = $2 | %reclevel = $3 | inc %reclevel | %file = $4- }
else { %s = $1 | %file = $2- | %reclevel = 1 }
var %mhandle = MWS.Mhtml, %trhandle = $mws.gettempfilename(%s,-nToRun).name, %tshandle = $mws.gettempfilename(%s,-nToSend).name
var %torun = $mws.gettempfilename(%s,-nToRun).filename, %tosend = $mws.gettempfilename(%s,-nToSend).filename
%torun = $mws.quote(%torun) | %tosend = $mws.quote(%tosend)
;## Add quotes to file
%file = $mws.quote(%file)
;## If the previous source file handle was open, close it, as we're going to open another one
;## The other file streams can stay open
if ($mws.isfileopen(%mhandle)) { .fclose %mhandle }
;## Open file streams
if (%rec) {
;## We are in recursive parsing mode, close previous and open new one
if ($mws.isfileopen(%mhandle)) {
.fclose %mhandle
}
.fopen %mhandle %file
}
else {
.fopen %mhandle %file
}
if (!$mws.isfileopen(%trhandle)) { .fopen $iif(!$exists(%torun),-n) %trhandle $mws.quote(%torun) }
if (!$mws.isfileopen(%tshandle)) { .fopen $iif(!$exists(%tosend),-n) %tshandle $mws.quote(%tosend) }
if (!%rec) {
;## Write header aliases
.fwrite -n %trhandle alias -l mhtml.print $mws.lb if ((!$1) || ($1 == -n && !$2)) $mws.lb return $mws.rb $chr(124) if ($1 == -n) $mws.lb .fwrite -n %tshandle $eval($2-,0) $mws.rb $chr(124) else $mws.lb .fwrite %tshandle $eval($1-,0) $mws.rb $mws.rb
.fwrite -n %trhandle alias -l mhtml.isset $MWS.lb if ($get($1)) $mws.lb return $eval($true,0) $mws.rb $chr(124) else $mws.lb return $eval($false,0) $mws.rb $MWS.rb
.fwrite -n %trhandle alias -l mhtml.get $MWS.lb return $eval($,0) $+ mws.gq( $+ %s $+ ,$1).item $MWS.rb
;## .fwrite -n %trhandle alias -l mhtml.post $MWS.lb return $eval($,0) $+ mws.gp( $+ %s $+ ,$1).item $MWS.rb
.fwrite -n %trhandle alias -l mhtml.rootdir $MWS.lb return $nofile(%file) $MWS.rb $+ $crlf
.fwrite -n %trhandle alias -___runme $MWS.lb
}
var %i = 1, %t = $lines(%file), %line, %inscript = $false, %amatch = alias $+(*,$MWS.lb,*), %numlb, %numrb, %il,%aline, %incendpos, %returncode, %window = $+(@,%s)
if (!$window(%window)) {
window -lh %window 0 0 0 0
}
while (%i <= %t) {
.fseek -l %mhandle %i
%line = $fread(%mhandle)
;## check for script start
if (%line == <?mhtml) {
%inscript = $true
inc %i | continue
}
;## check for script end
if (%line == ?>) {
%inscript = $false
inc %i | continue
}
;## Check if we're currently inside script code, check for aliases, copy it to the ToRun file
if (%inscript == $true) {
if (%amatch iswm %line) {
;## Got an alias, copy it to the top of the ToRun file
%numlb = 0 | %numrb = 0 | %aline = %i
;## Loop while there's an uneven number of curly brackets
%il = 1
while (%i <= %t) {
.fseek -l %mhandle %i
%line = $fread(%mhandle)
inc %numlb $count(%line,$MWS.lb) | inc %numrb $count(%line,$MWS.rb)
;## Copy line to window
if (%line) { aline %window %line }
inc %il | inc %i
if (%numlb == %numrb) { break }
if (%i > %t) { mws.dbg Bracket mismatch error in mhtml file %file on line %aline $+ , aborting execution | return $false }
}
continue
}
if ($mid(%line,1,14) == $+(mhtml.include,$chr(32))) {
;## Include another file
%returncode = $mws.mhtml.rec(%s,%reclevel,$+($nofile(%file),$mid(%line,15)))
if (%returncode == $false) { return $false }
.fclose %mhandle
.fopen %mhandle %file
}
else {
;## Usual script code, write directly to file
if (%line) {
.fseek -l %trhandle $lines(%torun) | .fseek -n %trhandle
.fwrite -n %trhandle %line
}
}
}
else {
;## Check if it's a special include directive
if ($mid(%line,1,12) == $+(<?mhtml.inc,$chr(32))) {
%returncode = $mws.mhtml.rec(%s,%reclevel,$+($nofile(%file),$mid(%line,13,-2)))
if (%returncode == $false) { return $false }
.fclose %mhandle
.fopen %mhandle %file
}
else {
;## Normal html code, write print command + html with parsed characters
.fseek -l %trhandle $lines(%torun) | .fseek -n %trhandle
.fwrite -n %trhandle mhtml.print -n $mws.mhtml.parsechars(%line)
}
}
inc %i
}
if (!%rec) {
;## Write final curly bracket
write %torun $MWS.rb
;## Save aliases from alias window
savebuf -a %window %torun
;## Load script
.load -rs %torun
-___runme
.unload -rs %torun
.timer -m 1 100 .window -c %window
.fclose %trhandle | .fclose %mhandle
;## Send the output
mws.sendtempfile %s -nToSend
return $true
}
}
;## Recurses an mhtml file when it's included into another mhtml file
Alias MWS.Mhtml.Rec {
if ($2 == 100) { return $false }
return $mws.mhtml(-r,$1,$2,$3-)
}
;## Replaces curly brackets with $chr counterparts to avoid problems with the mIRC parser
Alias MWS.Mhtml.parsechars {
var %in = $1-
var %m1 = $+($chr(32),$MWS.lb,$chr(32))
var %m2 = $+($chr(32),$MWS.rb,$chr(32))
var %m3 = $+($chr(32),$chr(124),$chr(32))
var %r1 = $+($chr(32),$eval($chr(123),0),$chr(32))
var %r2 = $+($chr(32),$eval($chr(125),0),$chr(32))
var %r3 = $+($chr(32),$eval($chr(124),0),$chr(32))
%in = $replace(%in,%m1,%r1,%m2,%r2,%m3,%r3)
if (%in == $chr(123)) { %in = $eval($chr(123),0) }
if (%in == $chr(125)) { %in = $eval($chr(125),0) }
return %in
}
;######################################## AutoUpdate ########################################
Alias mws.gotfile {
if ($right($1-,20) == motionws_update.zip") {
mws.echo Updating MotionWS..
var %u = $1-
var %s = $dll($mws.quote($mws.dll.zip), Unzip, -od %u $mws.quote($scriptdir))
if ($gettok(%s,1,32) != S_OK) { mws.echo Error while applying update: %s }
if ($exists(%u)) { .remove %u }
mws.echo Please wait..
mws.loadtables
if ($mws.isrunning) { mws.stop | mws.pd wasrunning $true }
else { mws.pd wasrunning $false }
mws.pd updated $true
.load -rs $mws.quote($script)
}
if ($right($1-,13) == versions.txt") {
;## Check for newer version
var %build = $read($1-,n,1), %time = $gettok(%build,2,95), %curtime = $gettok($mws.build,2,95)
if ($calc(%curtime - %time) < 0) {
;## New update available
mws.echo New version available!
var %dname = mws.newversion
if (!$dialog(%dname)) { dialog -m %dname %dname }
var %i = 1, %f = $mws.quote($1-), %t = $lines(%f)
did -a %dname 1 Version %build $+ : $+ $crlf $+ $crlf
loadbuf $+(2-,%t) -o %dname 1 $mws.quote($1-)
}
else {
mws.echo No new version
}
if ($exists($1-)) { .remove $1- }
}
}
;## Get's the latest update, regardless of version
Alias mws.update { if (%mwsdev == true) { echo -s This is the dev build, stupid | return } | mws.stop | mws.getfile mws.ileet.net 80 /updates/motionws_update.zip }
;## Checks if there is a new STABLE release available for update
Alias mws.updatecheck { mws.getfile mws.ileet.net 80 /updates/versions.txt }
;## Downloads a file
Alias mws.getfile {
var %addr = $1, %port = $2, %s = mwsupdate, %getfile = $3-
sockclose %s
sockopen %s %addr %port
sockmark %s %getfile %addr
mws.echo Connecting to $+(%addr,:,%port) $+ ..
}
On *:sockopen:mwsupdate: {
if ($sockerr) { mws.echo Socket error $sockerr (sockopen), aborting | return }
var %s = $sockname, %getfile = $gettok($sock(%s).mark,1,32), %addr = $gettok($sock(%s).mark,2,32), %of = $mws.quote($+($scriptdir,$nopath(%getfile)))
write -c %of
%getfile = $mws.rawurlencode(%getfile)
mws.echo Connected to $sock(%s).ip $+ , sending request..
sockwrite %s $+(GET %getfile HTTP/1.0,$crlf,Host: %addr,$crlf,Connection: Close,$crlf,User-agent: MWS,$crlf,Accept: */*,$crlf,$crlf)
}
On *:sockread:mwsupdate: {
if ($sockerr) { mws.echo Socket error $sockerr (sockread), aborting | return }
var %s = $sockname, %of = $mws.quote($+($scriptdir,$nopath($gettok($sock(%s).mark,1,32)))), %read = $true
while (%read) {
sockread &data
if ($bvar(&data,0)) { bwrite %of -1 -1 &data }
if (!$sockbr) { %read = $false }
}
}
On *:sockclose:mwsupdate: {
var %s = $sockname, %of, %offset
mws.echo Connection to $+($sock(%s).ip,:,$sock(%s).port) closed, file recieved
%of = $mws.quote($+($scriptdir,$nopath($gettok($sock(%s).mark,1,32))))
bread %of 0 $file(%of).size &file
%offset = $calc($bfind(&file, 1, 13 10 13 10) + 4)
bcopy &file2 1 &file %offset -1
write -c %of
bwrite %of -1 -1 &file2
mws.gotfile %of
}
;######################################## Dialogs below ########################################
dialog mws.config {
title "MotionWS-2 Configuration"
size -1 -1 477 270
option pixels
icon 1, 0 0 476 60
tab "Main", 2, 2 65 471 174
box "Sockets/Files", 7, 9 94 238 135, tab 2
text "Listen on port:", 8, 20 108 168 16, tab 2 right
edit "", 9, 191 107 49 21, tab 2 multi autohs autovs
text "HTdocs:", 10, 19 133 49 16, tab 2 right
edit "", 11, 71 131 139 21, tab 2 multi autohs autovs
button "...", 12, 213 132 25 20, tab 2
text "Directory index:", 13, 19 158 97 16, tab 2 right
edit "", 14, 118 156 121 21, tab 2 multi autohs autovs
text "Htaccess filename:", 15, 18 183 97 16, tab 2 right
edit "", 16, 118 180 121 21, tab 2 multi autohs autovs
box "Logging/Debugging", 17, 252 94 215 135, tab 2
check "Echo debug info", 18, 259 116 100 20, tab 2
check "Debug log", 19, 259 141 71 20, tab 2
edit "", 20, 332 141 99 21, tab 2 multi autohs autovs
button "...", 21, 434 142 25 20, tab 2
check "Http log", 22, 259 166 64 20, tab 2
edit "", 23, 332 167 99 21, tab 2 multi autohs autovs
button "...", 24, 434 167 25 20, tab 2
text "('Http log' uses the standard http log format)", 25, 299 192 156 29, tab 2
text "Server name:", 45, 18 206 97 16, tab 2 right
edit "", 46, 118 204 121 21, tab 2 multi autohs autovs
tab "Advanced", 3
box "Sockets", 26, 9 94 181 132, tab 3
text "Max upload speed:", 27, 15 116 108 16, tab 3 right
edit "", 28, 126 113 36 21, tab 3 multi autohs autovs
text "KB/s", 29, 164 116 23 16, tab 3
text "Note: Set the value to 0 for unlimited bandwidth usage.", 127, 25 146 138 40, tab 3
box "Folder properties", 30, 196 94 271 132, tab 3
check "Folders can be listed by default", 31, 205 112 174 20, tab 3
check "Folders can be downloaded from by default", 32, 205 135 233 20, tab 3
text "Date format:", 33, 206 160 70 16, tab 3 right
edit "", 34, 278 157 130 21, tab 3 multi autohs autovs
tab "Misc", 40
check "Check for updates on webserver start", 41, 11 96 217 20, tab 40
check "Use GZIP compression where available", 42, 11 120 208 20, disable tab 40
check "Enable CGI module", 43, 11 144 118 20, tab 40
tab "About", 4
text "MotionWS2", 35, 12 98 454 16, tab 4 center
text "Created by oracel", 36, 375 214 92 16, tab 4
edit "", 37, 7 118 461 91, tab 4 read multi return vsbar
link "Visit the MotionWS2 webpage", 38, 9 214 155 16, tab 4
button "Ok", 5, 317 241 75 25, default ok
button "Cancel", 6, 398 241 75 25, cancel
text "Note: Many of these settings require that you restart MotionWS2 for them to take effect.", 39, 13 239 249 28
link "Need help?", 44, 409 65 60 16
}
dialog mws.newversion {
title "MotionWS - New version available!"
size -1 -1 209 139
option dbu
edit "", 1, 1 12 207 111, read multi vsbar
text "New version available! Check out what's new:", 2, 2 3 204 8
button "Download", 3, 128 125 37 12, ok default
button "Cancel", 4, 170 125 37 12, cancel
}
dialog mws.vfolders {
title "Virtual folders managment"
size -1 -1 108 130
option dbu
list 1, 1 1 68 128, sort size vsbar hsbar
button "Add", 2, 70 2 37 12
button "Remove", 3, 70 16 37 12, disabled
button "Edit", 4, 70 30 37 12, disabled
button "Close", 5, 70 117 37 12, ok
}
;######################################## Dialog events & commands ########################################
On *:Dialog:MWS.Config:*:*: {
var %dname = mws.config
if ($devent == init) {
if (!$mws.isrunning) { mws.loadtables }
loadbuf -o %dname 37 $mws.quote($+($mws.docsdir,\about.txt))
did -g %dname 1 $mws.quote($+($mws.datadir,\top.png))
did -a %dname 9 $mws.gs(ListenPort)
did -a %dname 11 $mws.gs(HTdocs)
did -a %dname 46 $mws.gs(ServerName)
did -a %dname 14 $mws.gs(DirectoryIndex)
did -a %dname 16 $mws.gs(AccessFile)
if ($group(#mws.debug).status == on) { did -c %dname 18 }
if ($group(#mws.debuglog).status == on) { did -c %dname 19 }
if ($group(#mws.httplog).status == on) { did -c %dname 22 }
did -a %dname 20 $mws.gs(Logfile)
did -a %dname 23 $mws.gs(HttpLogFile)
did -a %dname 28 $int($calc($mws.gs(MaxCPS) / 1024))
if ($mws.gs(deflist) == true) { did -c %dname 31 }
if ($mws.gs(defget) == true) { did -c %dname 32 }
if ($mws.gs(cgi) == true) { did -c %dname 43 }
if ($mws.gs(CheckForUpdateOnStart) == true) { did -c %dname 41 }
did -a %dname 34 $mws.gs(DateFormat)
if ($did(19).state == 1) { did -e $dname 20,21 }
else { did -b $dname 20,21 }
if ($did(22).state == 1) { did -e $dname 23,24 }
else { did -b $dname 23,24 }
}
if ($devent == sclick) && ($did == 5) {
mws.ps Listenport $did(9).text
mws.ps Htdocs $did(11).text
mws.ps DirectoryIndex $did(14).text
mws.ps AccessFile $did(16).text
if ($did(18).state == 1) { .enable #mws.debug } | else { .disable #mws.debug }
if ($did(19).state == 1) { .enable #mws.debuglog } | else { .disable #mws.debuglog }
if ($did(22).state == 1) { .enable #mws.httplog } | else { .disable #mws.httplog }
mws.ps LogFile $did(20).text
mws.ps HttpLogFile $did(23).text
mws.ps ServerName $did(46).text
mws.ps MaxCPS $calc($did(28).text * 1024)
mws.ps DefList $replace($did(31).state,1,True,0,False)
mws.ps DefGet $replace($did(32).state,1,True,0,False)
mws.ps CGI $replace($did(43).state,1,True,0,False)
mws.ps CheckForUpdateOnStart $replace($did(41).state,1,True,0,False)
mws.ps DateFormat $did(34).text
if (!$mws.isrunning) { mws.savetables }
}
if ($devent == sclick) {
if ($did == 19) {
if ($did(19).state == 1) { did -e $dname 20,21 }
else { did -b $dname 20,21 }
}
if ($did == 22) {
if ($did(22).state == 1) { did -e $dname 23,24 }
else { did -b $dname 23,24 }
}
if ($did == 12) {
did -ra $dname 11 $$sdir($mircdir)
}
if ($did == 21) {
did -ra $dname 20 $$sfile($mircdir)
}
if ($did == 24) {
did -ra $dname 23 $$sfile($mircdir)
}
if ($did == 38) {
run http://mws.ileet.net
}
if ($did == 44) {
run $mws.quote($scriptdirdocs\help.html)
}
}
}
On *:Dialog:MWS.Newversion:sclick:3: {
mws.update
}
on *:dialog:mws.vfolders:*:*: {
var %tbl = $mws.ht.vfolders
if ($devent == init) {
if (!$mws.isrunning) { mws.loadtables }
mws.addvfitems $dname
}
if ($devent == sclick) {
if ($did(1).seltext) { did -e $dname 3,4 }
else { did -b $dname 3,4 }
if ($did == 2) {
if (!$dialog(mws.addvfolder)) { var %x = $dialog(mws.addvfolder,mws.addvfolder,-4) }
}
if ($did == 4) {
mws.pd vfolders.edit true
mws.pd vfolders.vfolder $mws.rawurlencode($did(1).seltext)
if (!$dialog(mws.addvfolder)) { var %x = $dialog(mws.addvfolder,mws.addvfolder,-4) }
mws.pd vfolders.edit false
mws.pd vfolders.vfolder
}
if ($did == 3) {
var %f = $mws.rawurlencode($did(1).seltext), %ln = $did(1,1).sel
mws.deletevirtualfolder %f
mws.addvfitems $dname
did -c $dname 1 %ln
}
}
if ($devent == close) {
if (!$mws.isrunning) { mws.savetables }
}
}
alias mws.addvfitems {
var %tbl = $mws.ht.vfolders, %i = 1, %t = $hget(%tbl,0).item
did -r $1 1
while (%i <= %t) {
did -a $1 1 $mws.rawurldecode($hget(%tbl,%i).item)
inc %i
}
}
dialog mws.addvfolder {
title "Virtual folder mapping"
size -1 -1 132 91
option dbu
edit "/foldername", 1, 52 1 79 10, multi autohs autovs
edit "", 2, 52 12 64 10, multi autohs autovs
button "...", 3, 118 12 13 10
check "The contents of this folder can be listed", 4, 1 24 107 10
check "The contents of this folder can be downloaded", 5, 1 33 122 10
text "Virtual folder name:", 6, 0 2 50 8, right
text "Physical folder:", 7, 0 13 50 8, right
edit "", 8, 42 45 50 10
text "Username:", 9, 7 46 34 8, right
text "Password:", 10, 7 58 34 8, right
edit "", 11, 42 57 50 10, pass
box "", 12, 1 70 130 4
button "Ok", 13, 53 77 37 12, ok
button "Cancel", 14, 93 77 37 12, cancel
}
on *:dialog:mws.addvfolder:*:*: {
if ($devent == init) {
did -c $dname 4,5
if ($mws.gd(vfolders.edit) == true) {
var %vfolder = $mws.gd(vfolders.vfolder), %rfolder = $mws.getvirtualfolder(%vfolder), %get = $mws.getvirtualfolder(%vfolder).get, %list = $mws.getvirtualfolder(%vfolder).list, %username = $mws.getvirtualfolder(%vfolder).username, %password = $mws.getvirtualfolder(%vfolder).password
did -ra $dname 1 %vfolder
did -a $dname 2 %rfolder
if (%get != true) { did -u $dname 5 }
if (%list != true) { did -u $dname 4 }
did -a $dname 8 %username
did -a $dname 11 %password
}
}
if ($devent == sclick) {
if ($did == 13) {
var %vfolder = $did(1).text, %rfolder = $did(2).text, %get = $did(5).state, %list = $did(4).state, %username = $did(8).text, %password = $did(11).text
if (!%vfolder) { mws.errmsg No virtual folder specified | halt }
if (!%rfolder) { mws.errmsg No physical folder specified | halt }
if (%username && !%password) { mws.errmsg No password specified | halt }
if (%vfolder == /) { mws.errmsg You can not map "/" as a virtual folder. Please use your Htdocs directory as root directory | halt }
;var %sw = $iif(%get || %list || %username, $+(-,$iif(%list,l),$iif(%get,g),$iif(%username,p)))
var %sw
%sw = -
if (%get == 1) { %sw = $+(%sw,g) }
if (%list == 1) { %sw = $+(%sw,l) }
if (%username) { %sw = $+(%sw,p) }
if (%sw == -) { var %sw }
mws.addvirtualfolder %sw %username %password $mws.rawurlencode(%vfolder) %rfolder
mws.addvfitems mws.vfolders
}
if ($did == 3) {
did -ra $dname 2 $sdir($mircdir)
}
}
}
dialog mws.cgi {
title "CGI Setup"
size -1 -1 174 48
option dbu
combo 1, 43 2 91 120, size drop
button "Add..", 2, 137 2 37 12
button "Remove", 3, 137 18 37 12
button "Close", 4, 137 34 37 12, ok
text "CGI executable:", 5, 1 16 40 8, right
edit "", 6, 42 15 79 10, multi autohs
button "...", 7, 122 15 12 10
link "Need help?", 10, 52 37 30 8
text "File extension:", 8, 2 4 39 8, right
}
on *:dialog:mws.cgi:*:*: {
var %tbl = $mws.ht.cgi, %dlg = mws.cgi
if ($devent == init) {
mws.loadtables
var %i = 1, %t = $hget(%tbl,0).item
while (%i <= %t) {
did -a %dlg 1 $hget(%tbl,%i).item
inc %i
}
}
if ($devent == edit) {
var %item = $did(1).seltext
if (%item) {
mws.pc %item $did(6).text
}
}
if ($devent == sclick) {
if ($did == 3) {
hdel $mws.ht.cgi $did(1).seltext
did -r %dlg 1,6
var %i = 1, %t = $hget(%tbl,0).item
while (%i <= %t) {
did -a %dlg 1 $hget(%tbl,%i).item
inc %i
}
}
if ($did == 1) {
did -ra %dlg 6 $mws.gc($did(1).seltext)
}
if ($did == 7) {
did -ra %dlg 6 $$sfile($mircdir, Select CGI executable, Ok)
;## Change hash value here
var %item = $did(1).seltext
if (%item) {
mws.pc %item $did(6).text
}
}
if ($did == 2) {
var %item = $$input(Enter new file extension (no periods):,eq,New CGI file extension)
mws.pc %item
did -r %dlg 1,6
var %i = 1, %t = $hget(%tbl,0).item
while (%i <= %t) {
did -a %dlg 1 $hget(%tbl,%i).item
inc %i
}
}
if ($did == 10) {
run $mws.quote($scriptdirdocs\help.html)
}
if ($did == 4) {
mws.savetables
}
}
}
dialog mws.connections {
title "MotionWS Connections"
size -1 -1 209 102
option dbu
list 1, 0 1 209 86, size
button "Close", 2, 171 89 37 12, ok
}
alias mws.connections {
var %tbl = mws.connections
if (!$dialog(%tbl)) {
dialog -m %tbl %tbl
}
.timermwsconnections -m 0 100 $!mws.connections.add
}
alias mws.connections.add {
var %tbl = mws.connections
if (!$dialog(%tbl)) {
.timermwsconnections off
return
}
did -r %tbl 1
var %i = 1, %t = $sock(mws.*,0), %sck, %totcps = 0, %totsockets = 0
while (%i <= %t) {
%sck = $sock(mws.*,%i)
if (%sck == $MWS.ListenName) || (mws.* !iswm %sck) { inc %i | continue }
inc %totsockets
var %timeopen = $iif($sock(%sck).to == 0,1,$sock(%sck).to), %cps = $calc($sock(%sck).sent / %timeopen)
inc %totcps %cps
did -a %tbl 1 Sock %totsockets $+ : %sck $+ /IP: $sock(%sck).ip $+ /Open: $duration($sock(%sck).to) $+ /Upload: $round($calc(%cps / 1024),2) $+ KB/sec
inc %i
}
did -a %tbl 1 ---
var %maxcps = $mws.gs(MaxCPS)
if (%maxcps > 0) {
did -a %tbl 1 Currently %totsockets sockets, using $round($calc(%totcps / 1024),2) $+ KB/sec (Maximum $calc($mws.gs(MaxCPS) / 1024) $+ KB/sec allowed)
}
else {
did -a %tbl 1 Currently %totsockets sockets, using $round($calc(%totcps / 1024),2) $+ KB/sec (No bandwidth limit)
}
}
Alias MWS.Errmsg {
var %x = $input($1-,oh,Error)
}
;######################################## CGI ########################################
Alias mws.cgi {
if (!$1-) { mws.managecgi | return }
;## /mws.cgi <sockname> <type> <vfolder> <rfolder>
var %ticks = $ticks
;## Set some initial variables
var %s = $1, %type = $2, %vfolder = $3, %rfolder = $4-, %exec = $shortfn($mws.gc(%type)), %reqm = $gettok($mws.inheader(%s,_request_),1,32), %qstring1 = $gettok(%vfolder,2,63), %qstring2 = $+(?,%qstring1)
mws.dbg CGI: Generating filenames for output
;## Generate a primary output filename
var %outpri = $mws.gettempfilename(%s,-nCGI.Primary).filename, %hpri = $mws.gettempfilename(%s,-nCGI.Primary).name, %cgioutput = $mws.gettempfilename(%s,-nCGI.Output).filename, %wfilename = $mws.gettempfilename(%s,-nPostData).filename
%outpri = $mid(%outpri,1,-3) $+ bat
var %vbfile = $+($scriptdir,temp\,%s,.Env.vbs), %vb = mws.vbscript
var %w = .fwrite
.fopen -n %vb $mws.quote(%vbfile)
.fopen -n %hpri $mws.quote(%outpri)
%w -n %vb Set WshShell = WScript.CreateObject("WScript.Shell") $+ $crlf $+ Set WshProcessEnv = WshShell.Environment("PROCESS")
;## Generate a secondary output file
var %outsec = $mws.gettempfilename(%s,-nCGI.Secondary).filename
;## Write standard CGI headers to the batch file
mws.dbg CGI: Setting Environmental variables
%w -n %vb WshProcessEnv("GATEWAY_INTERFACE") = $mws.quote(CGI/1.1)
%w -n %vb WshProcessEnv("SERVER_SOFTWARE") = $mws.quote($mws.serverreply)
%w -n %vb WshProcessEnv("SERVER_PROTOCOL") = $mws.quote(HTTP/1.1)
%w -n %vb WshProcessEnv("REDIRECT_STATUS") = $mws.quote(200)
%w -n %vb WshProcessEnv("REQUEST_METHOD") = $mws.quote(%reqm)
%w -n %vb WshProcessEnv("REQUEST_URI") = $mws.quote(%vfolder)
%w -n %vb WshProcessEnv("PATH_INFO") = $mws.quote(%vfolder)
%w -n %vb WshProcessEnv("PATH_TRANSLATED") = $mws.quote($longfn(%rfolder))
%w -n %vb WshProcessEnv("SCRIPT_FILENAME") = $mws.quote($longfn(%rfolder))
%w -n %vb WshProcessEnv("DOCUMENT_ROOT") = $mws.quote($nofile($longfn(%rfolder)))
%w -n %vb WshProcessEnv("SCRIPT_NAME") = $mws.quote($gettok(%vfolder,1,63))
%w -n %vb WshProcessEnv("REMOTE_ADDR") = $mws.quote($sock(%s).ip)
%w -n %vb WshProcessEnv("CONTENT_TYPE") = $mws.quote($mws.inheader(%s,Content-Type:))
%w -n %vb WshProcessEnv("CONTENT_LENGTH") = $mws.quote($mws.inheader(%s,Content-Length:))
%w -n %vb WshProcessEnv("REDIRECT_URL") = $mws.quote($gettok(%vfolder,1,63))
%w -n %vb WshProcessEnv("SERVER_NAME") = $mws.quote($mws.gs(ServerName))
%w -n %vb WshProcessEnv("SERVER_PORT") = $mws.quote($mws.gs(listenport))
;## If it's a GET or HEAD request, add querystring
;if (%reqm == GET) || (%reqm == HEAD) {
%w -n %vb WshProcessEnv("QUERY_STRING") = $mws.quote(%qstring1)
%w -n %vb WshProcessEnv("REDIRECT_QUERY_STRING") = $mws.quote(%qstring1)
;}
;## Loop to add additional headers from the incoming hashtable
var %ht = $mws.ht.inheaders, %match = $+(%s,.*), %i = 1, %t = $hfind(%ht,%match,0,w), %hitem, %hdata, %hdr
while (%i <= %t) {
%hitem = $hfind(%ht,%match,%i,w)
%hdata = $hget(%ht,%hitem)
;## All extra headers should be added as HTTP_ $+ <header>, with all -'s converted to underscore
%hdr = $upper(HTTP_ $+ $replace($gettok(%hitem,3,46),-,_,:,))
if (%hdr != HTTP_GET) && (%hdr != HTTP_POST) && (%hdr != HTTP_HEAD) && (%hdr != HTTP__REQUEST_) {
%w -n %vb WshProcessEnv(" $+ %hdr $+ ") = $mws.quote(%hdata)
}
inc %i
}
;## Append POST data if it applies
if ($exists(%wfilename)) {
;## POST data applies
var %postfile = < $mws.quote(%wfilename)
}
%w -n %vb Return = WshShell.Run(" $+ CMD /C "" $+ %outpri $+ "" $+ ",0)
;## Write exection line to batch file
%w -n %hpri %exec $mws.quote($longfn(%rfolder)) %postfile > $mws.quote(%cgioutput)
;## Write echoline to batch file, needed to verify when the script has finished processing
%w -n %hpri echo Done > $mws.quote(%outsec)
.fclose %hpri
.fclose %vb
;## Execute the batchfile through COM using Online's /xrun alias
mws.dbg CGI: Processing done in $calc(($ticks - %ticks) / 1000) $+ s, Running WSH file and waiting for output..
run -n $mws.quote(%vbfile)
;## Wait for the CGI executable to finish processing
mws.cgi.wait %s
}
Alias MWS.vbw {
var %s = $1, %var = $2, %val = $3-
;## Generate a enviromental setting vbscript filename
var %vbfile = $+($scriptdir,temp\,%s,.Env.vbs)
write $mws.quote(%vbfile) WshProcessEnv(" $+ $2 $+ ") = $mws.quote($3-)
}
Alias mws.cgi.wait {
var %s = $1, %file = $mws.gettempfilename(%s,-nCGI.Secondary).filename
if (!$exists($mws.quote(%file))) {
;## Delayed recursion
.timermws.cgi. $+ %s -m 1 2 mws.cgi.wait %s
return
}
;## Get output filename
var %outfile = $mws.gettempfilename(%s,-nCGI.Output).filename, %ohandle = $mws.gettempfilename(%s,-nCGI.Output).name
;## Open stream to file
.fopen %ohandle $mws.quote(%outfile)
;## Loop while there's headers
var %done = $false, %header, %len = 0, %recode, %cookies, %cookiedata
while (!%done) {
;## Get the header lines
%header = $fread(%ohandle)
if (%header) {
;## If it's a status reply, reply to the client with 302 Found
if ($gettok(%header,1,32) == Status:) {
%recode = $gettok(%header,2,32)
}
else {
if ($gettok(%header,1,32) == Set-Cookie:) {
;## Multiple cookie hack
%cookiedata = $mid(%header,13)
%header = Set-cookie:. $+ %cookies %cookiedata
inc %cookies
}
;## Add header to the outheader hashtable
mws.outheader %s %header
}
}
else {
;## Empty line, calculate offset for messagebody data start
var %offset = $fopen(%ohandle).pos
%done = $true
break
}
}
if (%recode == 302) {
;## No point in continuing if it's a 302
mws.response %s 302
return
}
;## Get filesize and load messagebody into a binary variable
var %size = $file($mws.quote(%outfile)).size, %x = $fread(%ohandle,$calc(%size - %offset),&data)
;## Close the filehandle and empty the file
.fclose %ohandle
write -c $mws.quote(%outfile)
;## Reopen file, write data, close file
.fopen %ohandle $mws.quote(%outfile)
.fwrite -b %ohandle &data
.fclose %ohandle
;## Send the file
mws.sendfile %s %outfile
}
Alias MWS.Pbar {
;## Thanks to Eric^^ for this one
; /pbar -c [pos] [max] [text]
; the -c switch close the progress bar
if ($1 == -c) { if ($window(@pbar)) window -c @pbar | return }
if (!$window(@pbar)) window -BhaCdfopk +Ldf @pbar -1 -1 300 60
drawrect -rfn @pbar $rgb(220,220,220) 1 0 0 300 60
drawline -rn @pbar $rgb(255,255,255) 2 0 60 0 0 300 0
drawline -rn @pbar $rgb(128,128,128) 2 0 60 300 60 300 0
if ($3 != $null) {
var %width = $calc(150 - ($width($3-,Verdana,11) /2))
drawtext -rnc @pbar $rgb(170,170,170) Verdana 11 $calc(%width + 1) 10 290 20 $3-
drawtext -rnc @pbar $rgb(text) Verdana 11 %width 9 290 20 $3-
}
drawrect -rn @pbar $rgb(frame) 1 10 29 280 20
drawrect -rnf @pbar $rgb(134,187,246) 1 11 30 $calc(($1 / $2) *278) 18
var %width = $width($+($calc(($1 / $2) *100),%),tahoma,11)
drawdot @pbar
}