NullLogic

A _very_ crude Content Management System

#!/usr/bin/nsp /* * CMS sample prog by Dan Cahill * This is the Crappy Management system. * It lets you browse the filesystem, execute shell commands, and edit files, * and since there's no security, it lets everyone else do it, too... :-) * * build nesla.cgi and put it in /cgi-bin/ * make a .htaccess file, add these three lines, * * Options +ExecCGI * AddHandler nes-script .ns * Action nes-script /cgi-bin/nesla.cgi * DirectoryIndex index.html index.ns index.php * * and that's about it.. * * the most likely problem is file permissions, but you're on your own there. */ // This thing has serious limits that make its usefulness rather limited. global MASTERPASSWORD="nesla"; if (typeof(_SERVER)!='table') exit; function dologin() { var user="nobody"; var pass=MASTERPASSWORD; print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"); print("<HTML> <HEAD> <TITLE>Nesla - Crappy Management system</TITLE> <STYLE TYPE=text/css> A { color: #0000FF; text-decoration: none; } A:HOVER { background-color: #E0E0FF; } </STYLE> </HEAD> <BODY> <CENTER> <FORM ACTION='", _SERVER['PATH_INFO'], "' METHOD='POST' NAME='login'> <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0> <TR><TD><B> Username </B></TD><TD><INPUT SIZE=50 style='width:200px' NAME='username' VALUE='", user, "'></TD></TR> <TR><TD><B> Password </B></TD><TD><INPUT SIZE=50 style='width:200px' NAME='password' VALUE='", pass, "' TYPE=password></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2><input type='submit' value='login' name='submit'></TD></TR> </TABLE> </FORM> </CENTER> </BODY> </HTML> "); exit; } if (_POST['PASSWORD']!=null) { _GET['DOWNLOAD']=''; if (_POST['PASSWORD']==MASTERPASSWORD) { // printf("Set-Cookie: wminfo=%.2s:%.4s:%s:%s:%s; path=%s/; expires=%s\r\n"); // printf("Set-Cookie: wmpass=%s; path=%s/\r\n"); _HEADER['SET-COOKIE']="NESLACMS="+_POST['PASSWORD']; print("<SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\">\r\n<!--\r\nlocation.replace(\"", _SERVER['PATH_INFO'], "\");\r\n// -->\r\n</SCRIPT>\r\n"); print("<NOSCRIPT><META HTTP-EQUIV=\"Refresh\" CONTENT=\"1; URL=", _SERVER['PATH_INFO'], "\"></NOSCRIPT>\r\n"); } else { print("bad pass"); } exit; } if (_COOKIE['NESLACMS']==null) { _GET['DOWNLOAD']=''; dologin(); } global MASTERPASSWORD="********"; // if user is logged in, and download request exists, process that instead if (_GET['DOWNLOAD']!=null) { if (_GET['DOWNLOAD']!='') { sendfile(_GET['DOWNLOAD']); exit; } } if (_SERVER['REQUEST_METHOD']=='POST') { var opt=_POST['OPT']; if (opt=='browse') { // limit browsing to docroot if (_SERVER['DOCUMENT_ROOT']==null) { print("you have no docroot"); } else { if (string.ncmp(_SERVER['DOCUMENT_ROOT'], _POST['PATH'], string.len(_SERVER['DOCUMENT_ROOT']))!=0) { print("<B><font color=red>refusing to leave document root</font></B>"); parent=_SERVER['DOCUMENT_ROOT']; _POST['PATH']=parent; } } dir=dirlist(_POST['PATH']); x=string.split(_POST['PATH'], "/"); for (i=0;;i++) { if (x[i]==null) break; } parent=""; for (j=0;j<i-1;j++) { if (x[j]=='') { continue; } parent=parent+'/'+x[j]; } if (parent=='') parent='/'; // limit browsing to docroot if (_SERVER['DOCUMENT_ROOT']==null) { print("you have no docroot"); } else { if (string.ncmp(_SERVER['DOCUMENT_ROOT'], parent, string.len(_SERVER['DOCUMENT_ROOT']))!=0) { parent=_SERVER['DOCUMENT_ROOT']; _POST['PATH']=parent; } } print("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 WIDTH=100%>\n"); for (i=0;;i++) { var x=iname(dir, i); if (typeof(dir[x])!='table') break; if (string.cmp(x, '.')==0) { } else if (string.cmp(x, '..')==0) { print("<TR><TD COLSPAN=4 STYLE='border-style:solid'><IMG SRC=/icons/folder.open.png> <A HREF='javascript:newparent(\"", parent, "\");'>Parent Directory - ", parent, "</A></TD></TR>\n"); } else if (dir[x].type=='dir') { print("<TR>"); print("<TD ALIGN=left NOWRAP STYLE='border-style:solid'> </TD>"); print("<TD ALIGN=left NOWRAP STYLE='border-style:solid' WIDTH=66%>dir - <A HREF='javascript:newparent(\"", _POST['PATH']+'/'+x, "\");'>", x, "/</A></TD>"); print("<TD ALIGN=right NOWRAP STYLE='border-style:solid'> </TD>"); print("<TD ALIGN=right NOWRAP STYLE='border-style:solid'>", time.sqldate(dir[x].mtime), " ", time.sqltime(dir[x].mtime), "</TD>"); print("</TR>\n"); } } for (i=0;;i++) { var x=iname(dir, i); if (typeof(dir[x])!='table') break; if (string.cmp(x, '.')==0) { } else if (string.cmp(x, '..')==0) { } else if (dir[x].type=='dir') { // hide htaccess files } else if (string.cmp(x, '.htaccess')==0) { } else { print("<TR>"); print("<TD ALIGN=left NOWRAP STYLE='border-style:solid'><A HREF='javascript:nexthand(\"edit\", \"", _POST['PATH']+'/'+x, "\");'>edit</A></TD>"); // print("<TD ALIGN=left NOWRAP STYLE='border-style:solid'>file - <A HREF='", x, "'>", x, "</A></TD>"); // print("<TD ALIGN=left NOWRAP STYLE='border-style:solid' WIDTH=66%>file - <A HREF='javascript:download(\"", _POST['PATH']+'/'+x, "\");'>", x, "</A></TD>"); print("<TD ALIGN=left NOWRAP STYLE='border-style:solid' WIDTH=66%>file - <A HREF=\"", _SERVER['PATH_INFO'], "?download=", _POST['PATH']+'/'+x, "\" TARGET=\"_blank\">", x, "</A></TD>"); print("<TD ALIGN=right NOWRAP STYLE='border-style:solid'>", math.ceil(dir[x].size/1024), " KiB</TD>"); print("<TD ALIGN=right NOWRAP STYLE='border-style:solid'>", time.sqldate(dir[x].mtime), " ", time.sqltime(dir[x].mtime), "</TD>"); print("</TR>\n"); } } print("</TABLE>\n"); } else if (opt=='shell') { print("\n"); system("cd "+_POST['PATH']+" && "+_POST['COMMAND']); } else if (opt=='edit') { system("chmod u+r "+_POST['FILE']); x=file.readall(_POST['FILE']); if ((typeof(x)=='number')&&(x<0)) { print("can't read file"); } else { print(x); } } else if (opt=='save') { if (_POST['ATTACHMENT1_SIZE']!=null) { x=file.writeall(_POST['EDITNAME']+"-new", _POST['ATTACHMENT1']); } else { x=file.writeall(_POST['EDITNAME']+"-new", _POST['EDITWINDOW']); } _POST['EDITWINDOW']=""; if ((typeof(x)=='number')&&(x<0)) { print("can't write file '", _POST['EDITNAME'], "'\n"); } else { system("chmod 644 "+_POST['EDITNAME']+"-new"); print("Wrote '", _POST['EDITNAME'], "' (", x, " bytes).\n"); print("<SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\">\r\n<!--\r\nlocation.replace(\"", _SERVER['PATH_INFO'], "\");\r\n// -->\r\n</SCRIPT>\r\n"); print("<NOSCRIPT><META HTTP-EQUIV=\"Refresh\" CONTENT=\"1; URL=", _SERVER['PATH_INFO'], "\"></NOSCRIPT>\r\n"); } } else { print("INVALID REQUEST"); print("<pre>",serialize(_GLOBALS),"</pre>"); } exit; } function printjs() { print("<SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\">\n<!--\n"); print( "function newXMLHttpRequest() {\n", " var xmlreq = false;\n", "\n", " if (window.XMLHttpRequest) {\n", " xmlreq = new XMLHttpRequest();\n", " } else if (window.ActiveXObject) {\n", " try {\n", " xmlreq = new ActiveXObject('Msxml2.XMLHTTP');\n", " } catch (e1) {\n", " try {\n", " xmlreq = new ActiveXObject('Microsoft.XMLHTTP');\n", " } catch (e2) {\n", " // Unable to create an XMLHttpRequest with ActiveX\n", " }\n", " }\n", " }\n", " return xmlreq;\n", "}\n" ); print( "function doresponse(opt, c) {\n", " return function () {\n", " if (c.readyState==4) {\n", // " alert('HTTP status: '+c.status+'\\nHTTP return: '+c.responseText);\n", " if (c.status==200) {\n", " redraw(opt, c);\n", " } else {\n", " alert('HTTP status: '+c.status+'\\nHTTP return: '+c.responseText);\n", " }\n", " }\n", " }\n", "}\n" ); print( "function nexthand(opt, filename) {\n", " var c = newXMLHttpRequest();\n", " var handlerFunction = doresponse(opt, c);\n", " var fdata='';\n", "\n", " fdata='opt='+opt;\n", " if (opt=='edit') {\n", " showpage(3);\n", " document.editor.editname.value=filename;\n", " document.editor.editwindow.innerText='';\n", " fdata+='&file='+filename;\n", " }\n", " for (var i=0;i<document.shell.elements.length;i++) {\n", // " alert(document.shell[i].name+'='+document.shell[i].value);\n", " fdata+='&'+document.shell[i].name+'='+document.shell[i].value;\n", " }\n", " c.onreadystatechange = handlerFunction;\n", " c.open('post', '", _SERVER['PATH_INFO'], "', true);\n", " c.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n", " c.setRequestHeader('Connection', 'close');\n", " c.send(fdata);\n", "}\n" ); print("function redraw(opt, c) {\n"); print(" if (opt=='browse') {\n"); print( // " r=c.responseXML.documentElement;\n" " r=c.responseText;\n", " document.getElementById('browsewindow').innerHTML=r;\n" // " document.getElementById('browsewindow').innerText=r;\n" ); print(" } else if (opt=='shell') {\n"); print(" r=c.responseText;\n"); print(" document.shell.shellwindow.value=r;\n"); print(" } else if (opt=='edit') {\n"); print(" r=c.responseText;\n"); print(" document.editor.editwindow.value=r;\n"); print(" }\n"); print("}\n"); print("// -->\n</SCRIPT>\n"); print(" <SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\"> <!-- function showpage(page) { for (var i=1;i<4;i++) { if (i==page) { document.getElementById('page'+i+'tab').style.borderBottom='solid 0px #000000'; document.getElementById('page'+i+'tab').bgColor='#FFFFFF'; document.getElementById('page'+i).style.display='block'; } else { document.getElementById('page'+i+'tab').style.borderBottom='solid 1px #000000'; document.getElementById('page'+i+'tab').bgColor='#D0D0D0'; document.getElementById('page'+i).style.display='none'; } } } function showdebug() { if (document.getElementById('debug').style.display=='none') { document.getElementById('debug').style.display='block'; } else { document.getElementById('debug').style.display='none'; } } function doshell() { showpage(2); nexthand('shell'); return false; } function newparent(p) { showpage(1); document.shell.path.value=p; nexthand('browse'); } // --> </SCRIPT> "); return; } if (string.cmp(_SERVER['REQUEST_METHOD'], "POST")==0) { var path=_POST['PATH']; var command=_POST['COMMAND']; } else { var path=_filepath; var command="ps auxw"; } print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"); print(" <HTML> <HEAD> <TITLE>Nesla - Crappy Management system</TITLE> <STYLE TYPE=text/css> A { color: #0000FF; text-decoration: none; } A:HOVER { background-color: #E0E0FF; } </STYLE> "); printjs(); print(" </HEAD> <BODY> <CENTER> "); print(" <FORM ACTION='", _SERVER['PATH_INFO'], "' METHOD='POST' NAME='shell' onsubmit=\"return doshell();\"> <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0> <TR><TD>Path </TD><TD><INPUT SIZE=50 NAME='path' VALUE='", path, "'></TD><TD VALIGN=BOTTOM ROWSPAN=2><input type='submit' value='run' name='submit'></TD></TR> <TR><TD>Command</TD><TD><INPUT SIZE=50 NAME='command' VALUE='", command, "'></TD></TR> </TABLE> "); print(" <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%> <TR><TD ALIGN=LEFT><TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 STYLE='border-style:solid'> <TR> <TD ID=page1tab NOWRAP STYLE='border-style:solid'> <A ACCESSKEY=1 HREF='javascript:showpage(1);'>FILE BROWSER</A> </TD> <TD ID=page2tab NOWRAP STYLE='border-style:solid'> <A ACCESSKEY=2 HREF='javascript:showpage(2);'>SHELL</A> </TD> <TD ID=page3tab NOWRAP STYLE='border-style:solid'> <A ACCESSKEY=3 HREF='javascript:showpage(3);'>TEXT EDITOR</A> </TD> </TR></TABLE></TD></TR> <TR><TD VALIGN=TOP STYLE='padding:3px'><HR> <DIV ID=page1 STYLE='display: block'> <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%> <TR><TD COLSPAN=2><B> Browser window </B></TD></TR> <TR><TD><SPAN ID='browsewindow'></SPAN></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2>[<A HREF='javascript:nexthand(\"browse\");'> BROWSE FILES </A>]</TD></TR> </TABLE> </DIV> <DIV ID=page2 STYLE='display: block'> <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%> <TR><TD COLSPAN=2><B> Shell window </B></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2><TEXTAREA WRAP=PHYSICAL NAME=shellwindow ROWS=25 COLS=80 style='width:100%'></TEXTAREA></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2>[<A HREF='javascript:nexthand(\"shell\");'> RUN COMMAND </A>]</TD></TR> </TABLE> </FORM> </DIV> <DIV ID=page3 STYLE='display: block'> <FORM ACTION='", _SERVER['PATH_INFO'], "' METHOD='POST' NAME='editor' ENCTYPE='multipart/form-data'> <!--FORM ACTION='", _SERVER['PATH_INFO'], "' METHOD='POST' NAME='editor'--> <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%> <INPUT TYPE=hidden NAME=path VALUE='", path, "'> <INPUT TYPE=hidden NAME=opt VALUE='save'> <TR><TD COLSPAN=2><B> Editor window </B></TD></TR> <TR><TD STYLE='padding:0px'> <TR><TD><B>Filename</B></TD><TD ALIGN=RIGHT><INPUT SIZE=100 NAME='editname' VALUE='", "'></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2><TEXTAREA WRAP=OFF NAME=editwindow ROWS=25 COLS=80 style='width:100%'></TEXTAREA></TD></TR> <TR><TD><B>Upload File</B></TD><TD ALIGN=RIGHT><INPUT SIZE=100 NAME=ATTACHMENT1 TYPE=FILE></TD></TR> <TR><TD ALIGN=CENTER COLSPAN=2><input type='submit' value='Save' name='submit'></TD></TR> </TD></TR> </TABLE> </FORM> </DIV> <HR> </TD></TR> </TABLE> "); print(" <SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\"> <!-- document.shell.command.focus(); showpage(1); nexthand('browse'); // --> </SCRIPT> "); print("<A HREF='javascript:showdebug();'>DEBUG</A>\n"); print("</CENTER>\n"); print("<DIV ID=debug STYLE='display:none'><PRE><FONT SIZE=2>\n"); print(serialize(_GLOBALS)); print("</FONT></PRE></DIV>\n"); print("</BODY>\n</HTML>\n");