import.module.libsock; var http=func(){ var sd=nil; return { establish:func(ip,port){ sd=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP); if(socket.bind(sd,ip,port)<0){ println("failed to bind socket "~sd~" at IP: "~ip~" port: "~port~"."); return; } socket.listen(sd,1); println("[",os.time(),"] start server at [",ip,":",port,"]"); }, shutdown:func(){ println("[",os.time(),"] shutdown server"); socket.closesocket(sd); }, accept:func(){ return socket.accept(sd); }, disconnect:func(client,log=0){ if(log) println("[",os.time(),"] [",client.ip,"] disconnected"); return socket.closesocket(client.sd); }, recv:func(client){ var data=socket.recv(client.sd,2048); if(!data.size){ println("[",os.time(),"] [",client.ip,"] closed connection"); return nil; } var first=split("\n",data.str)[0]; var (type,path)=split(" ",first)[0,1]; println("[",os.time(),"] [",client.ip,"] request ",type," [",path,"]"); return {type:type,path:path}; }, send:func(client,content){ println("[",os.time(),"] [",client.ip,"] get size ",size(content)," byte(s)"); return socket.send(client.sd,content); } }; }(); http.establish("127.0.0.1",8080); var highlight_style=" "; var html_read_file=func(filename){ var timer=maketimestamp(); timer.stamp(); var keyword=["var","func","for","while","foreach","forindex","break","continue","return","if","else","elsif","nil"]; var file_text=io.fin(filename); var (s,index,len)=("",-1,size(file_text)); var content=""; var next=func(){ if(index+1>=len) return index+1; index+=1; s=char(file_text[index]); return index; } var prev=func(){ index-=1; s=char(file_text[index]); } while(1){ if(next()>=len) break; if(s==">") content~=">"; elsif(s=="<") content~="<"; elsif(s=="[" or s=="]" or s=="(" or s==")" or s=="{" or s=="}") content~=""~s~""; elsif(s=="=" or s=="," or s==";" or s==":" or s=="|" or s=="&" or s=="!" or s=="?" or s=="+" or s=="-" or s=="*" or s=="/" or s=="~" or s==".") content~=""~s~""; elsif(s=="_" or ("a"[0]<=s[0] and s[0]<="z"[0]) or ("A"[0]<=s[0] and s[0]<="Z"[0]) or s[0]<0 or s[0]>=128){ var tmp=""~s; # generate a new string while(1){ if(next()>=len) break; if(s=="_" or ("a"[0]<=s[0] and s[0]<="z"[0]) or ("A"[0]<=s[0] and s[0]<="Z"[0]) or ("0"[0]<=s[0] and s[0]<="9"[0]) or s[0]<0 or s[0]>=128) tmp~=s; else{ prev(); break; } } var is_key=0; foreach(var i;keyword) if(tmp==i){ is_key=1; content~=""~tmp~""; break; } if(!is_key) content~=""~tmp~""; }elsif("0"[0]<=s[0] and s[0]<="9"[0]){ content~=""~s; if(next()>=len){ content~=""; break; } if(s=="o"){ content~="o"; while(1){ if(next()>=len) break; if("0"[0]<=s[0] and s[0]<="7"[0]) content~=s; else break; } content~=""; prev(); }elsif(s=="x"){ content~="x"; while(1){ if(next()>=len) break; if(("0"[0]<=s[0] and s[0]<="9"[0]) or ("a"[0]<=s[0] and s[0]<='f') or ("A"[0]<=s[0] or s[0]<="F")) content~=s; else break; } content~=""; prev(); }elsif(("0"[0]<=s[0] and s[0]<="9"[0]) or s=="." or s=="e"){ while("0"[0]<=s[0] and s[0]<="9"[0]){ content~=s; if(next()>=len) break; } if(s=="."){ content~=s; if(next()>=len) break; } while("0"[0]<=s[0] and s[0]<="9"[0]){ content~=s; if(next()>=len) break; } if(s=="e"){ content~=s; if(next()>=len) break; if(s=="-" or s=="+"){ content~=s; if(next()>=len) break; } } while("0"[0]<=s[0] and s[0]<="9"[0]){ content~=s; if(next()>=len) break; } prev(); content~=""; }else{ prev(); content~=""; } }elsif(s=="\"" or s=="'" or s=="`"){ var quot=s~""; # generate a new string content~=""~s; while(1){ if(next()>=len) break; if(s==quot){ content~=s~""; break; }elsif(s=="\\"){ content~=s; if(next()>=len) break; content~=s; }elsif(s==">"){ content~=">"; }elsif(s=="<"){ content~="<"; }else{ content~=s; } } }elsif(s=="#"){ content~=""~s; while(1){ if(next()>=len) break; if(s=="\n" or s=="\r"){ content~=s; break; }elsif(s==">"){ content~=">"; }elsif(s=="<"){ content~="<"; }else{ content~=s; } } content~=""; } else content~=s; } println("[",os.time(),"] analyzed [",filename,"] for ",timer.elapsedMSec(),"ms"); return content; } var respond={ ok:func(html){ println("[",os.time(),"] respond 200 OK"); return "Http/1.1 200 OK\n\n"~html~"\n"; }, not_found:func(){ println("[",os.time(),"] respond 404 NOT FOUND"); return "Http/1.1 404 NOT FOUND\n\n 404 not found 404 NOT FOUND! \n"; }, teapot:func(){ println("[",os.time(),"] respond 418 I'm a teapot"); return "Http/1.1 418 I'm a teapot\n\n I'm a teapot This server cannot brew coffee because it is a teapot. \n"; } }; var files=func(){ var res={}; var dd=unix.opendir("./test"); while((var name=unix.readdir(dd))!=nil) res[name]=1; return res; }(); while(1){ var client=http.accept(); var data=http.recv(client); if(data==nil){ http.disconnect(client); continue; } if(data.type=="GET"){ var path=data.path; var args=split("?",path); var tmp={}; if(size(args)==2){ path=args[0]; args=split("=",args[1]); for(var i=0;i"~highlight_style~"\n
\n";
                var page_back="
\n\n\n"; http.send(client,respond.ok(page~html_read_file("./test/"~filename)~page_back)); }else{ http.send(client,respond.ok(io.fin("./doc/nasal-http-test-web.html"))); } } elsif(path=="/shutdown"){ http.send(client,respond.ok("http server shutdown.")); break; } elsif(path=="/favicon.ico") http.send(client,respond.ok(io.fin("./doc/pic/favicon.ico"))); elsif(path=="/license") http.send(client,respond.ok(io.fin("./LICENSE"))); elsif(path=="/doc/pic/nasal.png" or path=="/doc/pic/benchmark.png" or path=="/doc/pic/mandelbrot.png") http.send(client,respond.ok(io.fin("."~path))); else{ var filename=substr(path,1,size(path)-1); if(contains(files,filename)){ var page=" "~filename~" "~highlight_style~"\n
\n";
                var page_back="
\n\n\n"; http.send(client,respond.ok(page~html_read_file("./test/"~filename)~page_back)); } elsif(filename=="teapot") http.send(client,respond.teapot()); else http.send(client,respond.not_found()); } }elsif(data.type=="POST"){ http.send(client,respond.not_found); } http.disconnect(client); } http.shutdown();