1 # -*- encoding: utf-8 -*-
3 __author__= "Łukasz Rekucki"
4 __date__ = "$2009-10-19 14:34:42$"
5 __doc__ = "Module documentation."
7 #import api.forms as forms
8 #import api.response as response
10 #from api.utils import validate_form, hglibrary
11 #from api.models import PartCache
15 #from piston.handler import BaseHandler
20 from library_handlers import *
23 from librarian import parser
29 XINCLUDE_REGEXP = r"""<(?:\w+:)?include\s+[^>]*?href=("|')wlrepo://(?P<link>[^\1]+?)\1\s*[^>]*?>"""
34 class DocumentTextHandler(BaseHandler):
35 allowed_methods = ('GET', 'POST')
37 @validate_form(forms.TextRetrieveForm, 'GET')
39 def read(self, request, form, docid, lib):
40 """Read document as raw text"""
42 revision = form.cleaned_data['revision']
43 chunk = form.cleaned_data['chunk']
44 user = form.cleaned_data['user'] or request.user.username
45 format = form.cleaned_data['format']
47 document = lib.document_for_revision(revision)
49 if document.id != docid:
50 return response.BadRequest().django_response({
51 'reason': 'name-mismatch',
52 'message': 'Provided revision is not valid for this document'
55 if document.owner != user:
56 return response.BadRequest().django_response({
57 'reason': 'user-mismatch',
58 'message': "Provided revision doesn't belong to user %s" % user
61 for error in check_user(request, user):
65 return document.data('xml')
67 xdoc = parser.WLDocument.from_string(document.data('xml'), parse_dublincore=False)
69 xchunk = xdoc.chunk(chunk)
72 return response.EntityNotFound().django_response({
73 'reason': 'no-chunk-in-document',
77 return librarian.serialize_children(xchunk, format=format)
79 except librarian.ParseError, e:
80 return response.EntityNotFound().django_response({
81 'reason': 'invalid-document-state',
85 except (EntryNotFound, RevisionNotFound), e:
86 return response.EntityNotFound().django_response({
87 'reason': 'not-found',
88 'exception': type(e), 'message': e.message
91 @validate_form(forms.TextUpdateForm, 'POST')
93 def create(self, request, form, docid, lib):
96 revision = form.cleaned_data['revision']
97 msg = form.cleaned_data['message']
98 user = form.cleaned_data['user'] or request.user.username
100 # do not allow changing not owned documents
103 if user != request.user.username:
104 return response.AccessDenied().django_response({
105 'reason': 'insufficient-priviliges',
108 current = lib.document(docid, user)
109 orig = lib.document_for_revision(revision)
112 return response.EntityConflict().django_response({
113 "reason": "out-of-date",
114 "provided_revision": orig.revision,
115 "latest_revision": current.revision })
117 if form.cleaned_data['contents']:
118 data = form.cleaned_data['contents']
120 chunks = form.cleaned_data['chunks']
121 data = current.data('xml')
125 xdoc = parser.WLDocument.from_string(data, parse_dublincore=False)
126 errors = xdoc.merge_chunks(chunks)
129 return response.EntityConflict().django_response({
130 "reason": "invalid-chunks",
131 "message": "Unable to merge following parts into the document: %s " % ",".join(errors)
134 data = xdoc.serialize()
137 # try to find any Xinclude tags
138 includes = [m.groupdict()['link'] for m in (re.finditer(\
139 XINCLUDE_REGEXP, data, flags=re.UNICODE) or []) ]
141 log.info("INCLUDES: %s", includes)
143 # TODO: provide useful routines to make this simpler
144 def xml_update_action(lib, resolve):
146 f = lib._fileopen(resolve('parts'), 'r')
147 stored_includes = json.loads(f.read())
152 if stored_includes != includes:
153 f = lib._fileopen(resolve('parts'), 'w+')
154 f.write(json.dumps(includes))
157 lib._fileadd(resolve('parts'))
159 # update the parts cache
160 PartCache.update_cache(docid, current.owner,\
161 stored_includes, includes)
163 # now that the parts are ok, write xml
164 f = lib._fileopen(resolve('xml'), 'w+')
165 f.write(data.encode('utf-8'))
169 ndoc = current.invoke_and_commit(\
170 xml_update_action, lambda d: (msg, user) )
173 # return the new revision number
174 return response.SuccessAllOk().django_response({
178 "previous_revision": current.revision,
179 "revision": ndoc.revision,
180 'timestamp': ndoc.revision.timestamp,
181 "url": reverse("doctext_view", args=[ndoc.id])
184 if ndoc: lib._rollback()
186 except RevisionNotFound, e:
187 return response.EntityNotFound(mimetype="text/plain").\
188 django_response(e.message)