0001-add-support-for-file-validation.patch
wcs/fields.py | ||
---|---|---|
30 | 30 |
from qommon.strftime import strftime |
31 | 31 | |
32 | 32 |
import data_sources |
33 |
import file_validation |
|
33 | 34 | |
34 | 35 | |
35 | 36 |
class PrefillSelectionWidget(CompositeWidget): |
... | ... | |
666 | 667 |
key = 'file' |
667 | 668 |
description = N_('File Upload') |
668 | 669 |
file_type = [] |
670 |
document_type = None |
|
669 | 671 |
max_file_size = None |
670 | 672 | |
671 | 673 |
widget_class = FileWithPreviewWidget |
... | ... | |
693 | 695 |
form.add(FileSizeWidget, 'max_file_size', title=('Max file size'), |
694 | 696 |
value=self.max_file_size, |
695 | 697 |
advanced=not(self.max_file_size)) |
698 |
document_types = file_validation.get_document_types() |
|
699 |
if document_types: |
|
700 |
document_types = [(None, '---')] + document_types |
|
701 |
form.add(SingleSelectWidget, 'document_type', title=_('Document type'), |
|
702 |
value=self.document_type, options=document_types) |
|
696 | 703 | |
697 | 704 |
def get_admin_attributes(self): |
698 |
return WidgetField.get_admin_attributes(self) + ['file_type',
|
|
705 |
l = WidgetField.get_admin_attributes(self) + ['file_type',
|
|
699 | 706 |
'max_file_size'] |
707 |
if file_validation.get_document_types(): |
|
708 |
l += ['document_type'] |
|
709 |
return l |
|
700 | 710 | |
701 | 711 |
def get_view_value(self, value): |
702 | 712 |
return htmltext('<a download="%s" href="[download]?f=%s">%s</a>') % ( |
wcs/file_validation.py | ||
---|---|---|
1 |
import json |
|
2 |
import urlparse |
|
3 |
import hashlib |
|
4 |
import urllib |
|
5 | ||
6 |
from qommon.misc import http_get_page |
|
7 |
from quixote import get_publisher, get_response |
|
8 |
from quixote.html import htmltext |
|
9 | ||
10 | ||
11 |
def json_encode_helper(d, charset): |
|
12 |
'''Encode a JSON structure into local charset''' |
|
13 |
if isinstance(d, unicode): |
|
14 |
return d.encode(charset) |
|
15 |
elif isinstance(d, list): |
|
16 |
return [json_encode_helper(e, charset) for e in d] |
|
17 |
elif isinstance(d, dict): |
|
18 |
new_d = {} |
|
19 |
for k, v in d.iteritems(): |
|
20 |
new_d[json_encode_helper(k, charset)] = json_encode_helper(v, charset) |
|
21 |
return new_d |
|
22 |
else: |
|
23 |
return d |
|
24 | ||
25 | ||
26 |
def json_encode(d, charset=None): |
|
27 |
return json_encode_helper(d, charset or get_publisher().site_charset) |
|
28 | ||
29 | ||
30 |
def has_file_validation(): |
|
31 |
return get_publisher().get_site_option('fargo_url') is not None |
|
32 | ||
33 | ||
34 |
def fargo_get(path): |
|
35 |
fargo_url = get_publisher().get_site_option('fargo_url') |
|
36 |
url = urlparse.urljoin(fargo_url, path) |
|
37 |
response, status, data, auth_header = http_get_page(url) |
|
38 |
if status == 200: |
|
39 |
return json_encode(json.loads(data)) |
|
40 | ||
41 | ||
42 |
def sha256_of_upload(upload): |
|
43 |
return hashlib.sha256(upload.get_content()).hexdigest() |
|
44 | ||
45 | ||
46 |
def get_document_types(): |
|
47 |
if not has_file_validation(): |
|
48 |
return |
|
49 |
response = fargo_get('/document-types/') |
|
50 |
publisher = get_publisher() |
|
51 |
if response.get('err') == 0: |
|
52 |
result = [] |
|
53 |
for schema in response['data']: |
|
54 |
result.append( |
|
55 |
( |
|
56 |
str(schema['name']), |
|
57 |
schema['label'].encode(publisher.site_charset) |
|
58 |
) |
|
59 |
) |
|
60 |
return result |
|
61 | ||
62 |
def validation_path(filled, field, upload): |
|
63 |
user = filled.get_user() |
|
64 |
if not user: |
|
65 |
return |
|
66 |
if not user.name_identifiers: |
|
67 |
return |
|
68 |
if not field.document_type: |
|
69 |
return |
|
70 |
name_id = user.name_identifiers[0] |
|
71 |
sha_256 = sha256_of_upload(upload) |
|
72 |
document_type = field.document_type |
|
73 |
path = '%s/%s/%s/' % ( |
|
74 |
urllib.quote(name_id), |
|
75 |
urllib.quote(sha_256), |
|
76 |
urllib.quote(document_type), |
|
77 |
) |
|
78 |
return path |
|
79 | ||
80 |
def validate_upload(filled, field, upload): |
|
81 |
path = validation_path(filled, field, upload) |
|
82 |
if not path: |
|
83 |
return |
|
84 |
response = fargo_get('metadata/' + path) |
|
85 |
if response is None: |
|
86 |
return |
|
87 |
if response['err'] == 1: |
|
88 |
return False |
|
89 |
return response['data'] |
|
90 | ||
91 |
def get_document_type_label(document_type): |
|
92 |
return dict(get_document_types()).get(document_type, {}) |
|
93 | ||
94 |
def validation_link(filled, field, upload): |
|
95 |
path = validation_path(filled, field, upload) |
|
96 |
if not path: |
|
97 |
return |
|
98 |
get_response().add_css_include('../js/smoothness/jquery-ui-1.10.0.custom.min.css') |
|
99 |
get_response().add_javascript(['jquery-ui.js', 'jquery.js', 'fargo.js']) |
|
100 |
label = get_document_type_label(field.document_type) |
|
101 |
fargo_url = get_publisher().get_site_option('fargo_url') |
|
102 |
url = urlparse.urljoin(fargo_url, 'validation/' + path) |
|
103 |
url += '?next=%s' % urllib.quote(get_publisher().get_frontoffice_url() + '/reload-top') |
|
104 |
return htmltext(_('<a data-title="Validate as a %(document_type_label)s" data-width="800" data-height="500" href="%(url)s">Validate as a %(document_type_label)s</a>')) % { |
|
105 |
'url': url, |
|
106 |
'document_type_label': label, |
|
107 |
} |
wcs/forms/common.py | ||
---|---|---|
15 | 15 |
# along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 |
import sys |
18 |
import hashlib |
|
19 |
import urlparse |
|
18 | 20 | |
19 | 21 |
from quixote import get_publisher, get_request, get_response, get_session, redirect |
20 | 22 |
from quixote.directory import Directory |
21 | 23 |
from quixote.html import TemplateIO, htmltext |
22 | 24 | |
23 |
from wcs.fields import WidgetField |
|
25 |
from wcs.fields import WidgetField, FileField |
|
26 |
from wcs import file_validation |
|
24 | 27 | |
25 | 28 |
from qommon import template |
26 | 29 |
from qommon import get_logger |
... | ... | |
399 | 402 |
s = f.get_view_value(value) |
400 | 403 |
s = s.replace(str('[download]'), str('%sdownload' % form_url)) |
401 | 404 |
r += s |
405 |
if isinstance(f, FileField): |
|
406 |
s = self.file_validation_status(f, value) |
|
407 |
if s: |
|
408 |
r += htmltext(str(s)) |
|
402 | 409 |
r += htmltext('</div></div>') |
403 | 410 | |
404 | 411 | |
... | ... | |
529 | 536 |
else: |
530 | 537 |
return redirect('files/%s/' % fn) |
531 | 538 | |
539 |
def file_validation_status(self, field, value): |
|
540 |
status = file_validation.validate_upload(self.filled, field, value) |
|
541 |
if status is None: |
|
542 |
return |
|
543 |
r = TemplateIO(html=True) |
|
544 |
r += htmltext('<div class="file-validation">') |
|
545 |
if status is False: |
|
546 |
r += file_validation.validation_link(self.filled, field, value) |
|
547 |
else: |
|
548 |
r += htmltext(_('<p>%s validated by %s on %s</p>')) % ( |
|
549 |
status['label'], status['creator'], status['created']) |
|
550 |
r += htmltext('<ul>') |
|
551 |
for meta in status['metadata']: |
|
552 |
r += htmltext(_('<li>%(label)s: %(value)s</li>')) % { |
|
553 |
'label': meta['label'], |
|
554 |
'value': meta['value'] |
|
555 |
} |
|
556 |
r += htmltext('</ul>') |
|
557 |
r += htmltext('</div>') |
|
558 |
return str(r) |
|
559 | ||
532 | 560 |
def _q_lookup(self, component): |
533 | 561 |
if component == 'files': |
534 | 562 |
self.check_receiver() |
wcs/qommon/static/js/fargo.js | ||
---|---|---|
1 | ||
2 |
$(function() { |
|
3 |
var iframe = $('<iframe frameborder="0" marginwidth="0" marginheight="0" allowfullscreen></iframe>'); |
|
4 |
var dialog = $("<div></div>").append(iframe).appendTo("body").dialog({ |
|
5 |
autoOpen: false, |
|
6 |
modal: true, |
|
7 |
resizable: false, |
|
8 |
width: "auto", |
|
9 |
height: "auto", |
|
10 |
close: function () { |
|
11 |
iframe.attr("src", ""); |
|
12 |
} |
|
13 |
}); |
|
14 |
$('.file-validation a').click(function (e) { |
|
15 |
e.preventDefault(); |
|
16 |
var src = $(e.target).attr('href'); |
|
17 |
var title = $(e.target).data("title"); |
|
18 |
var width = $(e.target).data("width"); |
|
19 |
var height = $(e.target).data("height"); |
|
20 |
iframe.attr({ |
|
21 |
width: parseInt(width), |
|
22 |
height: parseInt(height), |
|
23 |
src: src |
|
24 |
}); |
|
25 |
dialog.dialog("option", "title", title); |
|
26 |
dialog.dialog("open"); |
|
27 |
}); |
|
28 |
$('p.use-file-from-fargo span').click(function(e) { |
|
29 |
e.preventDefault(); |
|
30 |
var base_widget = $(this).parents('.file-upload-widget'); |
|
31 |
document.fargo_set_token = function (token, title) { |
|
32 |
if (token) { |
|
33 |
$(base_widget).find('.filename').text(title); |
|
34 |
$(base_widget).find('.fileinfo').show(); |
|
35 |
$(base_widget).find('input[type=hidden]').val(token); |
|
36 |
$(base_widget).find('input[type=file]').hide(); |
|
37 |
} |
|
38 |
document.fargo_close_dialog(); |
|
39 |
} |
|
40 |
document.fargo_close_dialog = function () { |
|
41 |
document.fargo_set_token = undefined; |
|
42 |
dialog.dialog('close'); |
|
43 |
} |
|
44 |
var src = $(this).data('src'); |
|
45 |
var title = $(this).data("title"); |
|
46 |
var width = $(this).data("width"); |
|
47 |
var height = $(this).data("height"); |
|
48 |
iframe.attr({ |
|
49 |
width: parseInt(width), |
|
50 |
height: parseInt(height), |
|
51 |
src: src |
|
52 |
}); |
|
53 |
dialog.dialog("option", "title", title); |
|
54 |
dialog.dialog("open"); |
|
55 |
}); |
|
56 |
}); |
wcs/root.py | ||
---|---|---|
192 | 192 |
_q_exports = ['admin', 'backoffice', 'forms', 'login', 'logout', 'saml', |
193 | 193 |
'ident', 'register', 'afterjobs', 'themes', 'myspace', 'user', 'roles', |
194 | 194 |
'pages', ('tmp-upload', 'tmp_upload'), 'api', '__version__', |
195 |
'tryauth', 'auth', 'preview'] |
|
195 |
'tryauth', 'auth', 'preview', ('reload-top', 'reload_top')]
|
|
196 | 196 | |
197 | 197 |
api = ApiDirectory() |
198 | 198 |
themes = template.ThemesDirectory() |
... | ... | |
308 | 308 |
# or a form ? |
309 | 309 |
return forms.root.RootDirectory()._q_lookup(component) |
310 | 310 | |
311 |
def reload_top(self): |
|
312 |
r = TemplateIO(html=True) |
|
313 |
r += htmltext('<script>window.top.document.location.reload();</script>') |
|
314 |
return r.getvalue() |
|
315 | ||
311 | 316 |
admin = None |
312 | 317 |
backoffice = None |
313 | 318 | |
314 |
- |