115 lines
4.8 KiB
Python
115 lines
4.8 KiB
Python
|
#!/usr/bin/env python
|
||
|
# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||
|
|
||
|
u"""Ce script est prévu pour être utilisé dans un script CGI.
|
||
|
Il enregistre les fichiers uploadés dans le répertoire spécifié, et éventuellement lance une commande avec comme argument les fichiers enregistrés.
|
||
|
"""
|
||
|
|
||
|
import sys, os, types, cgi, tempfile
|
||
|
from os import path
|
||
|
|
||
|
cgitb = None # marqueur pour savoir si le module cgitb a été importé
|
||
|
#import cgitb; cgitb.enable()
|
||
|
|
||
|
class FileManager(object):
|
||
|
def __init__(self, destdir=None, parse_env=True):
|
||
|
if destdir is None: destdir = '/tmp'
|
||
|
self.fileinfos = []
|
||
|
self.count = 0
|
||
|
self.destdir = destdir
|
||
|
if parse_env: self.parse_env()
|
||
|
|
||
|
def parse_env(self):
|
||
|
class FieldStorage(cgi.FieldStorage):
|
||
|
def make_file(self, binary=None):
|
||
|
return self.fm._new_file(self)
|
||
|
FieldStorage.fm = self
|
||
|
self.form = FieldStorage()
|
||
|
|
||
|
def _new_file(self, form):
|
||
|
fp = path.join(self.destdir, 'upload%i' % self.count)
|
||
|
outf = open(fp, 'w+b')
|
||
|
self.count += 1
|
||
|
self.fileinfos.append((form.name, form.filename, fp, form.type))
|
||
|
return outf
|
||
|
|
||
|
def write_csv(self, outf):
|
||
|
close = False
|
||
|
if type(outf) is types.StringType:
|
||
|
outf = open(outf, 'w+b')
|
||
|
close = True
|
||
|
try:
|
||
|
outf.write("name,value,file,type\n")
|
||
|
for fi in self.fileinfos:
|
||
|
outf.write("%s,%s,%s,%s\n" % fi)
|
||
|
finally:
|
||
|
if close: outf.close()
|
||
|
|
||
|
# Analyser les options
|
||
|
from optparse import OptionParser
|
||
|
parser = OptionParser(usage=u"\n\t%prog [options]\n\t%prog [options] -c command [args]", description=__doc__)
|
||
|
parser.add_option('-d', '--destdir', dest='destdir',
|
||
|
help=u"Spécifier le répertoire de destination des fichiers uploadés. Ce répertoire est créé si nécessaire.")
|
||
|
parser.add_option('-p', '--printcsv', action='store_true', dest='printcsv',
|
||
|
help=u"Afficher la liste des fichiers uploadés au format CSV. Chaque ligne est de la forme 'name,value,file,type' où name est le nom du champ dans le formulaire http, value le nom du fichier tel qu'il a été fourni par le client, file le chemin complet vers le fichier uploadé, et type le type mime du contenu.")
|
||
|
parser.add_option('-c', '--cmd', action='store_true', dest='cmd',
|
||
|
help=u"Lancer une commande après avoir enregistré les fichiers. Implique --remove")
|
||
|
parser.add_option('-G', '--infos', action='store_const', const='infos', dest='argtype',
|
||
|
help=u"La commande est lancée avec 4 arguments pour chaque fichier uploadé. Les arguments sont fournis dans l'ordre donné par l'option -p. C'est l'option par défaut.")
|
||
|
parser.add_option('-F', '--files', action='store_const', const='files', dest='argtype',
|
||
|
help=u"La commande est lancée avec en argument chaque fichier uploadé, correspondant à la colonne file de l'option -p")
|
||
|
parser.add_option('-C', '--csv', action='store_const', const='csv', dest='argtype',
|
||
|
help=u"La commande est lancée avec en argument un fichier au format CSV qui liste les fichiers uploadés. Cf l'option -p pour le format de ce fichier.")
|
||
|
parser.set_defaults(argtype='infos')
|
||
|
parser.add_option('--remove', action='store_true', dest='clear',
|
||
|
help=u"Supprimer les fichiers uploadés.")
|
||
|
parser.add_option('-k', '--keep', action='store_false', dest='clear',
|
||
|
help=u"Ne pas supprimer les fichiers uploadés. Utiliser cette option avec -c pour garder les fichiers uploadés.")
|
||
|
parser.add_option('--devel', action='store_true', dest='devel',
|
||
|
help=u"Activer le mode développement: le module cgitb est chargé et activé.")
|
||
|
o, args = parser.parse_args()
|
||
|
|
||
|
if o.devel and cgitb is None:
|
||
|
import cgitb; cgitb.enable()
|
||
|
|
||
|
# Créer destdir le cas échéant
|
||
|
if o.destdir is not None and not path.isdir(o.destdir):
|
||
|
os.makedirs(o.destdir)
|
||
|
|
||
|
# Si aucune commande n'est spécifiée, afficher la liste des fichiers au format CSV
|
||
|
if o.printcsv is None and o.cmd is None:
|
||
|
o.printcsv = True
|
||
|
|
||
|
# Avec -c, par défaut supprimer les fichiers
|
||
|
if o.cmd and o.clear is None:
|
||
|
o.clear = True
|
||
|
|
||
|
fm = FileManager(o.destdir)
|
||
|
|
||
|
if o.printcsv:
|
||
|
fm.write_csv(sys.stdout)
|
||
|
|
||
|
if o.cmd:
|
||
|
tmpfile = None
|
||
|
if o.argtype == 'infos':
|
||
|
for fi in fm.fileinfos:
|
||
|
args.extend(fi)
|
||
|
elif o.argtype == 'files':
|
||
|
args.extend(map(lambda fi: fi[2], fm.fileinfos))
|
||
|
elif o.argtype == 'csv':
|
||
|
fd, tmpfile = tempfile.mkstemp()
|
||
|
os.close(fd)
|
||
|
fm.write_csv(tmpfile)
|
||
|
args.append(tmpfile)
|
||
|
|
||
|
os.spawnvp(os.P_WAIT, args[0], args)
|
||
|
|
||
|
if tmpfile is not None:
|
||
|
try: os.remove(tmpfile)
|
||
|
except: pass
|
||
|
|
||
|
if o.clear:
|
||
|
for fi in fm.fileinfos:
|
||
|
try: os.remove(fi[0])
|
||
|
except: pass
|