class DocumentVersion(Version): """Silva Document version. """ meta_type = "Obsolete Document Version" grok.implements(IDocumentVersion) security = ClassSecurityInfo() manage_options = ( {'label':'Edit', 'action':'manage_main'}, ) + Version.manage_options def __init__(self, id): super(DocumentVersion, self).__init__(id) self.content = ParsedXML('content', '<doc></doc>') # display edit screen as main management screen security.declareProtected('View management screens', 'manage_main') manage_main = PageTemplateFile('www/documentVersionEdit', globals()) security.declareProtected( SilvaPermissions.AccessContentsInformation, 'fulltext') def fulltext(self): """Return the content of this object without any xml for cataloging. """ return [ self.get_content().getId(), self.get_title(), remove_source_xml(self.get_document_xml(text_only=True))] security.declareProtected( SilvaPermissions.ChangeSilvaContent, 'get_document_xml') def get_document_xml(self, text_only=False): """Generate a version of the document XML. You can restrict to only the text XML. """ stream = StringIO() if not text_only: stream.write( '<silva_document id="%s">' % self.get_content().getId()) # Write Title stream.write('<title>%s</title>' % translateCdata(self.get_title())) # Write Document self.content.documentElement.writeStream(stream) if not text_only: # Write Metadata binding = self.service_metadata.getMetadata(self) stream.write(binding.renderXML()) # End of document stream.write('</silva_document>') return stream.getvalue() security.declareProtected( SilvaPermissions.ChangeSilvaContent, 'get_document_xml_as') def get_document_xml_as(self, format='kupu', request=None): """Render the Document XML on a different format. """ transformer = EditorTransformer(editor=format) context = Context(self, request) rendered_document = transformer.to_target( sourceobj=self.get_document_xml(), context=context) result = unicode(rendered_document.asBytes('utf8'), 'utf8') result = result.replace(u'\xa0', u' ') return result security.declareProtected( SilvaPermissions.ChangeSilvaContent, 'set_document_xml_from') def set_document_xml_from(self, data, format='kupu', request=None): """Set the document xml of the version from the given data in the given format. """ transformer = EditorTransformer(editor=format) context = Context(self, request) document = transformer.to_source(targetobj=data, context=context)[0] title = document.find('title')[0].extract_text() content = document.find('doc')[0].asBytes(encoding="UTF8") self.content.manage_edit(content) self.set_title(title) notify(lifecycleevent.ObjectModifiedEvent(self))
class SilvaXMLAttribute(SimpleItem): """An attribute that contains Silva XML""" security = ClassSecurityInfo() meta_type = 'Silva XML Attribute' def __init__(self, id): self.id = id self._content = ParsedXML(id, '<doc></doc>') security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_content') def get_content(self): """need a way to retrieve xml content from untrusted code""" return self._content security.declareProtected(SilvaPermissions.AccessContentsInformation, 'toXML') def toXML(self, out): """returns contents of this field, serialized as XML""" out.write('<%s type="xml">' % self.id) self._content.documentElement.writeStream(out) out.write('</%s>' % self.id) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'render') def render(self): """return the rendered contents""" docel = self._content.documentElement service_editor = self.service_editor service_editor.setViewer('service_doc_viewer') return service_editor.renderView(docel) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'editorHTML') def editorHTML(self, editor='kupu', encoding=None): """returns the HTML for a ParsedXML field""" s = StringIO() contents = self.toXML(s) return self._transformSLVToHTML(s.getvalue(), editor, encoding) security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'saveEditorHTML') def saveEditorHTML(self, html, editor='kupu', encoding=None): """saves the HTML to a ParsedXML field""" title, xml = self._transformHTMLToSLV(html, editor, encoding) self._content.manage_edit(xml) def clearEditorCache(self): """ Clears editor cache for this version """ editor_service = self.service_editor document_element = self._content.documentElement editor_service.clearCache(document_element) def isCachable(self): """Return true if this document is cacheable. That means the document contains no dynamic elements like code, datasource or toc. """ non_cacheable_elements = ['toc', 'code',] # It should suffice to test the children of the root element only, # since currently the only non-cacheable elements are root elements # XXX Are we very sure it isn't possible to add code elements and tocs # inside tables or lists? for node in self._content.documentElement.childNodes: node_name = node.nodeName if node_name in non_cacheable_elements: return False # FIXME: how can we make this more generic as it is very # specific now..? if node_name == 'source': if not externalsource.isSourceCachable(self.aq_inner, node): return False return True def fulltext(self): """Returns the text of all text nodes as a flat string""" return self._fulltext_helper(self._content.documentElement) def _fulltext_helper(self, node): ret = [] for child in node.childNodes: if child.nodeType == child.TEXT_NODE: ret.append(child.nodeValue) elif child.nodeType == child.ELEMENT_NODE: ret.append(self._fulltext_helper(child)) return ' '.join(ret) def _transformSLVToHTML(self, string, editor='kupu', encoding=None): """transform Silva XML to HTML""" transformer = EditorTransformer(editor=editor) # we need to know what browser we are dealing with in order to know # what html to produce, unfortunately Mozilla uses different tags in # some cases (b instead of strong, i instead of em) browser = 'Mozilla' if self.REQUEST['HTTP_USER_AGENT'].find('MSIE') > -1: browser = 'IE' ctx = Context(f=StringIO(), last_version=1, url=self.aq_parent.absolute_url(), browser=browser, model=self.aq_parent) ctx.f.write(string) htmlnode = transformer.to_target(sourceobj=ctx.f.getvalue(), context=ctx) if encoding is not None: ret = htmlnode.asBytes(encoding=encoding) ret = ret.replace('\xa0', ' ') else: ret = unicode(htmlnode.asBytes('utf8'),'utf8') ret = ret.replace(u'\xa0', u' ') return ret def _transformHTMLToSLV(self, string, editor='kupu', encoding=None): """transform (messy structure-wise) HTML to Silva XML""" transformer = EditorTransformer(editor=editor) # we need to know what browser we are dealing with in order to know # what html to produce, unfortunately Mozilla uses different tags in # some cases (b instead of strong, i instead of em) browser = 'Mozilla' if self.REQUEST['HTTP_USER_AGENT'].find('MSIE') > -1: browser = 'IE' ctx = Context(url=self.aq_parent.absolute_url(), browser=browser, model=self.aq_parent, request=self.REQUEST) silvanode = transformer.to_source(targetobj=string, context=ctx)[0] title = silvanode.find('title')[0].extract_text() # unicode docnode = silvanode.find('doc')[0] content = docnode.asBytes(encoding="UTF8") # UTF-8 return title, content
class SilvaXMLAttribute(SimpleItem): """An attribute that contains Silva XML""" security = ClassSecurityInfo() meta_type = 'Silva XML Attribute' def __init__(self, id): self.id = id self._content = ParsedXML(id, '<doc></doc>') security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_content') def get_content(self): """need a way to retrieve xml content from untrusted code""" return self._content security.declareProtected(SilvaPermissions.AccessContentsInformation, 'toXML') def toXML(self, out): """returns contents of this field, serialized as XML""" out.write('<%s type="xml">' % self.id) self._content.documentElement.writeStream(out) out.write('</%s>' % self.id) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'render') def render(self): """return the rendered contents""" docel = self._content.documentElement service_editor = self.service_editor service_editor.setViewer('service_doc_viewer') return service_editor.renderView(docel) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'editorHTML') def editorHTML(self, editor='kupu', encoding=None): """returns the HTML for a ParsedXML field""" s = StringIO() contents = self.toXML(s) return self._transformSLVToHTML(s.getvalue(), editor, encoding) security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'saveEditorHTML') def saveEditorHTML(self, html, editor='kupu', encoding=None): """saves the HTML to a ParsedXML field""" title, xml = self._transformHTMLToSLV(html, editor, encoding) self._content.manage_edit(xml) def clearEditorCache(self): """ Clears editor cache for this version """ editor_service = self.service_editor document_element = self._content.documentElement editor_service.clearCache(document_element) def isCachable(self): """Return true if this document is cacheable. That means the document contains no dynamic elements like code, datasource or toc. """ non_cacheable_elements = [ 'toc', 'code', ] # It should suffice to test the children of the root element only, # since currently the only non-cacheable elements are root elements # XXX Are we very sure it isn't possible to add code elements and tocs # inside tables or lists? for node in self._content.documentElement.childNodes: node_name = node.nodeName if node_name in non_cacheable_elements: return False # FIXME: how can we make this more generic as it is very # specific now..? if node_name == 'source': if not externalsource.isSourceCachable(self.aq_inner, node): return False return True def fulltext(self): """Returns the text of all text nodes as a flat string""" return self._fulltext_helper(self._content.documentElement) def _fulltext_helper(self, node): ret = [] for child in node.childNodes: if child.nodeType == child.TEXT_NODE: ret.append(child.nodeValue) elif child.nodeType == child.ELEMENT_NODE: ret.append(self._fulltext_helper(child)) return ' '.join(ret) def _transformSLVToHTML(self, string, editor='kupu', encoding=None): """transform Silva XML to HTML""" transformer = EditorTransformer(editor=editor) # we need to know what browser we are dealing with in order to know # what html to produce, unfortunately Mozilla uses different tags in # some cases (b instead of strong, i instead of em) browser = 'Mozilla' if self.REQUEST['HTTP_USER_AGENT'].find('MSIE') > -1: browser = 'IE' ctx = Context(f=StringIO(), last_version=1, url=self.aq_parent.absolute_url(), browser=browser, model=self.aq_parent) ctx.f.write(string) htmlnode = transformer.to_target(sourceobj=ctx.f.getvalue(), context=ctx) if encoding is not None: ret = htmlnode.asBytes(encoding=encoding) ret = ret.replace('\xa0', ' ') else: ret = unicode(htmlnode.asBytes('utf8'), 'utf8') ret = ret.replace(u'\xa0', u' ') return ret def _transformHTMLToSLV(self, string, editor='kupu', encoding=None): """transform (messy structure-wise) HTML to Silva XML""" transformer = EditorTransformer(editor=editor) # we need to know what browser we are dealing with in order to know # what html to produce, unfortunately Mozilla uses different tags in # some cases (b instead of strong, i instead of em) browser = 'Mozilla' if self.REQUEST['HTTP_USER_AGENT'].find('MSIE') > -1: browser = 'IE' ctx = Context(url=self.aq_parent.absolute_url(), browser=browser, model=self.aq_parent, request=self.REQUEST) silvanode = transformer.to_source(targetobj=string, context=ctx)[0] title = silvanode.find('title')[0].extract_text() # unicode docnode = silvanode.find('doc')[0] content = docnode.asBytes(encoding="UTF8") # UTF-8 return title, content