--- a/server/migractions.py Mon Sep 07 13:53:12 2009 +0200
+++ b/server/migractions.py Mon Sep 07 20:23:40 2009 +0200
@@ -166,14 +166,20 @@
% (self.config.appid, backupfile)):
return
# unpack backup
- bkup = tarfile.open(backupfile, 'r|gz')
- for name in bkup.getnames():
- if name[0] in '/.':
- raise Exception('Security check failed, path starts with "/" or "."')
- bkup.close() # XXX seek error if not close+open !?!
- bkup = tarfile.open(backupfile, 'r|gz')
tmpdir = tempfile.mkdtemp()
- bkup.extractall(path=tmpdir)
+ try:
+ bkup = tarfile.open(backupfile, 'r|gz')
+ except tarfile.ReadError:
+ # assume restoring old backup
+ shutil.copy(backupfile, osp.join(tmpdir, 'system'))
+ else:
+ for name in bkup.getnames():
+ if name[0] in '/.':
+ raise Exception('Security check failed, path starts with "/" or "."')
+ bkup.close() # XXX seek error if not close+open !?!
+ bkup = tarfile.open(backupfile, 'r|gz')
+ bkup.extractall(path=tmpdir)
+ bkup.close()
self.config.open_connections_pools = False
repo = self.repo_connect()
@@ -186,7 +192,6 @@
print '-> error trying to restore [%s]' % exc
if not self.confirm('Continue anyway?', default='n'):
raise SystemExit(1)
- bkup.close()
shutil.rmtree(tmpdir)
# call hooks
repo.open_connections_pools()
--- a/server/session.py Mon Sep 07 13:53:12 2009 +0200
+++ b/server/session.py Mon Sep 07 20:23:40 2009 +0200
@@ -129,8 +129,11 @@
if row[0] == targeteid:
break
else:
- raise Exception('cache inconsistency for %s %s %s %s' %
- (eid, rtype, role, targeteid))
+ # this may occurs if the cache has been filed by a hook
+ # after the database update
+ self.debug('cache inconsistency for %s %s %s %s', eid, rtype,
+ role, targeteid)
+ return
del rset.rows[idx]
if isinstance(rset.description, list): # else description not set
del rset.description[idx]
--- a/sobjects/notification.py Mon Sep 07 13:53:12 2009 +0200
+++ b/sobjects/notification.py Mon Sep 07 20:23:40 2009 +0200
@@ -21,7 +21,7 @@
from cubicweb.server.hookhelper import SendMailOp
from cubicweb.server.hooksmanager import Hook
-parse_message_id = deprecated('parse_message_id is now defined in cubicweb.common.mail')
+parse_message_id = deprecated('parse_message_id is now defined in cubicweb.common.mail')(parse_message_id)
class RecipientsFinder(Component):
--- a/utils.py Mon Sep 07 13:53:12 2009 +0200
+++ b/utils.py Mon Sep 07 20:23:40 2009 +0200
@@ -7,6 +7,8 @@
"""
__docformat__ = "restructuredtext en"
+from logilab.mtconverter import xml_escape
+
import locale
from md5 import md5
from datetime import datetime, timedelta, date
@@ -262,17 +264,18 @@
# 2/ css files
for cssfile, media in self.cssfiles:
w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
- (media, cssfile))
+ (media, xml_escape(cssfile)))
# 3/ ie css if necessary
if self.ie_cssfiles:
w(u'<!--[if lt IE 8]>\n')
for cssfile, media in self.ie_cssfiles:
w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
- (media, cssfile))
+ (media, xml_escape(cssfile)))
w(u'<![endif]--> \n')
# 4/ js files
for jsfile in self.jsfiles:
- w(u'<script type="text/javascript" src="%s"></script>\n' % jsfile)
+ w(u'<script type="text/javascript" src="%s"></script>\n' %
+ xml_escape(jsfile))
# 5/ post inlined scripts (i.e. scripts depending on other JS files)
if self.post_inlined_scripts:
w(u'<script type="text/javascript">\n')
@@ -305,7 +308,8 @@
self.htmltag = u'<html xmlns="http://www.w3.org/1999/xhtml" ' \
'xmlns:cubicweb="http://www.logilab.org/2008/cubicweb" ' \
'xml:lang="%s" lang="%s">' % (req.lang, req.lang)
-
+ # keep main_stream's reference on req for easier text/html demoting
+ req.main_stream = self
def write(self, data):
"""StringIO interface: this method will be assigned to self.w
--- a/web/data/cubicweb.ajax.js Mon Sep 07 13:53:12 2009 +0200
+++ b/web/data/cubicweb.ajax.js Mon Sep 07 20:23:40 2009 +0200
@@ -387,24 +387,30 @@
return stripped;
}
-/* convenience function that returns a DOM node based on req's result. */
+/* convenience function that returns a DOM node based on req's result.
+ * XXX clarify the need to clone
+ * */
function getDomFromResponse(response) {
if (typeof(response) == 'string') {
- return html2dom(response);
+ var doc = html2dom(response);
+ } else {
+ var doc = response.documentElement;
}
- var doc = response.documentElement;
var children = doc.childNodes;
if (!children.length) {
// no child (error cases) => return the whole document
- return doc.cloneNode(true);
+ return jQuery(doc).clone().context;
}
children = stripEmptyTextNodes(children);
if (children.length == 1) {
// only one child => return it
- return children[0].cloneNode(true);
+ return jQuery(children[0]).clone().context;
}
// several children => wrap them in a single node and return the wrap
- return DIV(null, map(methodcaller('cloneNode', true), children));
+ return DIV(null, map(function(node) {
+ return jQuery(node).clone().context;
+ },
+ children));
}
function postJSON(url, data, callback) {
--- a/web/request.py Mon Sep 07 13:53:12 2009 +0200
+++ b/web/request.py Mon Sep 07 20:23:40 2009 +0200
@@ -26,7 +26,7 @@
from cubicweb.common.mail import header
from cubicweb.common.uilib import remove_html_tags
from cubicweb.utils import SizeConstrainedList, HTMLHead
-from cubicweb.view import STRICT_DOCTYPE
+from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT
from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
RequestError, StatusResponse)
@@ -663,6 +663,16 @@
"""
raise NotImplementedError()
+ def demote_to_html(self):
+ """helper method to dynamically set request content type to text/html
+
+ The global doctype and xmldec must also be changed otherwise the browser
+ will display '<[' at the beginning of the page
+ """
+ self.set_content_type('text/html')
+ self.main_stream.doctype = TRANSITIONAL_DOCTYPE_NOEXT
+ self.main_stream.xmldecl = u''
+
# page data management ####################################################
def get_page_data(self, key, default=None):
--- a/web/views/editcontroller.py Mon Sep 07 13:53:12 2009 +0200
+++ b/web/views/editcontroller.py Mon Sep 07 20:23:40 2009 +0200
@@ -191,7 +191,22 @@
return
attrtype = rschema.objects(entity.e_schema)[0].type
# on checkbox or selection, the field may not be in params
- if attrtype == 'Boolean':
+ # NOTE: raising ValidationError here is not a good solution because
+ # we can't gather all errors at once. Hopefully, the new 3.6.x
+ # form handling will fix that
+ if attrtype == 'Int':
+ try:
+ value = int(value)
+ except ValueError:
+ raise ValidationError(entity.eid,
+ {attr: self.req._("invalid integer value")})
+ elif attrtype == 'Float':
+ try:
+ value = float(value)
+ except ValueError:
+ raise ValidationError(entity.eid,
+ {attr: self.req._("invalid float value")})
+ elif attrtype == 'Boolean':
value = bool(value)
elif attrtype == 'Decimal':
value = Decimal(value)
--- a/web/views/editforms.py Mon Sep 07 13:53:12 2009 +0200
+++ b/web/views/editforms.py Mon Sep 07 20:23:40 2009 +0200
@@ -20,7 +20,8 @@
from cubicweb.utils import make_uid
from cubicweb.view import EntityView
from cubicweb.common import tags
-from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, eid_param, uicfg
+from cubicweb.web import INTERNAL_FIELD_VALUE, RequestError, stdmsgs, eid_param
+from cubicweb.web import uicfg
from cubicweb.web.form import FormViewMixIn, FieldNotFound
from cubicweb.web.formfields import guess_field
from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
@@ -327,13 +328,13 @@
"""creation view for an entity"""
etype = kwargs.pop('etype', self.req.form.get('etype'))
try:
- entity = self.vreg['etypes'].etype_class(etype)(self.req)
- except:
- self.w(self.req._('no such entity type %s') % etype)
- else:
- self.initialize_varmaker()
- entity.eid = self.varmaker.next()
- self.render_form(entity)
+ etype = self.vreg.case_insensitive_etypes[etype.lower()]
+ except KeyError:
+ raise RequestError(self.req._('no such entity type %s') % etype)
+ entity = self.vreg['etypes'].etype_class(etype)(self.req)
+ self.initialize_varmaker()
+ entity.eid = self.varmaker.next()
+ self.render_form(entity)
def form_title(self, entity):
"""the form view title"""
--- a/web/views/igeocodable.py Mon Sep 07 13:53:12 2009 +0200
+++ b/web/views/igeocodable.py Mon Sep 07 20:23:40 2009 +0200
@@ -74,6 +74,7 @@
need_navigation = False
def call(self, gmap_key, width=400, height=400, uselabel=True, urlparams=None):
+ self.req.demote_to_html()
# remove entities that don't define latitude and longitude
self.rset = self.rset.filtered_rset(lambda e: e.latitude and e.longitude)
self.req.add_js('http://maps.google.com/maps?sensor=false&file=api&v=2&key=%s' % gmap_key,