+++ /dev/null
-Le fichier index.py est un exemple d'utilisation de mod_python pour
-générer automatiquement un index de répertoires et sous-répertoires
-avec liens pour télécharger les fichiers qui s'y trouvent.
-
-Pour l'utiliser il faut :
-- installer le paquet Debian libapache2-mod-python
-- ajouter les lignes suivantes dans un VirtualHost Apache :
-
- <Directory /var/www/partage>
- AddHandler mod_python .py
- PythonHandler index
- PythonDebug Off
- DirectoryIndex index.py
- </Directory>
-
-- placer le fichier index.py dans le dossier web à gérer
- (dans l'exemple fourni ici : /var/www/partage/index.py)
-
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Index automatique des dossiers et sous-dossiers et liens sur les fichiers.
-(Page de téléchargement pour les documents de la CRE en Asie-Pacifique.)
-
-Copyright : Agence universitaire de la Francophonie
-Licence : GNU General Public Licence, version 2
-Auteur : Jean Christophe André
-Date de création : 25 mars 2009
-"""
-
-import os
-import re
-import mod_python
-import urllib
-
-HTML = u"""
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <title>CRE</title>
- <style type="text/css">
-body { background: url('Bamboo2.png') #80FF80; }
-a { color: black; text-decoration: none; }
-a:hover { color: black; text-decoration: underline; }
-a:visited { color: black; text-decoration: underline; }
-li { padding: 3pt; list-style: none; font-weight: bold; font-family: sans; }
-li em { color: black; font-size: 70%%; }
-.hidden { display: none; }
-.visible { display: inline; }
- </style>
- <script type="text/javascript">
-function sw(id) {
- elt = document.getElementById(id)
- if (elt.className == 'hidden') {
- elt.className = 'visible';
- } else {
- elt.className = 'hidden';
- }
-}
- </script>
-</head>
-<body>
-%(content)s
-</body>
-</html>
-"""
-
-id_number = 0
-
-def human_size(size):
- if size < 1024: return "%s octets" % size
- size /= 1024
- if size < 1024: return "%s Kio" % size
- size /= 1024
- if size < 1024: return "%s Mio" % size
- size /= 1024
- if size < 1024: return "%s Gio" % size
- size /= 1024
- return "%s Tio" % size
-
-def my_cmp(name1, name2):
- m1 = re.match('[0-9]+', name1)
- m2 = re.match('[0-9]+', name2)
- if not m1 or not m2:
- return cmp(name1, name2)
- n1 = int(m1.group())
- n2 = int(m2.group())
- if n1 == n2:
- return cmp(name1[m1.end():], name2[m2.end():])
- return n1 - n2
-
-def my_listdir(dir):
- path = os.path.join(os.environ["PWD"], dir)
- names = os.listdir(path)
- dirs = [x for x in names if os.path.isdir(os.path.join(path, x))]
- dirs.sort(cmp=my_cmp)
- files = [x for x in names if os.path.isfile(os.path.join(path, x))]
- files.sort(cmp=my_cmp)
- return dirs, files
-
-def my_getsize(file):
- path = os.path.join(os.environ["PWD"], file)
- return os.path.getsize(path)
-
-def dir_content(root, level=0):
- global id_number
- space = u" " * level
- dirs, files = my_listdir(root)
- content = space + u"""<div id="l%s" class="%s"><ul>\n""" \
- % (id_number, level == 0 and "visible" or "hidden")
- id_number += 1
- for dir in dirs:
- content += space + u"""<li>"""
- content += u"""<a href="javascript:void(0)" onclick="sw('l%s')">%s</a>""" \
- % (id_number, dir.decode('utf-8').replace('_',' '))
- content += u"""</li>\n"""
- content += dir_content(os.path.join(root, dir), level + 1)
- if level > 0:
- for file in files:
- content += space + u"""<li>"""
- content += u"""<a href="%s">%s</a> <em>(%s)</em>""" \
- % (urllib.quote(root+'/'+file),
- file.decode('utf-8').replace('_',' '),
- human_size(my_getsize(os.path.join(root, file))) )
- content += u"""</li>\n"""
- content += space + u"""</ul></div>\n"""
- return content
-
-def handler(request):
- html = HTML % {'content': dir_content(".")}
- request.content_type = "text/html; charset=utf-8"
- request.write(html.encode('utf-8'))
- return mod_python.apache.OK
-
--- /dev/null
+Le fichier index.py est un exemple d'utilisation de mod_python pour
+générer automatiquement un index de répertoires et sous-répertoires
+avec liens pour télécharger les fichiers qui s'y trouvent.
+
+Pour l'utiliser il faut :
+- installer le paquet Debian libapache2-mod-python
+- ajouter les lignes suivantes dans un VirtualHost Apache :
+
+ <Directory /var/www/partage>
+ AddHandler mod_python .py
+ PythonHandler index
+ PythonDebug Off
+ DirectoryIndex index.py
+ </Directory>
+
+- placer le fichier index.py dans le dossier web à gérer
+ (dans l'exemple fourni ici : /var/www/partage/index.py)
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Index automatique des dossiers et sous-dossiers et liens sur les fichiers.
+(Page de téléchargement pour les documents de la CRE en Asie-Pacifique.)
+
+Copyright : Agence universitaire de la Francophonie
+Licence : GNU General Public Licence, version 2
+Auteur : Jean Christophe André
+Date de création : 25 mars 2009
+"""
+
+import os
+import re
+import mod_python
+import urllib
+
+HTML = u"""
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <title>CRE</title>
+ <style type="text/css">
+body { background: url('Bamboo2.png') #80FF80; }
+a { color: black; text-decoration: none; }
+a:hover { color: black; text-decoration: underline; }
+a:visited { color: black; text-decoration: underline; }
+li { padding: 3pt; list-style: none; font-weight: bold; font-family: sans; }
+li em { color: black; font-size: 70%%; }
+.hidden { display: none; }
+.visible { display: inline; }
+ </style>
+ <script type="text/javascript">
+function sw(id) {
+ elt = document.getElementById(id)
+ if (elt.className == 'hidden') {
+ elt.className = 'visible';
+ } else {
+ elt.className = 'hidden';
+ }
+}
+ </script>
+</head>
+<body>
+%(content)s
+</body>
+</html>
+"""
+
+id_number = 0
+
+def human_size(size):
+ if size < 1024: return "%s octets" % size
+ size /= 1024
+ if size < 1024: return "%s Kio" % size
+ size /= 1024
+ if size < 1024: return "%s Mio" % size
+ size /= 1024
+ if size < 1024: return "%s Gio" % size
+ size /= 1024
+ return "%s Tio" % size
+
+def my_cmp(name1, name2):
+ m1 = re.match('[0-9]+', name1)
+ m2 = re.match('[0-9]+', name2)
+ if not m1 or not m2:
+ return cmp(name1, name2)
+ n1 = int(m1.group())
+ n2 = int(m2.group())
+ if n1 == n2:
+ return cmp(name1[m1.end():], name2[m2.end():])
+ return n1 - n2
+
+def my_listdir(dir):
+ path = os.path.join(os.environ["PWD"], dir)
+ names = os.listdir(path)
+ dirs = [x for x in names if os.path.isdir(os.path.join(path, x))]
+ dirs.sort(cmp=my_cmp)
+ files = [x for x in names if os.path.isfile(os.path.join(path, x))]
+ files.sort(cmp=my_cmp)
+ return dirs, files
+
+def my_getsize(file):
+ path = os.path.join(os.environ["PWD"], file)
+ return os.path.getsize(path)
+
+def dir_content(root, level=0):
+ global id_number
+ space = u" " * level
+ dirs, files = my_listdir(root)
+ content = space + u"""<div id="l%s" class="%s"><ul>\n""" \
+ % (id_number, level == 0 and "visible" or "hidden")
+ id_number += 1
+ for dir in dirs:
+ content += space + u"""<li>"""
+ content += u"""<a href="javascript:void(0)" onclick="sw('l%s')">%s</a>""" \
+ % (id_number, dir.decode('utf-8').replace('_',' '))
+ content += u"""</li>\n"""
+ content += dir_content(os.path.join(root, dir), level + 1)
+ if level > 0:
+ for file in files:
+ content += space + u"""<li>"""
+ content += u"""<a href="%s">%s</a> <em>(%s)</em>""" \
+ % (urllib.quote(root+'/'+file),
+ file.decode('utf-8').replace('_',' '),
+ human_size(my_getsize(os.path.join(root, file))) )
+ content += u"""</li>\n"""
+ content += space + u"""</ul></div>\n"""
+ return content
+
+def handler(request):
+ html = HTML % {'content': dir_content(".")}
+ request.content_type = "text/html; charset=utf-8"
+ request.write(html.encode('utf-8'))
+ return mod_python.apache.OK
+
--- /dev/null
+Le fichier partage-compta.py est un exemple d'utilisation de script WSGI
+pour générer automatiquement un index de répertoires et sous-répertoires,
+avec affichage de l'espace occupé par ceux-ci et des liens pour télécharger
+les fichiers s'y trouvant ou même les dossiers en entiers (archive .tar).
+
+Le fichier partage-compta.tpl est un modèle HTML pour la page affichée.
+
+Pour l'utiliser il faut :
+- installer le paquet Debian libapache2-mod-wsgi
+- ajouter les lignes suivantes dans un VirtualHost Apache :
+
+ WSGIScriptAlias /partage/compta /srv/python/partage-compta.py
+ <Location /partage/compta>
+ Order Allow,Deny
+ Allow from all
+ </Location>
+
+- placer les fichiers partage-compta.* dans le dossier /srv/python/
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Outil de partage de fichiers.
+
+Depends: libapache2-mod-wsgi
+
+Attention : le code n'est pas encore “thread-safe”...
+"""
+import os
+import re
+import urllib
+import tarfile
+
+ROOT_PATH = '/srv/www/compta'
+PAGE_TITLE = u'Rapport financier du BAP <em>(%s)</em>'
+BACKGROUND_URL = 'Bamboo2.png'
+EXCLUDED_FILES = [ 'description.txt' ]
+INVALID_NAME = u'%s <span class="alert">(NOM INVALIDE)</span>'
+
+html_template_filename = os.path.abspath(__file__.rstrip('.py') + '.tpl')
+dir_description_filename = 'description.txt'
+
+dir_link_template = u"""%s<li class="dir"><a href="javascript:void(0)" onclick="sw('l%s')">%s</a> <em>(%s) <a href="%s">archive du dossier</a></em> %s</li>"""
+dir_description_template = u""" <em>%s</em>"""
+begin_content_template = u"""%s<div id="l%s" class="hidden"><ul>"""
+end_content_template = u"""%s</ul></div>"""
+file_link_template = u"""%s<li><a href="%s">%s</a> <em>(%s)</em></li>"""
+
+def valid_path(path):
+ if os.path.islink('.' + path):
+ return False
+ if not os.path.isdir('.' + path):
+ return False
+ return True
+
+def human_size(size):
+ if size <= 1: return "0 octet"
+ if size < 1024: return "%s octets" % size
+ size /= 1024
+ if size < 1024: return "%s Kio" % size
+ size /= 1024
+ if size < 1024: return "%s Mio" % size
+ size /= 1024
+ if size < 1024: return "%s Gio" % size
+ size /= 1024
+ return "%s Tio" % size
+
+def my_cmp(name1, name2):
+ m1 = re.match('[0-9]+', name1)
+ m2 = re.match('[0-9]+', name2)
+ if not m1 or not m2:
+ return cmp(name1, name2)
+ n1 = int(m1.group())
+ n2 = int(m2.group())
+ if n1 == n2:
+ return cmp(name1[m1.end():], name2[m2.end():])
+ if n1 < n2:
+ return -1
+ return 1
+
+def my_listdir(path):
+ path = '.' + path
+ try:
+ names = os.listdir(path)
+ except OSError:
+ return [], []
+ dirs = []
+ files = []
+ for n in names:
+ p = path + '/' + n
+ if not os.path.islink(p):
+ if os.path.isdir(p):
+ dirs.append(n)
+ if os.path.isfile(p):
+ files.append(n)
+ dirs.sort(cmp=my_cmp)
+ files.sort(cmp=my_cmp)
+ return dirs, files
+
+
+id_number = 0
+
+def dir_content(prefix, root, level=0):
+ dirs, files = my_listdir(root)
+ if not len(dirs) and not len(files):
+ return [], 0
+ space = u" " * level
+ content = []
+ file_size_total = 0
+ for d in dirs:
+ path = root.rstrip('/') + '/' + d
+ sub_dir_content, sub_dir_size = dir_content(prefix, path, level + 1)
+ file_size_total += sub_dir_size
+ if sub_dir_content:
+ global id_number
+ id_number += 1
+ name = d.replace('_',' ')
+ try:
+ name = name.decode('utf-8')
+ except UnicodeDecodeError:
+ name = INVALID_NAME % name.decode('latin-1')
+ desc_file = '.' + path + '/' + dir_description_filename
+ if os.path.isfile(desc_file):
+ desc = file(desc_file).read().strip().replace('\n',' ')
+ desc = dir_description_template % desc.decode('utf-8')
+ else:
+ desc = ''
+ archive_path = (prefix + path + '.tar').decode('utf-8')
+ archive_size = human_size(sub_dir_size)
+ content.append(dir_link_template % \
+ (space, id_number, name, archive_size, archive_path, desc))
+ content.append(begin_content_template % (space, id_number))
+ content.extend(sub_dir_content)
+ content.append(end_content_template % space)
+ for f in files:
+ path = root.rstrip('/') + '/' + f
+ file_size = os.path.getsize('.' + path)
+ file_size_total += file_size
+ if file_size > 0 and f not in EXCLUDED_FILES:
+ name = f.replace('_',' ')
+ try:
+ name = name.decode('utf-8')
+ except UnicodeDecodeError:
+ name = INVALID_NAME % name.decode('latin-1')
+ content.append( file_link_template % (space,
+ urllib.quote(prefix + path), name, human_size(file_size)) )
+ return content, file_size_total
+
+class FileBuffer():
+ def __init__(self):
+ self.reset()
+ def reset(self):
+ self._data = []
+ def write(self, data):
+ self._data.append(data)
+ def read(self):
+ return ''.join(self._data)
+
+def tar_generator(path, mode='w|', bufsize=65536):
+ buffer = FileBuffer()
+ #yield 'open()\n'
+ tar = tarfile.open(mode=mode, fileobj=buffer, bufsize=bufsize)
+ for root, dirs, files in os.walk(path):
+ for name in files:
+ tar.add(os.path.join(root, name), recursive=False)
+ #yield '+ file: %s\n' % os.path.join(root, name)
+ yield buffer.read()
+ buffer.reset()
+ tar.close()
+ #yield 'close()\n'
+ yield buffer.read()
+
+def application(environ, start_response):
+ global id_number
+ id_number = 0
+ os.chdir(ROOT_PATH)
+ if False and not environ.get('HTTP_USER'):
+ headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
+ start_response('401 Authorization Required', headers)
+ return ['Authorization Required']
+ path = environ['PATH_INFO']
+ if not valid_path(os.path.dirname(path)):
+ headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
+ start_response('404 Not Found', headers)
+ return ['Not Found']
+ if os.path.isfile('.' + path):
+ if path.endswith('.txt'):
+ mime_type = 'text/plain; charset=utf-8'
+ elif path.endswith('.pdf'):
+ mime_type = 'application/pdf'
+ else:
+ mime_type = 'application/octet-stream'
+ length = str(os.path.getsize('.' + path))
+ headers = [('Content-Type', mime_type), ('Content-Length', length), ]
+ start_response('200 OK', headers)
+ return file('.' + path)
+ if path.endswith('.tar') and os.path.isdir('.' + path[:-4]):
+ #headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
+ headers = [('Content-Type', 'application/octet-stream'), ]
+ start_response('200 OK', headers)
+ return tar_generator('.' + path[:-4])
+ content, size = dir_content(environ['SCRIPT_NAME'], environ['PATH_INFO'])
+ environ.update({
+ 'page_title': PAGE_TITLE % human_size(size),
+ 'background_url': BACKGROUND_URL,
+ 'content': '<ul>\n' + '\n'.join(content) + '\n</ul>',
+ })
+ html_template = file(html_template_filename).read().decode('utf-8')
+ content = (html_template % environ).encode('utf-8')
+ headers = [('Content-Type', 'text/html; charset=utf-8'), ]
+ start_response('200 OK', headers)
+ return [content]
+
+if __name__ == '__main__':
+ # this runs when script is started directly from commandline
+ try:
+ # create a simple WSGI server and run the application
+ from wsgiref import simple_server
+ print "Running test application - point your browser at http://localhost:8000/ ..."
+ httpd = simple_server.WSGIServer(('', 8000), simple_server.WSGIRequestHandler)
+ httpd.set_app(application)
+ httpd.serve_forever()
+ except ImportError:
+ # wsgiref not installed, just output html to stdout
+ for content in application({}, lambda status, headers: None):
+ print content
+
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <title>%(page_title)s</title>
+ <style type="text/css">
+body { background: url(%(background_url)s) lightblue; }
+h1 em { color: blue; font-size: 70%%; }
+ul { padding-left: 5pt; margin-left: 3pt; border-left: 1px dotted blue; }
+li { padding: 3pt; list-style: none; font-weight: bold; font-family: sans; font-size: 80%%; }
+li em { color: blue; font-size: 70%%; }
+a { color: black; text-decoration: none; }
+a:visited { color: black; text-decoration: none; }
+a:hover { color: black; text-decoration: underline; }
+.dir { font-size: 100%%; }
+.hidden { display: none; }
+.visible { display: inline; }
+.alert { color: red; }
+ </style>
+ <script type="text/javascript">
+function sw(id) {
+ elt = document.getElementById(id)
+ if (elt.className == 'hidden') {
+ elt.className = 'visible';
+ } else {
+ elt.className = 'hidden';
+ }
+}
+ </script>
+</head>
+<body>
+<h1>%(page_title)s</h1>
+<!-- SCRIPT_NAME: %(SCRIPT_NAME)s -->
+<!-- PATH_INFO: %(PATH_INFO)s -->
+%(content)s
+</body>
+</html>