Ajout de la nouvelle technique de partage web (pour la comptabilité).
authorProgfou <jean-christophe.andre@auf.org>
Wed, 1 Sep 2010 11:09:46 +0000 (18:09 +0700)
committerProgfou <jean-christophe.andre@auf.org>
Wed, 1 Sep 2010 11:09:46 +0000 (18:09 +0700)
mod_python/Bamboo2.png [deleted file]
mod_python/description [deleted file]
mod_python/index.py [deleted file]
partageweb/Bamboo2.png [new file with mode: 0644]
partageweb/description [new file with mode: 0644]
partageweb/index.py [new file with mode: 0644]
partageweb2/description [new file with mode: 0644]
partageweb2/partage-compta.py [new file with mode: 0755]
partageweb2/partage-compta.tpl [new file with mode: 0644]

diff --git a/mod_python/Bamboo2.png b/mod_python/Bamboo2.png
deleted file mode 100644 (file)
index 9a03c8b..0000000
Binary files a/mod_python/Bamboo2.png and /dev/null differ
diff --git a/mod_python/description b/mod_python/description
deleted file mode 100644 (file)
index bf82d71..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-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)
-
diff --git a/mod_python/index.py b/mod_python/index.py
deleted file mode 100644 (file)
index 71b4280..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/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
-
diff --git a/partageweb/Bamboo2.png b/partageweb/Bamboo2.png
new file mode 100644 (file)
index 0000000..9a03c8b
Binary files /dev/null and b/partageweb/Bamboo2.png differ
diff --git a/partageweb/description b/partageweb/description
new file mode 100644 (file)
index 0000000..bf82d71
--- /dev/null
@@ -0,0 +1,18 @@
+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)
+
diff --git a/partageweb/index.py b/partageweb/index.py
new file mode 100644 (file)
index 0000000..71b4280
--- /dev/null
@@ -0,0 +1,117 @@
+#!/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
+
diff --git a/partageweb2/description b/partageweb2/description
new file mode 100644 (file)
index 0000000..da35b90
--- /dev/null
@@ -0,0 +1,19 @@
+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/
+
diff --git a/partageweb2/partage-compta.py b/partageweb2/partage-compta.py
new file mode 100755 (executable)
index 0000000..82e86cd
--- /dev/null
@@ -0,0 +1,208 @@
+#!/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
+
diff --git a/partageweb2/partage-compta.tpl b/partageweb2/partage-compta.tpl
new file mode 100644 (file)
index 0000000..2e02f63
--- /dev/null
@@ -0,0 +1,37 @@
+<!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>