def getFrame(self): """AJAX method to load a frame's contents Expects two query string parameters: ``path`` - the path to fetch - and ``theme``, which can be 'off', to disable the theme and 'apply' to apply the current theme to the response. Additionally: - a query string parameter ``links`` can be set to one of ``disable`` or ``replace``. The former will disable hyperlinks; the latter will replace them with links using the ``@@themeing-controlpanel-getframe`` view. - a query string parameter ``forms`` can be set to one of ``disable`` or ``replace``. The former will disable forms ; the latter will replace them with links using the ``@@themeing-controlpanel-getframe`` view. - a query string parameter ``title`` can be set to give a new page title """ processInputs(self.request) path = self.request.form.get('path', None) theme = self.request.form.get('theme', 'off') links = self.request.form.get('links', None) forms = self.request.form.get('forms', None) title = self.request.form.get('title', None) if not path: return "<html><head></head><body></body></html>" portal = getPortal() portal_url = portal.absolute_url() response = subrequest(path, root=portal) result = response.getBody() content_type = response.headers.get('content-type') encoding = None if content_type is not None and ';' in content_type: content_type, encoding = content_type.split(';', 1) if encoding is None: encoding = 'utf-8' else: # e.g. charset=utf-8 encoding = encoding.split('=', 1)[1].strip() # Not HTML? Return as-is if content_type is None or not content_type.startswith('text/html'): if len(result) == 0: result = ' ' # Zope does not deal well with empty responses return result result = result.decode(encoding).encode('ascii', 'xmlcharrefreplace') if len(result) == 0: result = ' ' # Zope does not deal well with empty responses if theme == 'off': self.request.response.setHeader('X-Theme-Disabled', '1') elif theme == 'apply': self.request.response.setHeader('X-Theme-Disabled', '1') themeInfo = getThemeFromResourceDirectory(self.context) policy = theming_policy(self.request) settings = policy.getSettings() context = self.context try: context = findContext(portal.restrictedTraverse(path)) except (KeyError, NotFound,): pass serializer = getHTMLSerializer([result], pretty_print=False) try: transform = compileThemeTransform( themeInfo.rules, themeInfo.absolutePrefix, settings.readNetwork, themeInfo.parameterExpressions or {}) except lxml.etree.XMLSyntaxError as e: return self.theme_error_template(error=e.msg) params = prepareThemeParameters( context, self.request, themeInfo.parameterExpressions or {}) # Fix url and path since the request gave us this view params['url'] = quote_param(''.join((portal_url, path,))) params['path'] = quote_param( ''.join((portal.absolute_url_path(), path,)) ) if themeInfo.doctype: serializer.doctype = themeInfo.doctype if not serializer.doctype.endswith('\n'): serializer.doctype += '\n' serializer.tree = transform(serializer.tree, **params) result = ''.join(serializer) if title or links or forms: tree = lxml.html.fromstring(result) def encodeUrl(orig): origUrl = urllib.parse.urlparse(orig) newPath = origUrl.path newQuery = urllib.parse.parse_qs(origUrl.query) # relative? if not origUrl.netloc: newPath = urllib.parse.urljoin( path.rstrip("/") + "/", newPath.lstrip("/")) elif not orig.lower().startswith(portal_url.lower()): # Not an internal URL - ignore return orig newQuery['path'] = newPath newQuery['theme'] = theme if links: newQuery['links'] = links if forms: newQuery['forms'] = forms if title: if isinstance(title, six.text_type): newQuery['title'] = title.encode('utf-8', 'replace') else: newQuery['title'] = title return self.request.getURL() + '?' + urllib.parse.urlencode(newQuery) if title: titleElement = tree.cssselect("html head title") if titleElement: titleElement[0].text = title else: headElement = tree.cssselect("html head") if headElement: headElement[0].append(lxml.html.builder.TITLE(title)) if links: for n in tree.cssselect("a[href]"): if links == 'disable': n.attrib['href'] = '#' elif links == 'replace': n.attrib['href'] = encodeUrl(n.attrib['href']) if forms: for n in tree.cssselect("form[action]"): if forms == 'disable': n.attrib['action'] = '#' n.attrib['onsubmit'] = 'javascript:return false;' elif forms == 'replace': n.attrib['action'] = encodeUrl(n.attrib['action']) result = lxml.html.tostring(tree) return result
def getFrame(self): """AJAX method to load a frame's contents Expects two query string parameters: ``path`` - the path to fetch - and ``theme``, which can be 'off', to disable the theme and 'apply' to apply the current theme to the response. Additionally: - a query string parameter ``links`` can be set to one of ``disable`` or ``replace``. The former will disable hyperlinks; the latter will replace them with links using the ``@@themeing-controlpanel-getframe`` view. - a query string parameter ``forms`` can be set to one of ``disable`` or ``replace``. The former will disable forms ; the latter will replace them with links using the ``@@themeing-controlpanel-getframe`` view. - a query string parameter ``title`` can be set to give a new page title """ processInputs(self.request) path = self.request.form.get('path', None) theme = self.request.form.get('theme', 'off') links = self.request.form.get('links', None) forms = self.request.form.get('forms', None) title = self.request.form.get('title', None) if not path: return "<html><head></head><body></body></html>" portal = getPortal() portal_url = portal.absolute_url() response = subrequest(path, root=portal) result = response.getBody() content_type = response.headers.get('content-type') encoding = None if content_type is not None and ';' in content_type: content_type, encoding = content_type.split(';', 1) if encoding is None: encoding = 'utf-8' else: # e.g. charset=utf-8 encoding = encoding.split('=', 1)[1].strip() # Not HTML? Return as-is if content_type is None or not content_type.startswith('text/html'): if len(result) == 0: result = ' ' # Zope does not deal well with empty responses return result result = result.decode(encoding).encode('ascii', 'xmlcharrefreplace') if len(result) == 0: result = ' ' # Zope does not deal well with empty responses if theme == 'off': self.request.response.setHeader('X-Theme-Disabled', '1') elif theme == 'apply': self.request.response.setHeader('X-Theme-Disabled', '1') themeInfo = getThemeFromResourceDirectory(self.context) registry = getUtility(IRegistry) settings = registry.forInterface(IThemeSettings, False) context = self.context try: context = findContext(portal.restrictedTraverse(path)) except (KeyError, NotFound,): pass serializer = getHTMLSerializer([result], pretty_print=False) try: transform = compileThemeTransform(themeInfo.rules, themeInfo.absolutePrefix, settings.readNetwork, themeInfo.parameterExpressions or {}) except lxml.etree.XMLSyntaxError, e: return self.theme_error_template(error=e.msg) params = prepareThemeParameters(context, self.request, themeInfo.parameterExpressions or {}) # Fix url and path since the request gave us this view params['url'] = quote_param("%s%s" % (portal_url, path,)) params['path'] = quote_param("%s%s" % (portal.absolute_url_path(), path,)) if themeInfo.doctype: serializer.doctype = themeInfo.doctype if not serializer.doctype.endswith('\n'): serializer.doctype += '\n' serializer.tree = transform(serializer.tree, **params) result = ''.join(serializer)