[utils] add a ``js_href`` function to generated proper javascript href
The main gain is the escaping of %
* * *
[pagination] use js_href for building javascript link (closes #2035033)
This prevent snicky error with url unquoting of javascript code
--- a/utils.py Fri Oct 21 14:32:37 2011 +0200
+++ b/utils.py Tue Oct 18 12:25:32 2011 +0200
@@ -25,6 +25,8 @@
import decimal
import datetime
import random
+import re
+
from operator import itemgetter
from inspect import getargspec
from itertools import repeat
@@ -540,6 +542,29 @@
return something
return json_dumps(something)
+PERCENT_IN_URLQUOTE_RE = re.compile(r'%(?=[0-9a-fA-F]{2})')
+def js_href(javascript_code):
+ """Generate a "javascript: ..." string for an href attribute.
+
+ Some % which may be interpreted in a href context will be escaped.
+
+ In an href attribute, url-quotes-looking fragments are interpreted before
+ being given to the javascript engine. Valid url quotes are in the form
+ ``%xx`` with xx being a byte in hexadecimal form. This means that ``%toto``
+ will be unaltered but ``%babar`` will be mangled because ``ba`` is the
+ hexadecimal representation of 186.
+
+ >>> js_href('alert("babar");')
+ 'javascript: alert("babar");'
+ >>> js_href('alert("%babar");')
+ 'javascript: alert("%25babar");'
+ >>> js_href('alert("%toto %babar");')
+ 'javascript: alert("%toto %25babar");'
+ >>> js_href('alert("%1337%");')
+ 'javascript: alert("%251337%");'
+ """
+ return 'javascript: ' + PERCENT_IN_URLQUOTE_RE.sub(r'%25', javascript_code)
+
@deprecated('[3.7] merge_dicts is deprecated')
def merge_dicts(dict1, dict2):
--- a/web/component.py Fri Oct 21 14:32:37 2011 +0200
+++ b/web/component.py Tue Oct 18 12:25:32 2011 +0200
@@ -30,7 +30,7 @@
from cubicweb import Unauthorized, role, target, tags
from cubicweb.schema import display_name
from cubicweb.uilib import js, domid
-from cubicweb.utils import json_dumps
+from cubicweb.utils import json_dumps, js_href
from cubicweb.view import ReloadableMixIn, Component
from cubicweb.selectors import (no_cnx, paginated_rset, one_line_rset,
non_final_entity, partial_relation_possible,
@@ -120,8 +120,8 @@
def ajax_page_url(self, **params):
divid = params.setdefault('divid', 'pageContent')
params['rql'] = self.cw_rset.printable_rql()
- return "javascript: $(%s).loadxhtml('json', %s, 'get', 'swap')" % (
- json_dumps('#'+divid), js.ajaxFuncArgs('view', params))
+ return js_href("$(%s).loadxhtml('json', %s, 'get', 'swap')" % (
+ json_dumps('#'+divid), js.ajaxFuncArgs('view', params)))
def page_link(self, path, params, start, stop, content):
url = xml_escape(self.page_url(path, params, start, stop))