Commit de2748e0 authored by Andreas Jung's avatar Andreas Jung

- cleaned up the code for uploading new content

- hopefully fixed all encoding problems
- other fixes
parent 17cd8a6e
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
# #
############################################################################## ##############################################################################
""" Zope Page Template module (wrapper for the Zope 3 ZPT implementation) """ """ Zope Page Template module (wrapper for the Zope 3 ZPT implementation) """
__version__='$Revision: 1.48 $'[11:-2] __version__='$Revision: 1.48 $'[11:-2]
import re
from urllib import quote from urllib import quote
import os, AccessControl, Acquisition import os, AccessControl, Acquisition
from Globals import ImageFile, package_home, InitializeClass from Globals import ImageFile, package_home, InitializeClass
...@@ -43,6 +43,9 @@ from webdav.WriteLockInterface import WriteLockInterface ...@@ -43,6 +43,9 @@ from webdav.WriteLockInterface import WriteLockInterface
from zope.pagetemplate.pagetemplate import PageTemplate from zope.pagetemplate.pagetemplate import PageTemplate
#from zope.pagetemplate.pagetemplatefile import PageTemplateFile #from zope.pagetemplate.pagetemplatefile import PageTemplateFile
# regular expression to extract the encoding from the XML preamble
encoding_reg= re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M)
class Src(Acquisition.Explicit): class Src(Acquisition.Explicit):
""" I am scary code """ """ I am scary code """
...@@ -58,6 +61,16 @@ class Src(Acquisition.Explicit): ...@@ -58,6 +61,16 @@ class Src(Acquisition.Explicit):
return self.document_src(REQUEST) return self.document_src(REQUEST)
def sniffEncoding(text, default_encoding='utf-8'):
""" try to determine the encoding from html or xml """
if text.startswith('<?xml'):
mo = encoding_reg.search(text)
if mo:
return mo.group(1)
return default_encoding
_default_content_fn = os.path.join(package_home(globals()), 'pt', 'default.html')
class ZPT(Script, PageTemplate, Historical, Cacheable, class ZPT(Script, PageTemplate, Historical, Cacheable,
...@@ -67,14 +80,11 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -67,14 +80,11 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
__implements__ = (WriteLockInterface,) __implements__ = (WriteLockInterface,)
meta_type = 'ZPT' meta_type = 'ZPT'
management_page_charset = 'utf-8'
func_defaults = None func_defaults = None
func_code = FuncCode((), 0) func_code = FuncCode((), 0)
_default_bindings = {'name_subpath': 'traverse_subpath'} _default_bindings = {'name_subpath': 'traverse_subpath'}
_default_content_fn = os.path.join(package_home(globals()),
'pt', 'default.html')
manage_options = ( manage_options = (
{'label':'Edit', 'action':'pt_editForm', {'label':'Edit', 'action':'pt_editForm',
...@@ -96,34 +106,47 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -96,34 +106,47 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
security.declareProtected(view, '__call__') security.declareProtected(view, '__call__')
def __init__(self, id, text=None, content_type=None, encoding='utf-8'): def __init__(self, id, text=None, content_type=None, encoding='utf-8'):
self.id = str(id) self.id = id
self.ZBindings_edit(self._default_bindings) self.ZBindings_edit(self._default_bindings)
if text is None:
text = open(self._default_content_fn).read()
self.pt_edit(text, content_type, encoding) self.pt_edit(text, content_type, encoding)
def _setPropValue(self, id, value): security.declareProtected(change_page_templates, 'pt_encoding')
PropertyManager._setPropValue(self, id, value) def pt_encoding(self):
self.ZCacheable_invalidate() encoding = sniffEncoding(self.read())
return encoding
# Use the encoding of the document as encoding for the ZMI to
# avoid any kind of encoding troubles
from ComputedAttribute import ComputedAttribute
management_page_charset = ComputedAttribute(pt_encoding, 1)
security.declareProtected(change_page_templates, 'pt_edit') security.declareProtected(change_page_templates, 'pt_edit')
def pt_edit(self, text, content_type, encoding='utf-8'): def pt_edit(self, text, content_type, encoding='utf-8'):
text = text.strip()
# if content_type == 'text/html':
# if not text.startswith('<?xml'):
# # not XHTML -> convert it to unicode
# text = unicode(text, encoding)
if not isinstance(text, unicode): if not isinstance(text, unicode):
text = unicode(text, encoding, 'strict') text = unicode(text, encoding)
assert isinstance(text, unicode)
print content_type, type(text),repr(text)
self.ZCacheable_invalidate() self.ZCacheable_invalidate()
PageTemplate.pt_edit(self, text, content_type) PageTemplate.pt_edit(self, text, content_type)
security.declareProtected(change_page_templates, 'pt_editAction') security.declareProtected(change_page_templates, 'pt_editAction')
def pt_editAction(self, REQUEST, title, text, content_type, expand): def pt_editAction(self, REQUEST, title, text, content_type, encoding, expand):
"""Change the title and document.""" """Change the title and document."""
if self.wl_isLocked(): if self.wl_isLocked():
raise ResourceLockedError("File is locked via WebDAV") raise ResourceLockedError("File is locked via WebDAV")
self.expand=expand
self.pt_setTitle(title) self.expand = expand
self.pt_edit(text, content_type) self.pt_setTitle(title, encoding)
self.pt_edit(text, content_type, encoding)
REQUEST.set('text', self.read()) # May not equal 'text'! REQUEST.set('text', self.read()) # May not equal 'text'!
REQUEST.set('title', self.title) REQUEST.set('title', self.title)
message = "Saved changes." message = "Saved changes."
...@@ -135,35 +158,40 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -135,35 +158,40 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
security.declareProtected(change_page_templates, 'pt_setTitle') security.declareProtected(change_page_templates, 'pt_setTitle')
def pt_setTitle(self, title, encoding='utf-8'): def pt_setTitle(self, title, encoding='utf-8'):
if not isinstance(title, unicode): if not isinstance(title, unicode):
title = unicode(title, encoding) title = unicode(title, encoding)
self._setPropValue('title', title) self._setPropValue('title', title)
def _setPropValue(self, id, value):
""" set a property and invalidate the cache """
PropertyManager._setPropValue(self, id, value)
self.ZCacheable_invalidate()
security.declareProtected(change_page_templates, 'pt_upload') security.declareProtected(change_page_templates, 'pt_upload')
def pt_upload(self, REQUEST, file='', charset=None): def pt_upload(self, REQUEST, file='', encoding='utf-8'):
"""Replace the document with the text in file.""" """Replace the document with the text in file."""
if self.wl_isLocked(): if self.wl_isLocked():
raise ResourceLockedError("File is locked via WebDAV") raise ResourceLockedError("File is locked via WebDAV")
if isinstance(file, str):
filename = None filename = None
if not isinstance(file, str): text = file
if not file: raise ValueError('File not specified') else:
if not file:
raise ValueError('File not specified')
filename = file.filename filename = file.filename
file = file.read() text = file.read()
ct, dummy = guess_content_type(filename, file) content_type, dummy = guess_content_type(filename, text)
if not ct in ('text/html', 'text/xml'): if not content_type in ('text/html', 'text/xml'):
raise ValueError('Unsupported mimetype: %s' % ct) raise ValueError('Unsupported mimetype: %s' % content_type)
if not isinstance(file, unicode): encoding = sniffEncoding(text, encoding)
if not charset: self.pt_edit(text, content_type, encoding)
raise ValueError('No encoding specified for non-unicode content') return self.pt_editForm(manage_tabs_message='Saved changes')
file = unicode(file, charset)
self.pt_edit(file, ct)
message = 'Saved changes.'
return self.pt_editForm(manage_tabs_message=message)
security.declareProtected(change_page_templates, 'pt_changePrefs') security.declareProtected(change_page_templates, 'pt_changePrefs')
def pt_changePrefs(self, REQUEST, height=None, width=None, def pt_changePrefs(self, REQUEST, height=None, width=None,
...@@ -199,7 +227,7 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -199,7 +227,7 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
# self, rev1, rev2, REQUEST, # self, rev1, rev2, REQUEST,
# historyComparisonResults=html_diff(rev1._text, rev2._text) ) # historyComparisonResults=html_diff(rev1._text, rev2._text) )
def pt_getContext(self, **kw): def pt_getContext(self, *args, **kw):
root = self.getPhysicalRoot() root = self.getPhysicalRoot()
context = self._getContext() context = self._getContext()
c = {'template': self, c = {'template': self,
...@@ -214,15 +242,9 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -214,15 +242,9 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
} }
return c return c
# security.declareProtected(change_page_templates, 'write')
# def write(self, text):
# PageTemplate.write(self, text)
security.declareProtected(view_management_screens, 'manage_main', 'read', security.declareProtected(view_management_screens, 'manage_main', 'read',
'ZScriptHTML_tryForm') 'ZScriptHTML_tryForm')
def _exec(self, bound_names, args, kw): def _exec(self, bound_names, args, kw):
"""Call a Page Template""" """Call a Page Template"""
if not kw.has_key('args'): if not kw.has_key('args'):
...@@ -256,7 +278,6 @@ class ZPT(Script, PageTemplate, Historical, Cacheable, ...@@ -256,7 +278,6 @@ class ZPT(Script, PageTemplate, Historical, Cacheable,
try: try:
# XXX: check the parameters for pt_render()! (aj) # XXX: check the parameters for pt_render()! (aj)
result = self.pt_render(self.pt_getContext()) result = self.pt_render(self.pt_getContext())
assert isinstance(result, unicode)
# result = self.pt_render(extra_context=bound_names) # result = self.pt_render(extra_context=bound_names)
if keyset is not None: if keyset is not None:
...@@ -375,41 +396,31 @@ manage_addZPTForm.__name__ = 'manage_addZPTForm' ...@@ -375,41 +396,31 @@ manage_addZPTForm.__name__ = 'manage_addZPTForm'
#manage_addZPTForm.__name__ = 'manage_addZPTForm' #manage_addZPTForm.__name__ = 'manage_addZPTForm'
def manage_addZPT(self, id, title=None, text=None, def manage_addZPT(self, id, title='', file=None, encoding='utf-8', submit=None, RESPONSE=None):
REQUEST=None, submit=None):
"Add a Page Template with optional file content." "Add a Page Template with optional file content."
id = str(id) if file:
if REQUEST is None: filename = file.filename
self._setObject(id, ZPT(id, text)) text = file.read()
ob = getattr(self, id) encoding = sniffEncoding(text)
if title: content_type, dummy = guess_content_type(filename, text)
ob.pt_setTitle(title)
return ob
else:
file = REQUEST.form.get('file')
headers = getattr(file, 'headers', None)
if headers is None or not file.filename:
zpt = ZPT(id, text) # collector 596
else: else:
zpt = ZPT(id, file, headers.get('content_type')) text = open(_default_content_fn).read()
encoding = 'utf-8'
content_type = 'text/html'
zpt = ZPT(id, text, content_type, encoding)
zpt.pt_setTitle(title, encoding)
self._setObject(id, zpt) self._setObject(id, zpt)
zpt = getattr(self, id)
# collector 596 if RESPONSE:
if title:
ob = getattr(self, id)
ob.pt_setTitle(title)
try:
u = self.DestinationURL()
except AttributeError:
u = REQUEST['URL1']
if submit == " Add and Edit ": if submit == " Add and Edit ":
u = "%s/%s" % (u, quote(id)) RESPONSE.redirect(zpt.absolute_url() + '/manage_main')
REQUEST.RESPONSE.redirect(u+'/manage_main') else:
return '' RESPONSE.redirect(self.absolute_url() + '/manage_main')
else:
return zpt
from Products.PageTemplates import misc_ from Products.PageTemplates import misc_
misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals()) misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals())
......
...@@ -33,6 +33,17 @@ button. ...@@ -33,6 +33,17 @@ button.
<input type="file" name="file" size="25" value="" /> <input type="file" name="file" size="25" value="" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Encoding
</div>
</td>
<td align="left" valign="top">
<input type="text" name="encoding" size="25" value="utf-8" />
<em>(only used for non-XML and non-HTML content)</em>
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
</td> </td>
......
...@@ -18,30 +18,29 @@ ...@@ -18,30 +18,29 @@
tal:attributes="value request/title | context/title" /> tal:attributes="value request/title | context/title" />
</td> </td>
<td align="left" valign="middle"> <td align="left" valign="middle">
<div class="form-optional"> <div class="form-label"> Last Modified </div>
Content-Type
</div>
</td> </td>
<td align="left" valign="middle"> <td align="left" valign="middle">
<input type="text" name="content_type" size="14" <div class="form-text"
tal:attributes="value request/content_type | context/content_type" /> tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
</div>
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="left" valign="middle"> <td align="left" valign="middle">
<div class="form-label"> <div class="form-label">
Last Modified Content-Type
</div> </div>
</td> </td>
<td align="left" valign="middle"> <td align="left" valign="middle">
<div class="form-text" <select name="content_type" size="1" tal:define="ct context/content_type">
tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000 <option value="text/html" tal:attributes="SELECTED python: ct == 'text/html'">text/html</option>
</div> <option value="text/xml" tal:attributes="SELECTED python: ct == 'text/xml'">text/xml</option>
</select>
</td> </td>
<td align="left" valign="top" colspan=2> <td align="left" valign="top" colspan=2>
<a href="source.html" tal:condition="context/html">Browse HTML source</a> <a href="source.html" tal:condition="context/html">Browse HTML source</a>
<a href="source.xml" tal:condition="not:context/html">Browse XML source</a> <a href="source.xml" tal:condition="not:context/html">Browse XML source</a>
<br> <br>
<input type="hidden" name="expand:int:default" value="0"> <input type="hidden" name="expand:int:default" value="0">
<input type="checkbox" value="1" name="expand:int" <input type="checkbox" value="1" name="expand:int"
...@@ -50,13 +49,21 @@ ...@@ -50,13 +49,21 @@
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="middle" class="form-label">Encoding</td>
<td>
<input type="text" readonly name="encoding" tal:attributes="value context/pt_encoding"/>
</td>
</tr>
<!-- XXX: check if 'None' is a proper argument for 'namespace' --> <!-- XXX: check if 'None' is a proper argument for 'namespace' -->
<tr tal:define="errors python: context.pt_errors(None)" tal:condition="errors"> <tr tal:define="errors python: context.pt_errors(None)" tal:condition="errors">
<tal:block define="global body python:context.document_src({'raw':1})"/> <tal:block define="global body python:context.document_src({'raw':1})"/>
<td align="left" valign="middle" class="form-label">Errors</td> <td align="left" valign="middle" class="form-label">Errors</td>
<td align="left" valign="middle" style="background-color: #FFDDDD" <td align="left" valign="middle" style="background-color: #FFDDDD"
colspan="3"> colspan="3">
<pre tal:content="python:modules['string'].join(errors, '\n')">errors</pre> <pre tal:content="python: '\n'.join(errors)">errors</pre>
</td> </td>
</tr> </tr>
...@@ -64,10 +71,12 @@ ...@@ -64,10 +71,12 @@
<td align="left" valign="middle" class="form-label">Warnings</td> <td align="left" valign="middle" class="form-label">Warnings</td>
<td align="left" valign="middle" style="background-color: #FFEEDD" <td align="left" valign="middle" style="background-color: #FFEEDD"
colspan="3"> colspan="3">
<pre tal:content="python:modules['string'].join(warnings, '\n')">errors</pre> <pre tal:content="python: '\n'.join(warnings)">errors</pre>
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="left" valign="top" colspan="4" <td align="left" valign="top" colspan="4"
tal:define="width request/dtpref_cols | string:100%; tal:define="width request/dtpref_cols | string:100%;
...@@ -120,7 +129,7 @@ to view or download the current text. ...@@ -120,7 +129,7 @@ to view or download the current text.
</div> </div>
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top">
<input type="file" name="file" size="25" value=""> <input type="file" name="file" size="40" value="">
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -129,8 +138,11 @@ to view or download the current text. ...@@ -129,8 +138,11 @@ to view or download the current text.
Encoding &nbsp; Encoding &nbsp;
</div> </div>
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top" colspan="2">
<input name="charset" value="utf-8"/> <input name="encoding" value="utf-8"/>
</td>
<td align="left" valign="top" colspan="1">
<em>(only used for non-XML and non-XHTML content)</em>
</td> </td>
</tr> </tr>
<tr> <tr>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment