|
a/webui.py |
|
b/webui.py |
1 |
#!/usr/bin/env python
|
1 |
from __future__ import print_function
|
2 |
#{{{ imports
|
2 |
#{{{ imports
|
3 |
import os
|
3 |
import os
|
4 |
import bottle
|
4 |
import bottle
|
5 |
import time
|
5 |
import time
|
6 |
import sys
|
6 |
import sys
|
7 |
import datetime
|
7 |
import datetime
|
8 |
import glob
|
8 |
import glob
|
9 |
import hashlib
|
9 |
import hashlib
|
10 |
import json
|
10 |
import json
|
11 |
import csv
|
11 |
import csv
|
12 |
import StringIO
|
12 |
import io
|
13 |
import ConfigParser
|
|
|
14 |
import string
|
13 |
import string
|
15 |
import shlex
|
14 |
import shlex
|
|
|
15 |
def msg(s):
|
|
|
16 |
print("%s" % s, file=sys.stderr)
|
|
|
17 |
py3k = sys.version_info >= (3, 0, 0)
|
|
|
18 |
if py3k:
|
|
|
19 |
from urllib.parse import urlencode, quote as urlquote
|
|
|
20 |
else: # 2.x
|
|
|
21 |
from urllib import urlencode, quote as urlquote
|
|
|
22 |
|
16 |
import urllib
|
23 |
import urllib
|
17 |
# import recoll and rclextract
|
24 |
# import recoll and rclextract
|
18 |
try:
|
25 |
try:
|
19 |
from recoll import recoll
|
26 |
from recoll import recoll
|
20 |
from recoll import rclextract
|
27 |
from recoll import rclextract
|
21 |
hasrclextract = True
|
28 |
hasrclextract = True
|
22 |
except:
|
29 |
except Exception as err:
|
|
|
30 |
msg("Import recoll because: %s" % err)
|
23 |
import recoll
|
31 |
import recoll
|
24 |
hasrclextract = False
|
32 |
hasrclextract = False
|
25 |
# import rclconfig system-wide or local copy
|
33 |
# Import rclconfig system-wide or local copy
|
26 |
try:
|
34 |
try:
|
27 |
from recoll import rclconfig
|
35 |
from recoll import rclconfig
|
28 |
except:
|
36 |
except:
|
29 |
import rclconfig
|
37 |
import rclconfig
|
30 |
#}}}
|
38 |
#}}}
|
|
... |
|
... |
120 |
config['csvfields'] = ' '.join(ncf)
|
128 |
config['csvfields'] = ' '.join(ncf)
|
121 |
config['fields'] = ' '.join(FIELDS)
|
129 |
config['fields'] = ' '.join(FIELDS)
|
122 |
# get mountpoints
|
130 |
# get mountpoints
|
123 |
config['mounts'] = {}
|
131 |
config['mounts'] = {}
|
124 |
for d in config['dirs']:
|
132 |
for d in config['dirs']:
|
125 |
name = 'mount_%s' % urllib.quote(d,'')
|
133 |
name = 'mount_%s' % urlquote(d,'')
|
126 |
config['mounts'][d] = select([bottle.request.get_cookie(name), 'file://%s' % d], [None, ''])
|
134 |
config['mounts'][d] = select([bottle.request.get_cookie(name), 'file://%s' % d], [None, ''])
|
127 |
|
135 |
|
128 |
# Parameters set by the admin in the recoll configuration
|
136 |
# Parameters set by the admin in the recoll configuration
|
129 |
# file. These override anything else, so read them last
|
137 |
# file. These override anything else, so read them last
|
130 |
val = rclconf.getConfParam('webui_nojsoncsv')
|
138 |
val = rclconf.getConfParam('webui_nojsoncsv')
|
|
... |
|
... |
169 |
}
|
177 |
}
|
170 |
return query
|
178 |
return query
|
171 |
#}}}
|
179 |
#}}}
|
172 |
#{{{ query_to_recoll_string
|
180 |
#{{{ query_to_recoll_string
|
173 |
def query_to_recoll_string(q):
|
181 |
def query_to_recoll_string(q):
|
|
|
182 |
if type(q['query']) == type(u''):
|
|
|
183 |
qs = q['query']
|
|
|
184 |
else:
|
174 |
qs = q['query'].decode('utf-8')
|
185 |
qs = q['query'].decode('utf-8')
|
175 |
if len(q['after']) > 0 or len(q['before']) > 0:
|
186 |
if len(q['after']) > 0 or len(q['before']) > 0:
|
176 |
qs += " date:%s/%s" % (q['after'], q['before'])
|
187 |
qs += " date:%s/%s" % (q['after'], q['before'])
|
|
|
188 |
qdir = q['dir']
|
|
|
189 |
if type(qdir) != type(u''):
|
|
|
190 |
qdir = qdir.decode('utf-8')
|
177 |
if q['dir'] != '<all>':
|
191 |
if qdir != '<all>':
|
178 |
qs += " dir:\"%s\" " % q['dir'].decode('utf-8')
|
192 |
qs += " dir:\"%s\" " % qdir
|
179 |
return qs
|
193 |
return qs
|
180 |
#}}}
|
194 |
#}}}
|
181 |
#{{{ recoll_initsearch
|
195 |
#{{{ recoll_initsearch
|
182 |
def recoll_initsearch(q):
|
196 |
def recoll_initsearch(q):
|
183 |
config = get_config()
|
197 |
config = get_config()
|
|
... |
|
... |
232 |
for f in FIELDS:
|
246 |
for f in FIELDS:
|
233 |
v = getattr(doc, f)
|
247 |
v = getattr(doc, f)
|
234 |
if v is not None:
|
248 |
if v is not None:
|
235 |
d[f] = v.encode('utf-8')
|
249 |
d[f] = v.encode('utf-8')
|
236 |
else:
|
250 |
else:
|
237 |
d[f] = ''
|
251 |
d[f] = b''
|
238 |
d['label'] = select([d['title'], d['filename'], '?'], [None, ''])
|
252 |
d['label'] = select([d['title'], d['filename'], '?'], [None, ''])
|
239 |
d['sha'] = hashlib.sha1(d['url']+d['ipath']).hexdigest()
|
253 |
d['sha'] = hashlib.sha1(d['url']+d['ipath']).hexdigest().encode('utf-8')
|
240 |
d['time'] = timestr(d['mtime'], config['timefmt'])
|
254 |
d['time'] = timestr(d['mtime'], config['timefmt']).encode('utf-8')
|
241 |
if dosnippets:
|
255 |
if dosnippets:
|
242 |
d['snippet'] = query.makedocabstract(doc, highlighter).encode('utf-8')
|
256 |
d['snippet'] = query.makedocabstract(doc, highlighter).encode('utf-8')
|
|
|
257 |
#for n,v in d.items():
|
|
|
258 |
# print("type(%s) is %s" % (n,type(v)))
|
243 |
results.append(d)
|
259 |
results.append(d)
|
244 |
tend = datetime.datetime.now()
|
260 |
tend = datetime.datetime.now()
|
245 |
return results, nres, tend - tstart
|
261 |
return results, nres, tend - tstart
|
246 |
#}}}
|
262 |
#}}}
|
247 |
#}}}
|
263 |
#}}}
|
|
... |
|
... |
349 |
query['page'] = 0
|
365 |
query['page'] = 0
|
350 |
qs = query_to_recoll_string(query)
|
366 |
qs = query_to_recoll_string(query)
|
351 |
bottle.response.headers['Content-Type'] = 'text/csv'
|
367 |
bottle.response.headers['Content-Type'] = 'text/csv'
|
352 |
bottle.response.headers['Content-Disposition'] = 'attachment; filename=recoll-%s.csv' % normalise_filename(qs)
|
368 |
bottle.response.headers['Content-Disposition'] = 'attachment; filename=recoll-%s.csv' % normalise_filename(qs)
|
353 |
res, nres, timer = recoll_search(query, False)
|
369 |
res, nres, timer = recoll_search(query, False)
|
354 |
si = StringIO.StringIO()
|
370 |
si = io.StringIO()
|
355 |
cw = csv.writer(si)
|
371 |
cw = csv.writer(si)
|
356 |
fields = config['csvfields'].split()
|
372 |
fields = config['csvfields'].split()
|
357 |
cw.writerow(fields)
|
373 |
cw.writerow(fields)
|
358 |
for doc in res:
|
374 |
for doc in res:
|
359 |
row = []
|
375 |
row = []
|
|
... |
|
... |
372 |
def set():
|
388 |
def set():
|
373 |
config = get_config()
|
389 |
config = get_config()
|
374 |
for k, v in DEFAULTS.items():
|
390 |
for k, v in DEFAULTS.items():
|
375 |
bottle.response.set_cookie(k, str(bottle.request.query.get(k)), max_age=3153600000, expires=315360000)
|
391 |
bottle.response.set_cookie(k, str(bottle.request.query.get(k)), max_age=3153600000, expires=315360000)
|
376 |
for d in config['dirs']:
|
392 |
for d in config['dirs']:
|
377 |
cookie_name = 'mount_%s' % urllib.quote(d, '')
|
393 |
cookie_name = 'mount_%s' % urlquote(d, '')
|
378 |
bottle.response.set_cookie(cookie_name, str(bottle.request.query.get('mount_%s' % d)), max_age=3153600000, expires=315360000)
|
394 |
bottle.response.set_cookie(cookie_name, str(bottle.request.query.get('mount_%s' % d)), max_age=3153600000, expires=315360000)
|
379 |
bottle.redirect('./')
|
395 |
bottle.redirect('./')
|
380 |
#}}}
|
396 |
#}}}
|
381 |
#{{{ osd
|
397 |
#{{{ osd
|
382 |
@bottle.route('/osd.xml')
|
398 |
@bottle.route('/osd.xml')
|