cgiparams.py et cgilsxml.py: modifications pour gérer la construction de QUERY_STRING

This commit is contained in:
Jephté Clain 2016-02-07 23:03:38 +04:00
parent 16b18f2048
commit 24f32118a8
2 changed files with 112 additions and 14 deletions

View File

@ -6,7 +6,7 @@ u"""Ce script est prévu pour être utilisé dans un script CGI.
Il permet de lister le contenu d'un répertoire au format XML, et de télécharger les fichiers trouvés.
"""
import os, sys, re, shutil, mimetypes, urlparse
import os, sys, re, shutil, mimetypes, urlparse, urllib
from os import path
from time import time, localtime
from types import UnicodeType, StringTypes
@ -178,18 +178,58 @@ def cgi_nocache():
print "Pragma: no-cache"
print "Expires: Thu, 01 Jan 1970 00:00:00 GMT"
def print_files(files, fgroups=None, select_group=None, script_name=None, query_string=None, xslt=None):
RE_COMMA = re.compile(',')
def lfix(values):
if values is None: return None
fvalues = []
for parts in values:
parts = RE_COMMA.split(parts)
fvalues.extend(parts)
return fvalues
def filter_query_string(query_string, includes=None, excludes=None, prefix=None):
params = urlparse.parse_qsl(query_string, keep_blank_values=True)
includes = lfix(includes)
if includes is None: names = dict(params).keys()
else: names = includes[:]
excludes = lfix(excludes)
if excludes is not None:
for name in excludes:
if name in names: names.remove(name)
params = [(name, value) for (name, value) in params if name in names]
query_string = urllib.urlencode(params)
if prefix:
if query_string != "": query_string = "%s&%s" % (prefix, query_string)
elif prefix != "": query_string = prefix
return query_string
def print_files(files, fgroups=None, select_group=None, script_name=None, xslt=None,
query_string=None, includes=None, excludes=None, prefix=None):
xresult = ET.Element("result")
xenv = ET.SubElement(xresult, "env")
if script_name is not None:
ET.SubElement(xenv, "script_name").text = _u(script_name)
ET.SubElement(xenv, "script_base").text = _u(re.sub(r'[^/]+$', '', script_name))
if query_string is not None:
fquery_string = filter_query_string(query_string, includes, excludes, prefix)
query_string = _u(query_string)
params = urlparse.parse_qsl(query_string, keep_blank_values=True)
fquery_string = _u(fquery_string)
fparams = urlparse.parse_qsl(fquery_string, keep_blank_values=True)
if includes or excludes or prefix:
xorig = ET.SubElement(xenv, "orig")
if query_string: query_string = u'?%s' % query_string
ET.SubElement(xorig, "query_string").text = query_string
xvars = ET.SubElement(xorig, "query_vars")
for name, value in params:
ET.SubElement(xvars, name).text = value
query_string = fquery_string
params = fparams
if query_string: query_string = u'?%s' % query_string
ET.SubElement(xenv, "query_string").text = query_string
xvars = ET.SubElement(xenv, "query_vars")
for name, value in urlparse.parse_qsl(query_string, keep_blank_values=True):
ET.SubElement(xvars, "var", name=name, value=value)
for name, value in params:
ET.SubElement(xvars, name).text = value
xfgroups = ET.SubElement(xresult, "fgroups")
if fgroups is not None:
for fgroup in fgroups:
@ -246,17 +286,20 @@ def run_cgilsxml():
help=u"Spécifier la valeur de QUERY_STRING pour provisionner l'environnement du fichier résultat. En mode CGI, cette valeur est prise dans la variable d'environnement QUERY_STRING.")
OP.add_option('-N', '--cgi-script-name', dest='script_name',
help=u"Spécifier la valeur de SCRIPT_NAME pour provisionner l'environnement du fichier résultat. En mode CGI, cette option est automatiquement activée si QUERY_STRING contient le paramètre script_name=SCRIPT_NAME, la valeur par défaut étant la valeur de la variable d'environnement SCRIPT_NAME."
+ u"\n Note: pour la lecture des paramètres de QUERY_STRING, l'API cgi.FieldStorage() est utilisé, ce qui fait que la valeur éventuellement fournie par l'option --cgi-query-string est ignorée."
+ u"\n L'ordre de priorité pour le calcul de cette valeur est: d'abord le paramètre script_name dans QUERY_STRING, puis l'option de la ligne de commande, enfin la valeur de la variable d'environnement")
OP.add_option('-G', '--cgi-param-group', dest='select_group',
help=u"Sélectionner le groupe spécifié. Seuls les fichiers du groupe sont affichés. En mode CGI, cette option est automatiquement activée si QUERY_STRING contient le paramètre group=GROUP."
+ u"\n S'il n'y a qu'un seul groupe, il est automatiquement sélectionné."
+ u"\n cf la note pour --cgi-script-name pour le calcul de cette valeur."
+ u"\n L'ordre de priorité pour le calcul de cette valeur est: d'abord le paramètre group dans QUERY_STRING, puis l'option de la ligne de commande")
OP.add_option('-t', '--cgi-param-xslt', dest='xslt',
help=u"Ajouter le chemin vers la feuille de style XSLT dans le flux XML généré. En mode CGI, cette option est automatiquement activée si QUERY_STRING contient le paramètre xslt=XSLT."
+ u"\n cf la note pour --cgi-script-name pour le calcul de cette valeur."
+ u"\n L'ordre de priorité pour le calcul de cette valeur est: d'abord le paramètre xslt dans QUERY_STRING, puis l'option de la ligne de commande")
OP.add_option('-i', '--include', dest='includes', action='append',
help=u"Spécifier un paramètre à inclure pour construire la valeur du chemin xpath /result/env/query_string dans le résultat. Il est possible de spécifier plusieurs paramètres en les séparant par des virgules. Par défaut, prendre tous les paramètres de la requête.")
OP.add_option('-x', '--exclude', dest='excludes', action='append',
help=u"Spécifier un paramètre à exclure pour construire la valeur du chemin xpath /result/env/query_string dans le résultat. Il est possible de spécifier plusieurs paramètres en les séparant par des virgules.")
OP.add_option('-p', '--prefix', dest="prefix",
help=u"Ajouter les paramètres supplémentaires spécifiés à /result/env/query_string.")
env = dict(filters=[], filter=None)
o, args = OP.parse_args()
filters = env['filters']
@ -266,14 +309,15 @@ def run_cgilsxml():
environ = os.environ
cgi_cache = o.cgi_allow_cache and True or False
cgi_mode = o.cgi_mode
cgi_query_string = o.query_string
if cgi_query_string is not None: environ['QUERY_STRING'] = cgi_query_string
if cgi_mode is None:
cgi_mode = 'REQUEST_METHOD' in environ
if cgi_mode:
import cgi; form = cgi.FieldStorage()
cgi_path_info = o.path_info
if cgi_path_info is None and 'PATH_INFO' in environ : cgi_path_info = environ.get('PATH_INFO')
cgi_query_string = o.query_string
if cgi_query_string is None and 'QUERY_STRING' in environ : cgi_query_string = environ.get('QUERY_STRING')
if cgi_query_string is None and 'QUERY_STRING' in environ: cgi_query_string = environ.get('QUERY_STRING')
cgi_script_name = None
if 'script_name' in form and cgi_script_name is None: cgi_script_name = form.getfirst("script_name")
if cgi_script_name is None: cgi_script_name = o.script_name
@ -339,7 +383,8 @@ def run_cgilsxml():
if not cgi_cache: cgi_nocache()
print "Content-Type: text/xml; charset=UTF-8"
print
print_files(files, fgroups, cgi_select_group, cgi_script_name, cgi_query_string, cgi_xslt)
print_files(files, fgroups, cgi_select_group, cgi_script_name, cgi_xslt,
cgi_query_string, o.includes, o.excludes, o.prefix)
if __name__ == '__main__':
run_cgilsxml()

View File

@ -3,10 +3,16 @@
u"""Ce script est prévu pour être utilisé dans un script CGI.
Il permet de lister les paramètres du formulaire et d'y accéder depuis un script bash
Il permet de lister les paramètres du formulaire et d'y accéder depuis un script
bash. Le tableau QVARS est initialisé avec la liste des variables correspondant
aux paramètres pour lesquels une valeur est définie.
Les arguments de ce script doivent être de la forme NAME[=DEFAULT]. Si le
paramètres était fourni dans la requête, il est affiché, sous forme de scalaire
ou de tableau. S'il n'était pas fourni, la valeur par défaut est affichée.
"""
import re, cgi
import re, cgi, urllib
RE_NAME_VALUE = re.compile(r'([a-zA-Z0-9_-]+)(?:=(.*))?$')
@ -21,17 +27,58 @@ def print_scalar(name, value):
print "%s=%s" % (name, quote(value))
def print_array(name, values):
print "%s=(" % name
print "%s=(" % name,
for value in values:
print quote(value, True)
print quote(value, True),
print ")"
RE_COMMA = re.compile(',')
def lfix(values):
if values is None: return None
fvalues = []
for parts in values:
parts = RE_COMMA.split(parts)
fvalues.extend(parts)
return fvalues
def build_query_string(form, includes=None, excludes=None, prefix=None):
includes = lfix(includes)
if includes is None: names = form.keys()
else: names = includes[:]
excludes = lfix(excludes)
if excludes is not None:
for name in excludes:
if name in names: names.remove(name)
params = []
for name in names:
values = form.getlist(name)
for value in values:
params.append((name, value))
query_string = urllib.urlencode(params)
if prefix:
if query_string != "": query_string = "%s&%s" % (prefix, query_string)
elif prefix != "": query_string = prefix
if query_string:
query_string = "?%s" % query_string
return query_string
def run_cgiparams():
from optparse import OptionParser
OP = OptionParser(usage=u"\n\t%prog [options] params...", description=__doc__)
OP.add_option('--qvars', dest="qvars", default="QVARS",
help=u"Spécifier le nom du tableau qui contiendra la liste des variables correspondant aux paramètres pour lesquels une valeur est définie. Par défaut, utiliser QVARS")
OP.add_option('-q', '--query-string', action='store_true', dest='print_qs',
help=u"Reconstruire et afficher la valeur de QUERY_STRING en fonction des paramètres fournis dans la requête. Les options -i et -x permettent de sélectionner les paramètres qui y sont inclus.")
OP.add_option('-i', '--include', dest='includes', action='append',
help=u"Spécifier un paramètre à inclure pour construire QUERY_STRING. Il est possible de spécifier plusieurs paramètres en les séparant par des virgules.")
OP.add_option('-x', '--exclude', dest='excludes', action='append',
help=u"Spécifier un paramètre à exclure pour construire QUERY_STRING. Il est possible de spécifier plusieurs paramètres en les séparant par des virgules.")
OP.add_option('-p', '--prefix', dest="prefix",
help=u"Ajouter les paramètres supplémentaires spécifiés à QUERY_STRING.")
o, args = OP.parse_args()
form = cgi.FieldStorage(keep_blank_values=True)
qvars = []
if args:
for nv in args:
mo = RE_NAME_VALUE.match(nv)
@ -39,6 +86,7 @@ def run_cgiparams():
fname, defvalue = mo.group(1), mo.group(2)
if defvalue is None: defvalue = ''
vname = fname.replace('-', '_')
if vname not in qvars: qvars.append(vname)
values = form.getlist(fname)
if len(values) == 0: print_scalar(vname, defvalue)
elif len(values) == 1: print_scalar(vname, values[0])
@ -46,9 +94,14 @@ def run_cgiparams():
else:
for fname in form.keys():
vname = fname.replace('-', '_')
qvars.append(vname)
values = form.getlist(fname)
if len(values) == 1: print_scalar(vname, values[0])
else: print_array(vname, values)
print_array(o.qvars, qvars)
if o.print_qs:
qs = build_query_string(form, o.includes, o.excludes, o.prefix)
print_scalar('QUERY_STRING', qs)
if __name__ == '__main__':
run_cgiparams()