#!/usr/bin/python2 # -*- coding: latin-1 -*- # ---------------------------------------------- # Llamar al servidor con interfaz web service # ---------------------------------------------- # Inicio de programa python sltsrw.py [-d] [-portnnnn] # -d: Debug, imprime información de trace # -portnnnn: Escucha por el puerto nnnn en vez de escuchar por el puerto 8080 # # El programa necesita que este escuchando el servidor sltsrv por el puerto que # se indica en salt.ini # Si sltsrv no está activo, lo inicia a partir de la información contenida # en el archivo salt.ini que ha de estar en la misma carpeta que sltsrw import sys import os import time import socket import threading import cgi import cStringIO import SimpleHTTPServer from StringIO import StringIO import Cookie class ScriptRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): """One instance of this class is created for each HTTP request""" def do_GET(self): """Begin serving a GET request""" # build self.body from the query string self.body = {} if self.path.find('?')>-1: qs = self.path.split('?',1)[1] self.body = cgi.parse_qs(qs, keep_blank_values=1) self.handle_data() def do_POST(self): """Begin serving a POST request. The request data is readable on a file-like object called self.rfile""" ctype, pdict = cgi.parse_header(self.headers.getheader('content-type')) length = int(self.headers.getheader('content-length')) if ctype == 'multipart/form-data': self.body = cgi.parse_multipart(self.rfile, pdict) elif ctype == 'application/x-www-form-urlencoded': qs = self.rfile.read(length) self.body = cgi.parse_qs(qs, keep_blank_values=1) else: self.body = {} # Unknown content-type # some browsers send 2 more bytes... [ready_to_read,x,y] = select.select([self.connection],[],[],0) if ready_to_read: self.rfile.read(2) self.handle_data() def handle_data(self): """Process the data received""" #Comprobar si es cliente autorizado if _ini.Existe("sltsrw","ipsok"): ipsok=eval(_ini("sltsrw","ipsok")) if ipsok!=[]: if ipsok.count(self.client_address[0])==0: self.send_error(401,"Cliente no autorizado") return self.resp_headers = {"Content-type":'text/html'} # default self.cookie=Cookie.SimpleCookie() if self.headers.has_key('cookie'): self.cookie=Cookie.SimpleCookie(self.headers.getheader("cookie")) if self.body!={}: if dbg: print "conectat (web) client",self.client_address sck=socketConnect() if sck!=None: sck.send(self.body['salt4msg'][0]) datos=sck.recv(128000) else: self.send_error(503,"No responde el server (sltsrv)") return ctype='text/plain' f=StringIO() f.write(datos) f.seek(0) self.resp_headers['Content-type'] = ctype self.resp_headers['Content-length'] = str(len(datos)) self.done(200,f) return path = self.get_file() # return a file name or None if os.path.isdir(path): # list directory dir_list = self.list_directory(path) self.copyfile(dir_list, self.wfile) return ext = os.path.splitext(path)[1].lower() if len(ext)>1 and hasattr(self,"run_%s" %ext[1:]): # if run_some_extension() exists exec ("self.run_%s(path)" %ext[1:]) else: # other files ctype = self.guess_type(path) if ctype.startswith('text/'): mode = 'r' else: mode = 'rb' try: f = open(path,mode) self.resp_headers['Content-type'] = ctype self.resp_headers['Content-length'] = str(os.fstat(f.fileno())[6]) self.done(200,f) except IOError: self.send_error(404, "File not found") def done(self, code, infile): """Send response, cookies, response headers and the data read from infile""" self.send_response(code) for morsel in self.cookie.values(): self.send_header('Set-Cookie', morsel.output(header='').lstrip()) for (k,v) in self.resp_headers.items(): self.send_header(k,v) self.end_headers() infile.seek(0) self.copyfile(infile, self.wfile) def get_file(self): """Set the Content-type header and return the file open for reading, or None""" path = self.path if path.find('?')>1: # remove query string, otherwise the file will not be found path = path.split('?',1)[0] path = self.translate_path(path) if os.path.isdir(path): for index in "index.html", "index.htm": index = os.path.join(path, index) if os.path.exists(index): path = index break return path def run_py(self, script): """Run a Python script""" # redirect standard output so that the "print" statements # in the script will be sent to the web browser sys.stdout = cStringIO.StringIO() # build the namespace in which the script will be run namespace = {'request':self.body, 'headers' : self.headers, 'resp_headers':self.resp_headers, 'Session':self.Session, 'HTTP_REDIRECTION':HTTP_REDIRECTION} try: execfile (script,namespace) except HTTP_REDIRECTION,url: self.resp_headers['Location'] = url self.done(301,cStringIO.StringIO()) except: # print a traceback # first reset the output stream sys.stdout = cStringIO.StringIO() exc_type,exc_value,tb=sys.exc_info() msg = exc_value.args[0] if tb.tb_next is None: # errors (detected by the parser) line = exc_value.lineno text = exc_value.text else: # exceptions line = tb.tb_next.tb_lineno text = open(script).readlines()[line-1] print '%s in file %s : %s' %(exc_type.__name__, os.path.basename(script), cgi.escape(msg)) print '
Line %s' %line print '
%s
' %cgi.escape(text) self.resp_headers['Content-length'] = sys.stdout.tell() self.done(200,sys.stdout) def run_tpl(self,script): """Templating system with the string substitution syntax introduced in Python 2.4""" # values must be strings, not lists dic = dict([ (k,v[0]) for k,v in self.body.items() ]) # first check if the string.Template class is available if hasattr(string,"Template"): # Python 2.4 or above try: data = string.Template(open(script).read()).substitute(dic) except: exc_type,exc_value,tb=sys.exc_info() msg = exc_value.args[0] data = '%s in file %s : %s' \ %(exc_type.__name__,os.path.basename(script), cgi.escape(msg)) else: data = "Unable to handle this syntax for " + \ "string substitution. Python version must be 2.4 or above" self.resp_headers['Content-length'] = len(data) self.done(200,cStringIO.StringIO(data)) def Session(self): """Session management If the client has sent a cookie named sessionId, take its value and return the corresponding SessionElement objet, stored in sessionDict Otherwise create a new SessionElement objet and generate a random 8-letters value sent back to the client as the value for a cookie called sessionId""" if self.cookie.has_key("sessionId"): sessionId=self.cookie["sessionId"].value else: sessionId=generateRandom(8) self.cookie["sessionId"]=sessionId try: sessionObject = sessionDict[sessionId] except KeyError: sessionObject = SessionElement() sessionDict[sessionId] = sessionObject return sessionObject # end of class ScriptRequestHandler import SocketServer class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass # end of class ThreadingTCPServer class CfgFile: def __init__(self,file=None): import ConfigParser self.cfg=ConfigParser.ConfigParser() if file==None: miCfg=os.path.dirname(os.path.abspath(__file__)) if os.path.basename(miCfg)[-3:].lower()=='zip': miCfg=os.path.dirname(miCfg) miCfg=os.path.abspath(miCfg+"/salt.cfg") else: miCfg=file self.cfg.read(miCfg) def __call__(self,sec,opt): ret=None if self.cfg.has_option(sec,opt): ret=self.cfg.get(sec,opt) lret=ret.lower() if lret=="true" or lret=="sí" or lret=="si" or lret=="1" or lret=="s": ret=True elif lret=="false" or lret=="no" or lret=="0" or lret=="n": ret=False elif ret.isdigit(): ret=eval(ret) return ret def Existe(self,sec,opt): ret=False if self.cfg.has_option(sec,opt): if self.cfg.get(sec,opt) != "": ret=True return ret # End of Class CfgFile _ini=CfgFile() def socketConnect(): try: sck=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sck.connect(('localhost',20001)) except: print 'Cal iniciar el servidor Salt4 (sltsrv)' sck=None return sck miPath=os.path.dirname(os.path.abspath(__file__)) if os.path.basename(miPath)[-3:].lower()=='zip': miPath=os.path.dirname(miPath) esprod=True port=8080 dbg=False if _ini.Existe("sltsrw","port"): port=_ini("sltsrw","port") for arg in sys.argv: if arg[0:2]=="-d": dbg=True elif arg[0:5]=="-port": port=arg[5:] if esprod: s=SocketServer.ThreadingTCPServer(('',port),ScriptRequestHandler) else: s=SocketServer.TCPServer(('',port),ScriptRequestHandler) if dbg: print "Esperant conexió web",port print "exe,prefix,args,miPath",sys.executable,sys.exec_prefix,sys.argv,miPath s.serve_forever()