obelisk http 0.4.4.py :  » Web-Server » Obelisk » obelisk-http » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Server » Obelisk 
Obelisk » obelisk http » obelisk-http-0.4.4.py
#!/usr/bin/python
#Obelisk http 0.4.4

#Filipe Caldas 27/19/2007

try:
    import socket,thread,os,sys,popen2
    from time import localtime
except:
    print "Some lib isn't installed."
try:
    import psyco
    psyco.full()
except:
    pass

#HERE IS THE CONFIG OF YOUR SERVER#

#CONFIG 
BINDER='127.0.0.1'                       #where the socket will be binded with bind((BINDER,PORT))
PORT=8080                                #listen port
HTML_DIR=os.curdir+'/html'               #dir where is the html stuff (no / in end)
CGI_DIR=os.curdir+'/cgi-bin/'            #dir where CGI-BIN is (/ in end!)
BAAR='/index.html'                       #file to send if GET /
LOGFILE='c:/obelisk-log.txt'             #Acess/Error Log file
BUFF=512                                 #Size to receive in HEAD requests
PHP='c:/php-5.2.4-Win32/php.exe'         #Where is the PHP executable, '' to disable php
PHPBINDER='./pybind.php'                 #this will be the PHP var interp who will pass from environment to $_GET[varname](don't change unless you know what you are making)
#/CONFIG


######################################################
#Global variables
######################################################
VERSION="0.4.4"
IDENT="Obelisk-HTTP"


######################################################
#Main
######################################################

def main():
    port=PORT
    server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    print "Obelisk Web Server "+VERSION+"\n\n"
    try:
        server.bind((BINDER,port))
    except:
        print "Error trying to bind to "+BINDER+":"+ str(port)
        raw_input("[Exit]")
        sys.exit(0)
    server.listen(5)
    print "Listening in "+ BINDER +":"+str(port)+"\n"
    client,address=server.accept()
    LogClient("Connection from " + str(address[0]) + " : " + str(address[1]))
    thread.start_new_thread(connection,(client,))
    while 1:
        client,address=server.accept()
        LogClient("Connection from " + str(address[0]) + " : " + str(address[1]))
        thread.start_new_thread(connection,(client,))

######################################################

######################################################

def connection(client):
    try:
        msg=client.recv(4) #head the method(POST,GET,HEAD?)
    except:
        LogClient("Connection Reset by Peer")
    if msg[0:3]=="GET":
        REQUEST_GET(client,msg)     #ok(absolutly no bugs)
    elif msg[0:4]=="POST":
        REQUEST_POST(client,msg)    #ok(popen2 is making me cry)
    elif msg[0:4]=="HEAD":
        REQUEST_HEAD(client,msg)
    else:
        SENDFILE(client,HTML_DIR+"/malformed.html","r",1)
    return 0

#####################################################

#####################################################

def LogClient(Message):
    try:
      fd=open(LOGFILE,'a')
    except:
        print "Error: Can't write to "+LOGFILE
        print "Change the LOGFILE variable to an existent file with permissions to write!"
        return 1
    tm=localtime()
    fd.write(str(tm[3]) + ":" + str(tm[4]) + "  " + str(tm[2]) + '/' + str(tm[1]) + '/' + str(tm[0]) + ":" + str(Message) + "\r\n")
    fd.close()
    return(0)

#####################################################

#####################################################

def SENDFILE(client,filename,readmethod,entire):
    """Send a file to a socket readmethod=r/rb entire=0/1 read entire file?"""
    if entire==1:
        try:
            fd=open(filename, readmethod)
        except:
            return 1
        client.send(fd.read())
    else:
        try:
            fd=open(filename, readmethod)
        except:
            return 1        
        EOF=0
        while EOF!=1:
            LN=fd.readline()
            if LN!='':
                client.send(LN)
            else:
                fd.close()
                EOF=1
    return 0

#####################################################

#####################################################

def SENDFILE2(client,filename,readmethod,entire,HEAD):
    """Send a file to a socket readmethod=r/rb entire=0/1 read entire file?"""
    """Request=Complete Server Request"""
    """This is a try to suport MS browsers"""
    if entire==1:
        try:
            fd=open(filename, readmethod)
        except:
            return 1
        bex=fd.read() #just read the file
        #this create a W3 header to file
        if bex[0:2]!="<!" and (filename[-3:]=='htm' or filename[-4:]=='html'):
            bex='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'+bex
        if HEAD!='':
            a=Decode_Header(HEAD,filename,len(bex))
            if a!=None:
                bex=a+bex
        client.send(bex)
    else:
        try:
            fd=open(filename, readmethod)
        except:
            return 1        
        EOF=0
        while EOF!=1:
            LN=fd.readline()
            if LN!='':
                client.send(LN)
            else:
                fd.close()
                EOF=1
    return 0

#####################################################

#####################################################

def Decode_Header(Header,Fname,LENBFF):
    """Receive a Get Request Header and a filename and try to interp"""
    """And return a response Header"""
    RETHEADER=''
    if Header=='':
        return ''
    else:
        dt=localtime()
        RETHEADER='HTTP/1.1 200 OK\nDate: ' + str(dt[2]) + ' ' +str(dt[1])+ ' ' + str(dt[0]) + ' ' +str(dt[3]) + ':' + str(dt[4]) + ':' + str(dt[5]) + "\n"
        RETHEADER=RETHEADER+'Server: ' + IDENT +'\n'
        RETHEADER=RETHEADER+'Content-Lenght: '+str(LENBFF)+"\n"
        if Header.find("Connection:")!=-1:
            RETHEADER=RETHEADER+'Connection: Keep-Alive\n'
            RETHEADER=RETHEADER+'Keep-Alive: timeout=5, max=100\n'
        return RETHEADER+"\n"
            
#####################################################

#####################################################


def Basic_Header(Header):
    """Receive a Get Request Header and a filename and try to interp"""
    """And return a response Header"""
    RETHEADER=''
    if Header=='':
        return ''
    else:
        dt=localtime()
        RETHEADER='HTTP/1.1 200 OK\nDate: ' + str(dt[2]) + ' ' +str(dt[1])+ ' ' + str(dt[0]) + ' ' +str(dt[3]) + ':' + str(dt[4]) + ':' + str(dt[5]) + "\n"
        RETHEADER=RETHEADER+'Server: ' + IDENT +'\n'
        if Header.find("Connection:")!=-1:
            RETHEADER=RETHEADER+'Connection: Keep-Alive\n'
            RETHEADER=RETHEADER+'Keep-Alive: timeout=5, max=100\n'
        return RETHEADER+"\n"
    
#####################################################

#####################################################

def EXECFILE(client,filename):
    """Execute a file and pass MSG to stdin, the response is sent to client"""
    try:
        if filename.find(".pl")!=-1 or filename.find(".py")!=-1 or filename.find(".cgi")!=-1 or filename.find(".sh")!=-1:
            fd=open(filename,"r")
            execpath=fd.readline()
            execpath=execpath[2:-1] #remove #! and \n
            execpath=execpath + " " + filename #WARNING
            filename=execpath
        if filename.find(";")!=-1 or filename.find("|")!=-1 or filename.find("$")!=-1 or filename.find("*")!=-1 or filename.find("@")!=-1 or filename.find("%")!=-1 or filename.find("&")!=-1 or filename.find("`")!=-1:
            return 1
        stdin, stdout = popen2.popen2(filename)
    except:
        return 1
    try:
        GOT=stdin.read()
        client.send(GOT)
        client.close()
    except:
        print "A fatal error ocurred when executing "+filename
        return 1
    return 0

#####################################################

#####################################################

def DOLIST_TO(client,msg):
    """Send a archive list to the client when he call a dir who end in /"""
    """Don't show nothing if"""
    try:
        bck=msg
        #HTML="Connection: close\nContent-type: text/html; charset=iso-8859-1\n\n"
        HTML='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
        HTML=HTML+'<html><title>'+msg+'</title><body><h3>Index of '+msg+'</h3><hr><br><br>'
        msg=HTML_DIR+msg
        ret=os.access(msg,os.F_OK)
        if ret==True:
            LIST=os.listdir(msg)
            for x in range(0,len(LIST)):
                if LIST[x]=="NO_ACCESS":
                    DO404(client)
                    return -1;
                elif LIST[x]=="index.html" or LIST[x]=="index.htm":
                    SENDFILE(client,HTML_DIR+bck+LIST[x],'r',1)
                    close(client);
                    return 2;
                HTML=HTML+'<b><a href="'+bck+LIST[x]+'">'+LIST[x]+'</a><br>'
            #Send page...
            HTML=HTML+'<br><hr><br><center><h6>'+IDENT+'</h6></center></body></html>'
            client.send(HTML)
            client.close()
        else:
            404(client)
    except:
        client.close()        
            

#####################################################
            
#####################################################

def DO404(client):
    err=SENDFILE(client,HTML_DIR+'/404.html','r',1)
    if err==1:
        print 'Error! > No :' + HTML_DIR + '/404.html'
        LogCLient("You must create a 404.html file in "+HTML_DIR+"\r\n")
    client.close()

#####################################################
                
#####################################################

def REQUEST_HEAD(client,frstbff):
    """Make a HEAD request"""  
    msg=frstbff+client.recv(BUFF-4)
    os.environ["REQUEST_METHOD"]='HEAD'
    pos=msg.find("\n")
    msg=msg[5:pos]
    if msg.find('HTTP/')!=-1:
        pos=msg.find('HTTP/')
        pos=pos-1
        msg=msg[0:pos]
    #transversal
    if msg.find("..")!=-1:
        client.close()
        return 0
    if msg.find("cgi-bin")==1:
        #404 no support to EXEC insisde HEAD method
        DO404(client)
    else:
        try:
            if msg[-1:]=="/" and msg!="/":
                DOLIST_TO(client,msg)
                return 0;
            elif os.stat(HTML_DIR+msg)[6]==0:
                DOLIST_TO(client,msg+'/')
                return 0;
        except:
            pass
        if msg == "/":
            msg=BAAR
        if msg.find('.html')!=-1 or msg.find('.htm')!=-1:
            err=SENDFILE(client,HTML_DIR+msg,'r',1)
        elif msg.find('.txt')!=-1 or msg.find('.c')!=-1:
            err=SENDFILE(client,HTML_DIR+msg, 'r',1)
        else:
            err=SENDFILE(client,HTML_DIR+msg,'rb',0)  
        if err==1:
            err=SENDFILE(client,HTML_DIR+'/404.html','r',1)
            if err==1:
                DO404(client)
                return -1
    return 0
    


#####################################################
                
#####################################################


def REQUEST_GET(client,frstbff):
    """Make a GET request client is the client socket and frstbff the first 4 bytes"""  
    msg=frstbff+client.recv(BUFF-4)
    os.environ["REQUEST_METHOD"]='GET' #set environment
    pos=msg.find("\n")
    msg=msg[4:pos]
    if msg.find('HTTP/')!=-1:
        pos=msg.find('HTTP/')
        pos=pos-1
        REQUEST_HEADER=msg[pos:] #a try to respond to browser subrequests
        msg=msg[0:pos]
    #check for transversal directory
    if msg.find("..")!=-1:
        client.close()
        return 0
    if msg.find("cgi-bin")==1:
        if msg.find(';')!=-1:
            client.close()
            return 1
        #here msg looks something like /cgi-bin/....
        msg=msg[9:] #remove "/cgi-bin/" now we have scriptname.x?var1=value1&...
        if msg.find('?')!=-1:
            #we have arguments to the cgi script
            pos=msg.find('?')
            opt=msg[(pos+1):]
            msg=msg[0:pos]
            os.environ['QUERY_STRING']=opt
            #environment set..
            #print CGI_DIR+msg
            err = EXECFILE(client,CGI_DIR+msg)
            if err==1:    
                err=SENDFILE(client,HTML_DIR+'/404.html','r',1)
                if err==1:
                    print "Error! > No "+HTML_DIR+'/404.html'
            
        else:
            err = EXECFILE(client,CGI_DIR+msg)
            if err==1:    
                err=SENDFILE(client,HTML_DIR+'/404.html','r',1)
                if err==1:
                    print "Error! > No "+HTML_DIR+'/404.html'
                    LogClient("You must create a 404.html file in "+HTML_DIR+"\r\n")
    else:
        try:
            if msg[-1:]=="/" and msg!="/":
                DOLIST_TO(client,msg)
                return 0;
            elif os.stat(HTML_DIR+msg)[6]==0:
                DOLIST_TO(client,msg+'/')
                return 0;
        except:
            pass
        if msg.find('?')!=-1:
            pos=msg.find('?')
            opt=msg[(pos+1):]
            msg=msg[0:pos]
            os.environ['QUERY_STRING']=opt
                
        if msg == "/":
            msg=BAAR
        if msg[-5:]=='.html' or msg[-4:]=='.htm':
            err=SENDFILE2(client,HTML_DIR+msg,'r',1,REQUEST_HEADER)
        elif msg[-4:]=='.php' and PHP!='':
            try:
                os.stat(HTML_DIR+msg)
            except:
                DO404(client)
                return 1
            REQUEST_HEADER=Basic_Header(REQUEST_HEADER)
            TEXT=exec_php(HTML_DIR+msg)
            if TEXT==-1:
                DO404(client)
                return 1
            else:
                client.send(REQUEST_HEADER+TEXT)
                client.close()
                return 0
        elif msg[-4:]=='.txt' or msg[-2:]=='.c':
            err=SENDFILE2(client,HTML_DIR+msg, 'r',1,REQUEST_HEADER)
        else:
            err=SENDFILE2(client,HTML_DIR+msg,'rb',0,REQUEST_HEADER)  
        if err==1:
            err=SENDFILE2(client,HTML_DIR+'/404.html','r',1,REQUEST_HEADER)
            if err==1:
                print 'Error! > No :' + HTML_DIR + '/404.html'
                LogCLient("You must create a 404.html file in "+HTML_DIR+"\r\n")
    client.close()
    return 0
            
######################################################
            
######################################################

def exec_php(filename):
    os.environ["INCLUDE"]=filename
    if os.environ["REQUEST_METHOD"]=='GET':
        try:
            stdin, stdout = popen2.popen2(PHP+" "+PHPBINDER) #PHPBINDER WILL include(filename)
            stdout.close()
            GOT=stdin.read()
            return GOT
        except:
            print "PHP binder cannot be executed as :"+PHP+""+PHPBINDER;
            return -1
    else:
        return -1;

######################################################
            
######################################################

def REQUEST_POST(client,msg):
    os.environ["REQUEST_METHOD"]='POST' #set post
    while msg.find("\n")==-1:
        msg=msg+client.recv(1)
    finder=""
    while finder.find("Content-Length:")==-1:
        while finder.find('\n')==-1:
            finder=finder+client.recv(1)
        if finder.find("Content-Length:")==-1:
            finder=""
    finder=finder[16:-2] #remove \r\n and Content Lenght..
    next_read=int(finder)
    while finder.find('\n')==-1:
        finder=finder+client.recv(1)
    POST=client.recv(next_read)
    #remove trash from msg (POST /)
    msg=msg[5:]; #+7 or +8 to remove cgi-bin
    if msg.find("HTTP/")==-1:
        msg=msg[0:-2]
    else:
        msg=msg[0:msg.find('HTTP/')]
    if msg.find(';')!=-1:
        client.close()
        return 0
    if msg.find('..')!=-1:
        client.close()
        return 0
    msg=msg[:-1]
    if  msg[-4:]==".php":
        RETX=_exec_PHP(HTML_DIR+msg,POST)
        if RETX==-1: #error he receive a beautiful 404 msg
            DO404(client)
            return 1
        else:
            try:
                client.send(RETX)
                client.close() 
                return 0
            except:
                pass
                return 
    #Isn't a php, remove cgi-bin/ and continue
    if msg.find("cgi-bin")!=-1:
        msg=msg[9:]
        if  EXEC_ARGC(client,CGI_DIR+msg,POST)==0:
            return 0
        else:
            if SENDFILE(client,HTML_DIR+'/404.html','r',1)==1:
                print 'Error! > No :' + HTML_DIR + '/404.html'
                LogClient("You must create a 404.html file in "+HTML_DIR+"\r\n")
        return 0
    else:
        DO404(client)
        return 1
            
######################################################
            
######################################################

def EXEC_ARGC(client,filename,msg):
    """Execute a file and pass MSG to stdin, the response is sent to client"""
    try:
        if filename.find(".pl")!=-1 or filename.find(".py")!=-1 or filename.find(".cgi")!=-1 or filename.find(".sh")!=-1:
            fd=open(filename,"r")
            execpath=fd.readline()
            execpath=execpath[2:-1] #remove #! and \n
            execpath=execpath + " " + filename #WARNING
            filename=execpath
        if filename.find(";")!=-1 or filename.find("|")!=-1 or filename.find("$")!=-1 or filename.find("*")!=-1 or filename.find("@")!=-1 or filename.find("%")!=-1 or filename.find("&")!=-1 or filename.find("`")!=-1:
            return 1
        stdin, stdout = popen2.popen2(filename)
    except:
        return 1
    try:
#Remove # to debug
#        print "Passing>"+msg
        stdout.write(msg)
#        print "Passed"
        stdout.close()
#        print "Reading"
        GOT=stdin.read()
        client.send(GOT)
#        print "Send "+GOT
        client.close()
    except:
        print "A fatal error ocurred when executing "+filename
        return 1
    return 0

######################################################

######################################################

def _exec_PHP(PHP_FILE,MSG):
    os.environ["INCLUDE"]=PHP_FILE
    os.environ["QUERY_STRING"]=MSG
    try:
        stdin, stdout = popen2.popen2(PHP+" "+PHPBINDER)
    except:
        print "PHP binder cannot be executed as :"+PHP+""+PHPBINDER;
        return 1
    try:
        stdout.close()
        GOT=stdin.read()
        return GOT
    except:
        return -1
    return 0

######################################################

######################################################

#call main();
if __name__ == '__main__':
   main()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.