#!/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()