2 # -*- coding: utf-8 -*-
4 Outil de partage de fichiers.
6 Depends: libapache2-mod-wsgi
8 Attention : le code n'est pas encore “thread-safe”...
15 ROOT_PATH
= '/srv/www/compta'
16 PAGE_TITLE
= u
'Rapport financier du BAP <em>(%s)</em>'
17 BACKGROUND_URL
= 'Bamboo2.png'
18 EXCLUDED_FILES
= [ 'description.txt' ]
19 INVALID_NAME
= u
'%s <span class="alert">(NOM INVALIDE)</span>'
21 html_template_filename
= os
.path
.abspath(__file__
.rstrip('.py') + '.tpl')
22 dir_description_filename
= 'description.txt'
24 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>"""
25 dir_description_template
= u
""" <em>%s</em>"""
26 begin_content_template
= u
"""%s<div id="l%s" class="hidden"><ul>"""
27 end_content_template
= u
"""%s</ul></div>"""
28 file_link_template
= u
"""%s<li><a href="%s">%s</a> <em>(%s)</em></li>"""
31 if os
.path
.islink('.' + path
):
33 if not os
.path
.isdir('.' + path
):
38 if size
<= 1: return "0 octet"
39 if size
< 1024: return "%s octets" % size
41 if size
< 1024: return "%s Kio" % size
43 if size
< 1024: return "%s Mio" % size
45 if size
< 1024: return "%s Gio" % size
47 return "%s Tio" % size
49 def my_cmp(name1
, name2
):
50 m1
= re
.match('[0-9]+', name1
)
51 m2
= re
.match('[0-9]+', name2
)
53 return cmp(name1
, name2
)
57 return cmp(name1
[m1
.end():], name2
[m2
.end():])
65 names
= os
.listdir(path
)
72 if not os
.path
.islink(p
):
78 files
.sort(cmp=my_cmp
)
84 def dir_content(prefix
, root
, level
=0):
85 dirs
, files
= my_listdir(root
)
86 if not len(dirs
) and not len(files
):
92 path
= root
.rstrip('/') + '/' + d
93 sub_dir_content
, sub_dir_size
= dir_content(prefix
, path
, level
+ 1)
94 file_size_total
+= sub_dir_size
98 name
= d
.replace('_',' ')
100 name
= name
.decode('utf-8')
101 except UnicodeDecodeError:
102 name
= INVALID_NAME
% name
.decode('latin-1')
103 desc_file
= '.' + path
+ '/' + dir_description_filename
104 if os
.path
.isfile(desc_file
):
105 desc
= file(desc_file
).read().strip().replace('\n',' ')
106 desc
= dir_description_template
% desc
.decode('utf-8')
109 archive_path
= (prefix
+ path
+ '.tar').decode('utf-8')
110 archive_size
= human_size(sub_dir_size
)
111 content
.append(dir_link_template
% \
112 (space
, id_number
, name
, archive_size
, archive_path
, desc
))
113 content
.append(begin_content_template
% (space
, id_number
))
114 content
.extend(sub_dir_content
)
115 content
.append(end_content_template
% space
)
117 path
= root
.rstrip('/') + '/' + f
118 file_size
= os
.path
.getsize('.' + path
)
119 file_size_total
+= file_size
120 if file_size
> 0 and f
not in EXCLUDED_FILES
:
121 name
= f
.replace('_',' ')
123 name
= name
.decode('utf-8')
124 except UnicodeDecodeError:
125 name
= INVALID_NAME
% name
.decode('latin-1')
126 content
.append( file_link_template
% (space
,
127 urllib
.quote(prefix
+ path
), name
, human_size(file_size
)) )
128 return content
, file_size_total
135 def write(self
, data
):
136 self
._data
.append(data
)
138 return ''.join(self
._data
)
140 def tar_generator(path
, mode
='w|', bufsize
=65536):
141 buffer = FileBuffer()
143 tar
= tarfile
.open(mode
=mode
, fileobj
=buffer, bufsize
=bufsize
)
144 for root
, dirs
, files
in os
.walk(path
):
146 tar
.add(os
.path
.join(root
, name
), recursive
=False)
147 #yield '+ file: %s\n' % os.path.join(root, name)
154 def application(environ
, start_response
):
158 if False and not environ
.get('HTTP_USER'):
159 headers
= [('Content-Type', 'text/plain; charset=utf-8'), ]
160 start_response('401 Authorization Required', headers
)
161 return ['Authorization Required']
162 path
= environ
['PATH_INFO']
163 if not valid_path(os
.path
.dirname(path
)):
164 headers
= [('Content-Type', 'text/plain; charset=utf-8'), ]
165 start_response('404 Not Found', headers
)
167 if os
.path
.isfile('.' + path
):
168 if path
.endswith('.txt'):
169 mime_type
= 'text/plain; charset=utf-8'
170 elif path
.endswith('.pdf'):
171 mime_type
= 'application/pdf'
173 mime_type
= 'application/octet-stream'
174 length
= str(os
.path
.getsize('.' + path
))
175 headers
= [('Content-Type', mime_type
), ('Content-Length', length
), ]
176 start_response('200 OK', headers
)
177 return file('.' + path
)
178 if path
.endswith('.tar') and os
.path
.isdir('.' + path
[:-4]):
179 #headers = [('Content-Type', 'text/plain; charset=utf-8'), ]
180 headers
= [('Content-Type', 'application/octet-stream'), ]
181 start_response('200 OK', headers
)
182 return tar_generator('.' + path
[:-4])
183 content
, size
= dir_content(environ
['SCRIPT_NAME'], environ
['PATH_INFO'])
185 'page_title': PAGE_TITLE
% human_size(size
),
186 'background_url': BACKGROUND_URL
,
187 'content': '<ul>\n' + '\n'.join(content
) + '\n</ul>',
189 html_template
= file(html_template_filename
).read().decode('utf-8')
190 content
= (html_template
% environ
).encode('utf-8')
191 headers
= [('Content-Type', 'text/html; charset=utf-8'), ]
192 start_response('200 OK', headers
)
195 if __name__
== '__main__':
196 # this runs when script is started directly from commandline
198 # create a simple WSGI server and run the application
199 from wsgiref
import simple_server
200 print "Running test application - point your browser at http://localhost:8000/ ..."
201 httpd
= simple_server
.WSGIServer(('', 8000), simple_server
.WSGIRequestHandler
)
202 httpd
.set_app(application
)
203 httpd
.serve_forever()
205 # wsgiref not installed, just output html to stdout
206 for content
in application({}, lambda status
, headers
: None):