Ajout d'un script WSGI pour l'annuaire des téléphones IP Thomson ST2030.
[progfou.git] / partageweb2 / partage-compta.py
CommitLineData
63a46810
P
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4Outil de partage de fichiers.
5
b816959a
P
6Copyright : Agence universitaire de la Francophonie — www.auf.org
7Licence : GNU General Public Licence, version 2
8Auteur : Jean Christophe André
9Date de création : 26 août 2010
10
63a46810
P
11Depends: libapache2-mod-wsgi
12
13Attention : le code n'est pas encore “thread-safe”...
14"""
15import os
16import re
17import urllib
18import tarfile
19
20ROOT_PATH = '/srv/www/compta'
21PAGE_TITLE = u'Rapport financier du BAP <em>(%s)</em>'
22BACKGROUND_URL = 'Bamboo2.png'
23EXCLUDED_FILES = [ 'description.txt' ]
24INVALID_NAME = u'%s <span class="alert">(NOM INVALIDE)</span>'
25
26html_template_filename = os.path.abspath(__file__.rstrip('.py') + '.tpl')
27dir_description_filename = 'description.txt'
28
29dir_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>"""
30dir_description_template = u""" <em>%s</em>"""
31begin_content_template = u"""%s<div id="l%s" class="hidden"><ul>"""
32end_content_template = u"""%s</ul></div>"""
33file_link_template = u"""%s<li><a href="%s">%s</a> <em>(%s)</em></li>"""
34
35def valid_path(path):
36 if os.path.islink('.' + path):
37 return False
38 if not os.path.isdir('.' + path):
39 return False
40 return True
41
42def human_size(size):
43 if size <= 1: return "0 octet"
44 if size < 1024: return "%s octets" % size
45 size /= 1024
46 if size < 1024: return "%s Kio" % size
47 size /= 1024
48 if size < 1024: return "%s Mio" % size
49 size /= 1024
50 if size < 1024: return "%s Gio" % size
51 size /= 1024
52 return "%s Tio" % size
53
54def my_cmp(name1, name2):
55 m1 = re.match('[0-9]+', name1)
56 m2 = re.match('[0-9]+', name2)
57 if not m1 or not m2:
58 return cmp(name1, name2)
59 n1 = int(m1.group())
60 n2 = int(m2.group())
61 if n1 == n2:
62 return cmp(name1[m1.end():], name2[m2.end():])
63 if n1 < n2:
64 return -1
65 return 1
66
67def my_listdir(path):
68 path = '.' + path
69 try:
70 names = os.listdir(path)
71 except OSError:
72 return [], []
73 dirs = []
74 files = []
75 for n in names:
76 p = path + '/' + n
77 if not os.path.islink(p):
78 if os.path.isdir(p):
79 dirs.append(n)
80 if os.path.isfile(p):
81 files.append(n)
82 dirs.sort(cmp=my_cmp)
83 files.sort(cmp=my_cmp)
84 return dirs, files
85
86
87id_number = 0
88
89def dir_content(prefix, root, level=0):
90 dirs, files = my_listdir(root)
91 if not len(dirs) and not len(files):
92 return [], 0
93 space = u" " * level
94 content = []
95 file_size_total = 0
96 for d in dirs:
97 path = root.rstrip('/') + '/' + d
98 sub_dir_content, sub_dir_size = dir_content(prefix, path, level + 1)
99 file_size_total += sub_dir_size
100 if sub_dir_content:
101 global id_number
102 id_number += 1
103 name = d.replace('_',' ')
104 try:
105 name = name.decode('utf-8')
106 except UnicodeDecodeError:
107 name = INVALID_NAME % name.decode('latin-1')
108 desc_file = '.' + path + '/' + dir_description_filename
109 if os.path.isfile(desc_file):
110 desc = file(desc_file).read().strip().replace('\n',' ')
111 desc = dir_description_template % desc.decode('utf-8')
112 else:
113 desc = ''
114 archive_path = (prefix + path + '.tar').decode('utf-8')
115 archive_size = human_size(sub_dir_size)
116 content.append(dir_link_template % \
117 (space, id_number, name, archive_size, archive_path, desc))
118 content.append(begin_content_template % (space, id_number))
119 content.extend(sub_dir_content)
120 content.append(end_content_template % space)
121 for f in files:
122 path = root.rstrip('/') + '/' + f
123 file_size = os.path.getsize('.' + path)
124 file_size_total += file_size
125 if file_size > 0 and f not in EXCLUDED_FILES:
126 name = f.replace('_',' ')
127 try:
128 name = name.decode('utf-8')
129 except UnicodeDecodeError:
130 name = INVALID_NAME % name.decode('latin-1')
131 content.append( file_link_template % (space,
132 urllib.quote(prefix + path), name, human_size(file_size)) )
133 return content, file_size_total
134
135class FileBuffer():
136 def __init__(self):
137 self.reset()
138 def reset(self):
139 self._data = []
140 def write(self, data):
141 self._data.append(data)
142 def read(self):
143 return ''.join(self._data)
144
145def tar_generator(path, mode='w|', bufsize=65536):
146 buffer = FileBuffer()
147 #yield 'open()\n'
148 tar = tarfile.open(mode=mode, fileobj=buffer, bufsize=bufsize)
149 for root, dirs, files in os.walk(path):
150 for name in files:
151 tar.add(os.path.join(root, name), recursive=False)
152 #yield '+ file: %s\n' % os.path.join(root, name)
153 yield buffer.read()
154 buffer.reset()
155 tar.close()
156 #yield 'close()\n'
157 yield buffer.read()
158
159def application(environ, start_response):
160 global id_number
161 id_number = 0
162 os.chdir(ROOT_PATH)
163 if False and not environ.get('HTTP_USER'):
164 headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
165 start_response('401 Authorization Required', headers)
166 return ['Authorization Required']
167 path = environ['PATH_INFO']
168 if not valid_path(os.path.dirname(path)):
169 headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
170 start_response('404 Not Found', headers)
171 return ['Not Found']
172 if os.path.isfile('.' + path):
173 if path.endswith('.txt'):
174 mime_type = 'text/plain; charset=utf-8'
175 elif path.endswith('.pdf'):
176 mime_type = 'application/pdf'
177 else:
178 mime_type = 'application/octet-stream'
179 length = str(os.path.getsize('.' + path))
180 headers = [('Content-Type', mime_type), ('Content-Length', length), ]
181 start_response('200 OK', headers)
182 return file('.' + path)
183 if path.endswith('.tar') and os.path.isdir('.' + path[:-4]):
184 #headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
185 headers = [('Content-Type', 'application/octet-stream'), ]
186 start_response('200 OK', headers)
187 return tar_generator('.' + path[:-4])
188 content, size = dir_content(environ['SCRIPT_NAME'], environ['PATH_INFO'])
189 environ.update({
190 'page_title': PAGE_TITLE % human_size(size),
191 'background_url': BACKGROUND_URL,
192 'content': '<ul>\n' + '\n'.join(content) + '\n</ul>',
193 })
194 html_template = file(html_template_filename).read().decode('utf-8')
195 content = (html_template % environ).encode('utf-8')
196 headers = [('Content-Type', 'text/html; charset=utf-8'), ]
197 start_response('200 OK', headers)
198 return [content]
199
200if __name__ == '__main__':
201 # this runs when script is started directly from commandline
202 try:
203 # create a simple WSGI server and run the application
204 from wsgiref import simple_server
205 print "Running test application - point your browser at http://localhost:8000/ ..."
206 httpd = simple_server.WSGIServer(('', 8000), simple_server.WSGIRequestHandler)
207 httpd.set_app(application)
208 httpd.serve_forever()
209 except ImportError:
210 # wsgiref not installed, just output html to stdout
211 for content in application({}, lambda status, headers: None):
212 print content
213