Example #1
0
 def trac_get_reference(env, context, rawtext, target, text):
     fulltext = target + ' ' + text if text else target
     link = extract_link(env, context, fulltext)
     uri = None
     missing = False
     if isinstance(link, (Element, Fragment)):
         linktext = Markup(link).striptags()
         # the following is a bit hackish, but it takes into account:
         #  - an eventual trailing '?' for missing wiki pages
         #  - space eventually introduced due to split_page_names option
         if linktext.rstrip('?').replace(' ', '') != target:
             text = linktext
         elt = find_element(link, 'href', 'missing')
         if elt is not None:
             uri = elt.attrib.get('href', '')
             missing = 'missing' in elt.attrib.get('class', '').split()
     else:
         uri = context.href.wiki(target)
         missing = not WikiSystem(env).has_page(target)
     if uri or missing:                    
         reference = nodes.reference(rawtext, text or target)
         reference['refuri'] = uri
         if missing:
             reference['classes'].append('missing')
         return reference
Example #2
0
 def _check_quickjump(self, req, noquickjump, kwd):
     """Look for search shortcuts"""
     # Source quickjump  FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == '/':
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _('Browse repository path %(path)s', path=kwd)
     else:
         context = web_context(req, 'search')
         link = find_element(extract_link(self.env, context, kwd), 'href')
         if link is not None:
             quickjump_href = link.attrib.get('href')
             name = link.children
             description = link.attrib.get('title', '')
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         if not quickjump_href.startswith(req.base_path or '/'):
             noquickjump = True
         if noquickjump:
             return {'href': quickjump_href, 'name': tag.em(name),
                     'description': description}
         else:
             help_url = req.href.wiki('TracSearch') + '#Quicksearches'
             search_url = req.href.search(q=kwd, noquickjump=1)
             # FIXME: use tag_
             add_notice(req, Markup(_(
                 'You arrived here through the <a href="%(help_url)s">'
                 'quick-jump</a> search feature. To instead search for the '
                 'term <strong>%(term)s</strong>, click <a '
                 'href="%(search_url)s">here</a>.',
                 help_url=escape(help_url), term=escape(kwd),
                 search_url=escape(search_url))))
             req.redirect(quickjump_href)
Example #3
0
 def _check_quickjump(self, req, kwd):
     """Look for search shortcuts"""
     noquickjump = int(req.args.get('noquickjump', '0'))
     # Source quickjump   FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == '/':
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _('Browse repository path %(path)s', path=kwd)
     else:
         link = extract_link(self.env, Context.from_request(req, 'search'),
                             kwd)
         if isinstance(link, Element):
             quickjump_href = link.attrib.get('href')
             name = link.children
             description = link.attrib.get('title', '')
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         if not quickjump_href.startswith(req.base_path or '/'):
             noquickjump = True
         if noquickjump:
             return {'href': quickjump_href, 'name': tag.EM(name),
                     'description': description}
         else:
             req.redirect(quickjump_href)
Example #4
0
 def trac_get_reference(env, context, rawtext, target, text):
     fulltext = target + ' ' + text if text else target
     link = extract_link(env, context, fulltext)
     uri = None
     missing = False
     if isinstance(link, (Element, Fragment)):
         linktext = Markup(link).striptags()
         # the following is a bit hackish, but it takes into account:
         #  - an eventual trailing '?' for missing wiki pages
         #  - space eventually introduced due to split_page_names option
         if linktext.rstrip('?').replace(' ', '') != target:
             text = linktext
         elt = find_element(link, 'href', 'missing')
         if elt is not None:
             uri = elt.attrib.get('href', '')
             missing = 'missing' in elt.attrib.get('class', '').split()
     else:
         uri = context.href.wiki(target)
         missing = not WikiSystem(env).has_page(target)
     if uri or missing:
         reference = nodes.reference(rawtext, text or target)
         reference['refuri'] = uri
         if missing:
             reference['classes'].append('missing')
         return reference
Example #5
0
 def expand(match):
     attrib, wiki_text = match.groups()  # "URL" or "href", "TracLink"
     link = extract_link(self.env, context, wiki_text)
     link = find_element(link, 'href')
     if link:
         href = link.attrib.get('href')
         name = link.children
         description = link.attrib.get('title', '')
     else:
         href = wiki_text
         description = None
         if self.sanitizer:
             href = ''
     attribs = []
     if href:
         if out_format == 'svg':
             format = '="javascript:window.parent.location.href=\'%s\'"'
         else:
             format = '="%s"'
         attribs.append(attrib + format % href)
     if description:
         attribs.append(
             'tooltip="%s"' %
             (description.replace('"', '').replace('\n', '')))
     return '\n'.join(attribs)
Example #6
0
    def process_request(self, req):
        link = req.args.get('link', '')
        parts = link.split(':', 1)
        if len(parts) > 1:
            resolver, target = parts
            if target[:1] + target[-1:] not in ('""', "''"):
                link = '%s:"%s"' % (resolver, target)
        from trac.web.chrome import web_context
        link_frag = extract_link(self.env, web_context(req), link)

        def get_first_href(item):
            """Depth-first search for the first `href` attribute."""
            if isinstance(item, Element):
                href = item.attrib.get('href')
                if href is not None:
                    return href
            if isinstance(item, Fragment):
                for each in item.children:
                    href = get_first_href(each)
                    if href is not None:
                        return href

        if isinstance(link_frag, (Element, Fragment)):
            href = get_first_href(link_frag)
            if href is None: # most probably no permissions to view
                raise PermissionError(_("Can't view %(link)s:", link=link))
        else:
            href = req.href(link.rstrip(':'))
        req.redirect(href)
Example #7
0
 def _check_quickjump(self, req, kwd):
     """Look for search shortcuts"""
     noquickjump = int(req.args.get('noquickjump', '0'))
     # Source quickjump   FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == '/':
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _('Browse repository path %(path)s', path=kwd)
     else:
         link = extract_link(self.env, Context.from_request(req, 'search'),
                             kwd)
         if isinstance(link, Element):
             quickjump_href = link.attrib.get('href')
             name = link.children
             description = link.attrib.get('title', '')
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         if not quickjump_href.startswith(req.base_path or '/'):
             noquickjump = True
         if noquickjump:
             return {
                 'href': quickjump_href,
                 'name': tag.EM(name),
                 'description': description
             }
         else:
             req.redirect(quickjump_href)
Example #8
0
 def _check_quickjump(self, req, kwd):
     """Look for search shortcuts"""
     # pylint: disable=maybe-no-member
     noquickjump = int(req.args.get('noquickjump', '0'))
     # Source quickjump   FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == '/':
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _('Browse repository path %(path)s', path=kwd)
     else:
         context = web_context(req, 'search')
         link = find_element(extract_link(self.env, context, kwd), 'href')
         if link is not None:
             quickjump_href = link.attrib.get('href')
             name = link.children
             description = link.attrib.get('title', '')
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         base_path = req.base_path.replace('@', '%40')
         redirect_href = quickjump_href.replace('@', '%40')
         if not redirect_href.startswith(base_path or '/'):
             noquickjump = True
         if noquickjump:
             return {'href': quickjump_href, 'name': tag.EM(name),
                     'description': description}
         else:
             req.redirect(quickjump_href)
Example #9
0
 def _check_quickjump(self, req, kwd):
     """Look for search shortcuts"""
     noquickjump = as_int(req.args.get('noquickjump'), 0)
     # Source quickjump   FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == '/':
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _('Browse repository path %(path)s', path=kwd)
     else:
         context = web_context(req, 'search')
         link = find_element(extract_link(self.env, context, kwd), 'href')
         if link is not None:
             quickjump_href = link.attrib.get('href')
             name = link.children
             description = link.attrib.get('title', '')
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         if not quickjump_href.startswith(req.base_path or '/'):
             noquickjump = True
         if noquickjump:
             return {
                 'href': quickjump_href,
                 'name': tag.em(name),
                 'description': description
             }
         else:
             req.redirect(quickjump_href)
Example #10
0
    def process_request(self, req):
        link = req.args.get("link", "")
        parts = link.split(":", 1)
        if len(parts) > 1:
            resolver, target = parts
            if target and (target[0] not in "'\"" or target[0] != target[-1]):
                link = '%s:"%s"' % (resolver, target)
        link_frag = extract_link(self.env, Context.from_request(req), link)

        def get_first_href(item):
            """Depth-first search for the first `href` attribute."""
            if isinstance(item, Element):
                href = item.attrib.get("href")
                if href is not None:
                    return href
            if isinstance(item, Fragment):
                for each in item.children:
                    href = get_first_href(each)
                    if href is not None:
                        return href

        if isinstance(link_frag, (Element, Fragment)):
            href = get_first_href(link_frag)
            if href is None:  # most probably no permissions to view
                raise PermissionError(_("Can't view %(link)s:", link=link))
        else:
            href = req.href(link.rstrip(":"))
        req.redirect(href)
Example #11
0
 def process_request(self, req):
     link = req.args.get('link', '')
     link_elt = extract_link(self.env, Context.from_request(req), link)
     if isinstance(link_elt, Element):
         href = link_elt.attrib.get('href')
         if href is None: # most probably no permissions to view
             raise PermissionError(_("Can't view %(link)s:", link=link))
     else:
         href = req.href(link.rstrip(':'))
     req.redirect(href)
	def _get_quickjump(self, req, query):
		"""Find quickjump requests if the search comes from the searchbox
		in the header.  The search is assumed to be from the header searchbox
		if no page or per_page arguments are found.
		"""
		if req.args.get('page') or req.args.get('per_page'):
			return None

		link = extract_link(self.env,
			Context.from_request(req, 'advsearch'), query)
		if isinstance(link, Element):
			return link.attrib.get('href')
    def _get_quickjump(self, req, query):
        """Find quickjump requests if the search comes from the searchbox
		in the header.  The search is assumed to be from the header searchbox
		if no page or per_page arguments are found.
		"""
        if req.args.get('page') or req.args.get('per_page'):
            return None

        link = extract_link(self.env, Context.from_request(req, 'advsearch'),
                            query)
        if isinstance(link, Element):
            return link.attrib.get('href')
Example #14
0
 def process_request(self, req):
     link = req.args.get('link', '')
     parts = link.split(':', 1)
     if len(parts) > 1:
         resolver, target = parts
         if target[:1] + target[-1:] not in ('""', "''"):
             link = '%s:"%s"' % (resolver, target)
     from trac.web.chrome import web_context
     link_frag = extract_link(self.env, web_context(req), link)
     if isinstance(link_frag, (Element, Fragment)):
         elt = find_element(link_frag, 'href')
         if elt is None: # most probably no permissions to view
             raise PermissionError(_("Can't view %(link)s:", link=link))
         href = elt.attrib.get('href')
     else:
         href = req.href(link.rstrip(':'))
     req.redirect(href)
Example #15
0
 def process_request(self, req):
     link = req.args.get('link', '')
     parts = link.split(':', 1)
     if len(parts) > 1:
         resolver, target = parts
         if target[:1] + target[-1:] not in ('""', "''"):
             link = '%s:"%s"' % (resolver, target)
     from trac.web.chrome import web_context
     link_frag = extract_link(self.env, web_context(req), link)
     if isinstance(link_frag, (Element, Fragment)):
         elt = find_element(link_frag, 'href')
         if elt is None:  # most probably no permissions to view
             raise PermissionError(_("Can't view %(link)s:", link=link))
         href = elt.attrib.get('href')
     else:
         href = req.href(link.rstrip(':'))
     req.redirect(href)
Example #16
0
 def expand(match):
     wiki_text = match.groups()[0] # TracLink ([1], source:file/, ...)
     link = extract_link(self.env, context, wiki_text)
     if isinstance(link, Element):
         href = link.attrib.get('href')
         name = link.children
         description = link.attrib.get('title', '')
     else:
         href = wiki_text
         description = None
     if out_format == 'svg':
         format = 'URL="javascript:window.parent.location.href=\'%s\'"'
     else:
         format = 'URL="%s"'
     url = format % href
     if description:
         url += '\ntooltip="%s"' % description \
                 .replace('"', '').replace('\n', '')
     return url
Example #17
0
 def expand(match):
     wiki_text = match.groups()[0] # TracLink ([1], source:file/, ...)
     link = extract_link(self.env, formatter.context, wiki_text)
     if isinstance(link, Element):
         href = link.attrib.get('href')
         name = link.children
         description = link.attrib.get('title', '')
     else:
         href = wiki_text
         description = None
     if out_format == 'svg':
         format = 'URL="javascript:window.parent.location.href=\'%s\'"'
     else:
         format = 'URL="%s"'
     url = format % href
     if description:
         url += '\ntooltip="%s"' % description \
                 .replace('"', '').replace('\n', '')
     return url
Example #18
0
 def expand(match):
     attrib, wiki_text = match.groups() # "URL" or "href", "TracLink"
     link = extract_link(self.env, context, wiki_text)
     link = find_element(link, 'href')
     if link:
         href = link.attrib.get('href')
         name = link.children
         description = link.attrib.get('title', '')
     else:
         href = wiki_text
         description = None
         if self.sanitizer:
             href = ''
     attribs = []
     if href:
         if out_format == 'svg':
             format = '="javascript:window.parent.location.href=\'%s\'"'
         else:
             format = '="%s"'
         attribs.append(attrib + format % href)
     if description:
         attribs.append('tooltip="%s"' % (description.replace('"', '')
                                          .replace('\n', '')))
     return '\n'.join(attribs)
Example #19
0
 def _check_quickjump(self, req, kwd):
     """Look for search shortcuts"""
     noquickjump = int(req.args.get("noquickjump", "0"))
     # Source quickjump   FIXME: delegate to ISearchSource.search_quickjump
     quickjump_href = None
     if kwd[0] == "/":
         quickjump_href = req.href.browser(kwd)
         name = kwd
         description = _("Browse repository path %(path)s", path=kwd)
     else:
         context = web_context(req, "search")
         link = find_element(extract_link(self.env, context, kwd), "href")
         if link is not None:
             quickjump_href = link.attrib.get("href")
             name = link.children
             description = link.attrib.get("title", "")
     if quickjump_href:
         # Only automatically redirect to local quickjump links
         if not quickjump_href.startswith(req.base_path or "/"):
             noquickjump = True
         if noquickjump:
             return {"href": quickjump_href, "name": tag.em(name), "description": description}
         else:
             req.redirect(quickjump_href)
Example #20
0
def get_absolute_url(url, formatter=None, base=None):
    """ Generate an absolute url from the url with the special schemes
        {htdocs,chrome,ticket,wiki,source} simply return the url if given with
        {http,https,ftp} schemes. Also supports TracLinks.
        
        Examples:
            http://example.com/filename.ext
                ie. http://www.google.com/logo.jpg
            
            htdocs://site/filename.ext
            htdocs://plugin/dir/filename.ext
                note: `chrome` is an alias for `htdocs`
            
            ticket://number/attachment.pdf
                ie. ticket://123/specification.pdf
            
            wiki://WikiWord/attachment.jpg
            
            source://changeset/path/filename.ext
                ie. source://1024/trunk/docs/README
    """
    def ujoin(*parts):
        """ Remove double slashes.
        """
        parts = [part.strip('/') for part in parts]
        return '/' + '/'.join(parts)

    # You must supply a formatter or a base.
    if not base:
        base = formatter.href.base

    if url.find('://') > 0:
        scheme, netloc, path, query, params, fragment = urlparse.urlparse(url)

        if scheme in ('ftp', 'http', 'https'):
            return url

        if scheme in ('htdocs', 'chrome'):
            return ujoin(base, 'chrome', path)

        if scheme in ('source', ):
            return ujoin(base, 'export', path)

        if scheme in ('ticket', ):
            return ujoin(base, 'raw-attachment/ticket', path)

        if scheme in ('wiki', ):
            return ujoin(base, 'raw-attachment/wiki', path)

        return url

    # You'll need a formatter for this, code from #3938, serious testing needed.
    else:
        link = extract_link(formatter.env, formatter.context, url)

        if isinstance(link, Element):
            url = link.attrib.get('href')

            scheme, netloc, path, query, params, fragment = urlparse.urlparse(
                url)
            if path.startswith('/browser/'):
                query_dict = xform_query(query)
                query_dict['format'] = 'raw'
                query = xfrom_query(query_dict)
                url = urlparse.urlunparse(
                    (scheme, netloc, path, query, params, fragment))

            elif path.startswith('/attachement/'):
                url = url.replace('/attachment/', '/raw-attachment/', 1)

            return url
Example #21
0
    def expand_macro(self, formatter, name, content):
        # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = content.split(',')
        if len(args) == 0:
            raise Exception("No argument.")
        filespec = args.pop(0)

        # style information
        size_re = re.compile('[0-9]+(%|px)?$')
        attr_re = re.compile('(align|valign|border|width|height|alt'
                             '|margin(?:-(?:left|right|top|bottom))?'
                             '|title|longdesc|class|id|usemap)=(.+)')
        quoted_re = re.compile("(?:[\"'])(.*)(?:[\"'])$")
        attr = {}
        style = {}
        link = ''
        while args:
            arg = args.pop(0).strip()
            if size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
            elif arg == 'nolink':
                link = None
            elif arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                link = None
                if isinstance(elt, Element):
                    link = elt.attrib.get('href')
            elif arg in ('left', 'right'):
                style['float'] = arg
            elif arg == 'center':
                style['margin-left'] = style['margin-right'] = 'auto'
                style['display'] = 'block'
                style.pop('margin', '')
            elif arg in ('top', 'bottom', 'middle'):
                style['vertical-align'] = arg
            else:
                match = attr_re.match(arg)
                if match:
                    key, val = match.groups()
                    if (key == 'align' and 
                            val in ('left', 'right', 'center')) or \
                        (key == 'valign' and \
                            val in ('top', 'middle', 'bottom')):
                        args.append(val)
                    elif key in ('margin-top', 'margin-bottom'):
                        style[key] = ' %dpx' % int(val)
                    elif key in ('margin', 'margin-left', 'margin-right') \
                             and 'display' not in style:
                        style[key] = ' %dpx' % int(val)
                    elif key == 'border':
                        style['border'] = ' %dpx solid' % int(val)
                    else:
                        m = quoted_re.search(val) # unquote "..." and '...'
                        if m:
                            val = m.group(1)
                        attr[str(key)] = val # will be used as a __call__ kwd

        # parse filespec argument to get realm and id if contained.
        parts = filespec.split(':')
        url = raw_url = desc = None
        attachment = None
        if (parts and parts[0] in ('http', 'https', 'ftp')): # absolute
            raw_url = url = desc = filespec
        elif filespec.startswith('//'):       # server-relative
            raw_url = url = desc = filespec[1:]
        elif filespec.startswith('/'):        # project-relative
            # use href, but unquote to allow args (use default html escaping)
            raw_url = url = desc = unquote(formatter.href(filespec))
        elif len(parts) == 3:                 # realm:id:attachment-filename
            realm, id, filename = parts
            attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            # FIXME: somehow use ResourceSystem.get_known_realms()
            #        ... or directly trac.wiki.extract_link
            from trac.versioncontrol.web_ui import BrowserModule
            try:
                browser_links = [res[0] for res in
                                 BrowserModule(self.env).get_link_resolvers()]
            except Exception:
                browser_links = []
            if parts[0] in browser_links:   # source:path
                # TODO: use context here as well
                realm, filename = parts
                rev = None
                if '@' in filename:
                    filename, rev = filename.split('@')
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename, rev=rev,
                                                 format='raw')
                desc = filespec
            else: # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm, id).child('attachment',
                                                           filename)
        elif len(parts) == 1: # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            raise TracError('No filespec given')
        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            raw_url = get_resource_url(self.env, attachment, formatter.href,
                                       format='raw')
            try:
                desc = get_resource_summary(self.env, attachment)
            except ResourceNotFound, e:
                raw_url = formatter.href.chrome('common/attachment.png')
                desc = _('No image "%(id)s" attached to %(parent)s',
                         id=attachment.id,
                         parent=get_resource_name(self.env, attachment.parent))
Example #22
0
    def expand_macro(self, formatter, name, content):
        args = None
        if content:
            content = stripws(content)
            # parse arguments
            # we expect the 1st argument to be a filename (filespec)
            args = [stripws(arg) for arg
                                 in self._split_args_re.split(content)[1::2]]
        if not args:
            return ''
        # strip unicode white-spaces and ZWSPs are copied from attachments
        # section (#10668)
        filespec = args.pop(0)

        # style information
        attr = {}
        style = {}
        link = ''
        # helper for the special case `source:`
        #
        from trac.versioncontrol.web_ui import BrowserModule
        # FIXME: somehow use ResourceSystem.get_known_realms()
        #        ... or directly trac.wiki.extract_link
        try:
            browser_links = [res[0] for res in
                             BrowserModule(self.env).get_link_resolvers()]
        except Exception:
            browser_links = []
        while args:
            arg = args.pop(0)
            if self._size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
            elif arg == 'nolink':
                link = None
            elif arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                elt = find_element(elt, 'href')
                link = None
                if elt is not None:
                    link = elt.attrib.get('href')
            elif arg in ('left', 'right'):
                style['float'] = arg
            elif arg == 'center':
                style['margin-left'] = style['margin-right'] = 'auto'
                style['display'] = 'block'
                style.pop('margin', '')
            elif arg in ('top', 'bottom', 'middle'):
                style['vertical-align'] = arg
            else:
                match = self._attr_re.match(arg)
                if match:
                    key, val = match.groups()
                    if (key == 'align' and
                            val in ('left', 'right', 'center')) or \
                        (key == 'valign' and
                            val in ('top', 'middle', 'bottom')):
                        args.append(val)
                    elif key in ('margin-top', 'margin-bottom'):
                        style[key] = ' %dpx' % _arg_as_int(val, key, min=1)
                    elif key in ('margin', 'margin-left', 'margin-right') \
                             and 'display' not in style:
                        style[key] = ' %dpx' % _arg_as_int(val, key, min=1)
                    elif key == 'border':
                        style['border'] = ' %dpx solid' % _arg_as_int(val, key)
                    else:
                        m = self._quoted_re.search(val)  # unquote "..." and '...'
                        if m:
                            val = m.group(1)
                        attr[str(key)] = val  # will be used as a __call__ kwd

        if self._quoted_re.match(filespec):
            filespec = filespec.strip('\'"')
        # parse filespec argument to get realm and id if contained.
        parts = [i.strip('\'"')
                 for i in self._split_filespec_re.split(filespec)[1::2]]
        realm = parts[0] if parts else None
        url = raw_url = desc = None
        attachment = None
        interwikimap = InterWikiMap(self.env)
        if realm in ('http', 'https', 'ftp', 'data'):  # absolute
            raw_url = url = filespec
            desc = url.rsplit('?')[0]
        elif realm in interwikimap:
            url, desc = interwikimap.url(realm, ':'.join(parts[1:]))
            raw_url = url
        elif filespec.startswith('//'):       # server-relative
            raw_url = url = filespec[1:]
            desc = url.rsplit('?')[0]
        elif filespec.startswith('/'):        # project-relative
            params = ''
            if '?' in filespec:
                filespec, params = filespec.rsplit('?', 1)
            url = formatter.href(filespec)
            if params:
                url += '?' + params
            raw_url, desc = url, filespec
        elif len(parts) == 3:                 # realm:id:attachment-filename
            #                                 # or intertrac:realm:id
            realm, id, filename = parts
            intertrac_target = "%s:%s" % (id, filename)
            it = formatter.get_intertrac_url(realm, intertrac_target)
            if it:
                url, desc = it
                raw_url = url + unicode_quote('?format=raw')
            else:
                attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            realm, filename = parts
            if realm in browser_links:  # source:path
                # TODO: use context here as well
                rev = None
                if '@' in filename:
                    filename, rev = filename.rsplit('@', 1)
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename, rev=rev,
                                                 format='raw')
                desc = filespec
            else:  # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                elif id == 'shared':
                    raw_url = url = formatter.href.chrome('shared', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm, id).child('attachment',
                                                           filename)
        elif len(parts) == 1:  # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            return system_message(_("No filespec given"))
        if attachment:
            try:
                desc = get_resource_summary(self.env, attachment)
            except ResourceNotFound:
                link = None
                raw_url = chrome_resource_path(formatter.context.req,
                                               'common/attachment.png')
                desc = _('No image "%(id)s" attached to %(parent)s',
                         id=attachment.id,
                         parent=get_resource_name(self.env, attachment.parent))
            else:
                if 'ATTACHMENT_VIEW' in formatter.perm(attachment):
                    url = get_resource_url(self.env, attachment,
                                           formatter.href)
                    raw_url = get_resource_url(self.env, attachment,
                                               formatter.href, format='raw')

        for key in ('title', 'alt'):
            if desc and key not in attr:
                attr[key] = desc
        if style:
            attr['style'] = '; '.join('%s:%s' % (k, escape(v))
                                      for k, v in style.iteritems())
        if not WikiSystem(self.env).is_safe_origin(raw_url,
                                                   formatter.context.req):
            attr['crossorigin'] = 'anonymous'  # avoid password prompt
        result = tag.img(src=raw_url, **attr)
        if link is not None:
            result = tag.a(result, href=link or url,
                           style='padding:0; border:none')
        return result
Example #23
0
    def expand_macro(self, formatter, name, content):
        # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = content.split(',')
        if len(args) == 0:
            raise Exception("No argument.")
        filespec = args[0]

        # style information
        size_re = re.compile('[0-9]+(%|px)?$')
        attr_re = re.compile('(align|border|width|height|alt'
                             '|title|longdesc|class|id|usemap)=(.+)')
        quoted_re = re.compile("(?:[\"'])(.*)(?:[\"'])$")
        attr = {}
        style = {}
        link = ''
        for arg in args[1:]:
            arg = arg.strip()
            if size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
                continue
            if arg == 'nolink':
                link = None
                continue
            if arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                link = None
                if isinstance(elt, Element):
                    link = elt.attrib.get('href')
                continue
            if arg in ('left', 'right', 'top', 'bottom'):
                style['float'] = arg
                continue
            match = attr_re.match(arg)
            if match:
                key, val = match.groups()
                m = quoted_re.search(val) # unquote "..." and '...'
                if m:
                    val = m.group(1)
                if key == 'align':
                    style['float'] = val
                elif key == 'border':
                    style['border'] = ' %dpx solid' % int(val);
                else:
                    attr[str(key)] = val # will be used as a __call__ keyword

        # parse filespec argument to get realm and id if contained.
        parts = filespec.split(':')
        url = raw_url = desc = None
        attachment = None
        if (parts and parts[0] in ('http', 'https', 'ftp')): # absolute
            raw_url = url = desc = filespec
        elif filespec.startswith('//'):       # server-relative
            raw_url = url = desc = filespec[1:]
        elif filespec.startswith('/'):        # project-relative
            # use href, but unquote to allow args (use default html escaping)
            raw_url = url = desc = unquote(formatter.href(filespec))
        elif len(parts) == 3:                 # realm:id:attachment-filename
            realm, id, filename = parts
            attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            # FIXME: somehow use ResourceSystem.get_known_realms()
            #        ... or directly trac.wiki.extract_link
            from trac.versioncontrol.web_ui import BrowserModule
            try:
                browser_links = [res[0] for res in
                                 BrowserModule(self.env).get_link_resolvers()]
            except Exception:
                browser_links = []
            if parts[0] in browser_links:   # source:path
                # TODO: use context here as well
                realm, filename = parts
                rev = None
                if '@' in filename:
                    filename, rev = filename.split('@')
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename, rev=rev,
                                                 format='raw')
                desc = filespec
            else: # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm, id).child('attachment',
                                                           filename)
        elif len(parts) == 1: # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            raise TracError('No filespec given')
        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            raw_url = get_resource_url(self.env, attachment, formatter.href,
                                       format='raw')
            desc = get_resource_summary(self.env, attachment)
        for key in ('title', 'alt'):
            if desc and not key in attr:
                attr[key] = desc
        if style:
            attr['style'] = '; '.join(['%s:%s' % (k, escape(v))
                                       for k, v in style.iteritems()])
        result = tag.img(src=raw_url, **attr)
        if link is not None:
            result = tag.a(result, href=link or url,
                           style='padding:0; border:none')
        return result
Example #24
0
def extract_url(env, context, wikilink, raw=False):
    """
= Description for `extract_url()` =
Extracts an URL from an Wiki link, e.g. to used in macro produced HTML code.

Website: http://trac-hacks.org/wiki/ExtractUrlPlugin

`$Id$`

== Description ==
Returns an (possible relative) URL which can be used in HTML code.

If `raw` is true the returned link will point to a downloadable
version of the linked resource otherwise the same link is returned
which would be used in the resulting Wiki page.

The raw links are also usable as online resouces, e.g. if the link target
is to be used as input for a flash application etc.

== Usage ==
General:
{{{
from tracextracturl import extract_url
# ...
  url = extract_url (env, context, wikilink, raw=False)
}}}

Inside WikiMacros:
{{{
#!python
from tracextracturl import extract_url

def MyMacro(WikiMacroBase):
  def expand_macro (self, formatter, name, content):
     # e.g. wikilink = 'wiki:WikiStart' or 'attachment:file.ext'
     url = extract_url(self.env, formatter.context, wikilink)
     rawurl = extract_url(self.env, formatter.context, wikilink, True)
}}}

== Example ==
Inside a Trac macro called from the wiki page 'ExamplePage' of project
'project1' on a multi-project trac server:
{{{
    extract_url(self.env, formatter, 'attachment:file.js', True)
}}}
will return `/project1/raw-attachment/wiki/ExamplePage/file.js`,
which could be directly accessed by the browser inside some javascript 
or flash HTML object code produced by the macro.
    """
    from genshi.builder import Element, Fragment
    from trac.wiki.formatter import extract_link

    if not wikilink:
        return ''

    link = extract_link(env, context, '[' + wikilink + ' x]')
    #env.log.debug("link = " + str(link.__class__) + ' ' + str(link))

    if isinstance(link, Element):
        href = link.attrib.get('href')
        #env.log.debug("href1 = " + href)
    elif isinstance(link, Fragment):
        link = link.children[0]
        href = link.attrib.get('href')
        #env.log.debug("href2 = " + href)
    else:
        href = None

    if not href:
        return ''

    if raw:
        # rewrite URL to point to downloadable/exportable/raw version of the
        # linked resource

        # Remove existing project URL part for later string search
        base_path = context.req.base_path
        if base_path and href.startswith(base_path):
            # href relative to base path
            rhref = href[len(base_path):]
        else:
            rhref = href

        # For browser links add the 'format=raw' URL parameter.
        # The alternative '/export' target isn't used because a revision number
        # would be needed.
        if rhref.startswith('/browser/'):
            if rhref.find('?') == -1:
                # If no other parameter exists, simply append:
                href += r'?format=raw'
            else:
                # Otherwise add to existing parameters if this one doesn't
                # exists yet:
                if href.find(r'?format=') == -1 and href.find(
                        r'&format=') == -1:
                    href += r'&format=raw'
        # Change 'attachment' links to 'raw-attachment' links:
        elif rhref.startswith('/attachment/'):
            href = href.replace('/attachment/', '/raw-attachment/', 1)
        # All other link types should be already fine for file export (if
        # applicable)
    return href
Example #25
0
    def expand_macro(self, formatter, name, content):
         # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = content.split(',')
        if len(args) == 0:
            raise Exception("No argument.")
        filespec = args[0]

        # style information
        size_re = re.compile('[0-9]+(%|px)?$')
        attr_re = re.compile('(align|border|width|height|alt'
                             '|title|longdesc|class|id|usemap)=(.+)')
        quoted_re = re.compile("(?:[\"'])(.*)(?:[\"'])$")
        layers_re = re.compile("^[0-9]+(\.[0-9]+)*$")
        attr = {}
        style = {}
        link = ''
        width = None
        layers = None
        for arg in args[1:]:
            arg = arg.strip()
            if size_re.match(arg):
                if width:
                    raise Exception("Argument 'width' appears more than once.")
                width = arg
                attr['width'] = arg
                continue
            if arg == 'nolink':
                link = None
                continue
            if arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                link = None
                if isinstance(elt, Element):
                    link = elt.attrib.get('href')
                continue
            if arg in ('left', 'right', 'top', 'bottom'):
                style['float'] = arg
                continue
            if arg.startswith('layers='):
                if layers:
                    raise Exception("Argument 'layers' appears more than once.")
                layers = arg.split('=', 1)[1]
                if not layers_re.match(layers):
                    raise Exception("Wrong layer list format, use dot separated list of integer numbers.")
            match = attr_re.match(arg)
            if match:
                key, val = match.groups()
                m = quoted_re.search(val) # unquote "..." and '...'
                if m:
                    val = m.group(1)
                if key == 'align':
                    style['float'] = val
                elif key == 'border':
                    style['border'] = ' %dpx solid' % int(val);
                else:
                    attr[str(key)] = val # will be used as a __call__ keyword

        # Got the args now do some processing
        attachment = formatter.resource.child('attachment', filespec)
        realm = formatter.resource.realm
        resource_id     = formatter.resource.id         # The use of "id" could cause a conflict?

        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            description = get_resource_summary(self.env, attachment)

        # Includes vdx for use with Visio
        png_url = url.replace(".dia",".png").replace(".vdx",".png")
        dia_attachment = Attachment(self.env, realm, resource_id, filespec)
        dia_path = dia_attachment.path
        dia_filename = dia_attachment.filename
        png_path = dia_path.replace('.dia','.png').replace(".vdx",".png")
        png_filename = dia_filename.replace('.dia','.png').replace(".vdx",".png")

        # the layers are encoded into the path as dot-separated list, e.g. basename.1.2.png
        if layers:
            layers_extension = '.' + layers + '.png'
            png_path = png_path.replace('.png', layers_extension)
            png_filename = png_filename.replace('.png', layers_extension)
            png_url = png_url.replace(".png", layers_extension)

        png_attachment = Attachment(self.env, realm, resource_id, filespec)

        if len(description) <= 0:
            description = 'PNG render of ' + dia_filename

        self.env.log.info('Getting file modification times.')
        try:
            dia_mtime = os.path.getmtime(dia_path)
        except Exception:
            raise Exception('File does not exist: %s', dia_path)

        try:
            png_mtime = os.path.getmtime(png_path)
        except Exception:
            png_mtime = 0
        else:
            try:
                im = Image.open(png_path)
            except Exception, e:
                self.env.log.info('Error checking original png file width for Dia = %s',e)
                raise Exception('Error checking original png file width for Dia.')
            existing_width = im.size[0]
Example #26
0
    def expand_macro(self, formatter, name, content, args=None):
        content = content.replace('\n', ',')
        largs, kwargs = parse_args(content, multi=['marker', 'to'])
        if len(largs) > 0:
            arg = unicode(largs[0])
            if _reCOORDS.match(arg):
                if not 'center' in kwargs:
                    kwargs['center'] = arg
            else:
                if not 'address' in kwargs:
                    kwargs['address'] = arg
        if 'from' in kwargs and not 'address' in kwargs and not 'center' in kwargs:
            arg = unicode(kwargs['from'])
            if _reCOORDS.match(arg):
                if not 'center' in kwargs:
                    kwargs['center'] = arg
            else:
                if not 'address' in kwargs:
                    kwargs['address'] = arg

        # Check if Google API key is set (if not the Google Map script file
        # wasn't inserted by `post_process_request` and the map wont load)
        if not self.api_key:
            raise TracError(
                "No Google Maps API key given! Tell your web admin to get one at http://code.google.com/apis/maps/signup.html .\n"
            )

        # Use default values if needed
        zoom = None
        size = None
        try:
            if 'zoom' in kwargs:
                zoom = unicode(int(kwargs['zoom']))
            else:
                zoom = unicode(self.default_zoom)
        except:
            raise TracError(
                "Invalid value for zoom given! Please provide an integer from 0 to 19."
            )

        if 'size' in kwargs:
            size = unicode(kwargs['size'])
        else:
            size = unicode(self.default_size)

        # Set target for hyperlinked markers
        target = ""
        if not 'target' in kwargs:
            kwargs['target'] = self.default_target
        if kwargs['target'] in ('new', 'newwindow', '_blank'):
            target = "newwindow"

        # Get height and width
        width = None
        height = None
        try:
            if size.find(':') != -1:
                (width, height) = size.lower().split(':')
                # Check for correct units:
                if    not width[-2:]  in _css_units \
                   or not height[-2:] in _css_units:
                    raise TracError("Wrong unit(s)!")
                # The rest must be a number:
                float(width[:-2])
                float(height[:-2])
            else:
                (width, height) = size.lower().split('x')
                width = str(int(width)) + "px"
                height = str(int(height)) + "px"
        except:
            raise TracError("Invalid value for size given! Please provide "
                            "{width}x{height} in pixels (without unit) or "
                            "{width}{unit}:{height}{unit} in CSS units (%s)." \
                                    % ', '.join(_css_units) )

        # Correct separator for 'center' argument because comma isn't allowed in
        # macro arguments
        center = ""
        if 'center' in kwargs:
            center = unicode(kwargs['center']).replace(':', ',').strip(' "\'')
            if not _reCOORDS.match(center):
                raise TracError("Invalid center coordinates given!")

        # Format address
        address = ""
        if 'address' in kwargs:
            address = self._format_address(kwargs['address'])
            if self.geocoding_server:
                coord = self._get_coords(address)
                center = ",".join(coord[0:2])
                address = ""
                if not 'zoom' in kwargs:
                    zoom = _accuracy_to_zoom[int(coord[2])]

        # Internal formatting functions:
        def gtyp(stype):
            return "G_%s_MAP" % str(stype)

        def gcontrol(control):
            return "map.addControl(new G%sControl());\n" % str(control)

        def gmarker(lat, lng, letter='', link='', title=''):
            if not title:
                title = link
            if not letter:
                letter = ''
            else:
                letter = str(letter).upper()
                if str(letter).startswith('.'):
                    letter = ''
                else:
                    letter = letter[0]
            return "SetMarkerByCoords(map,%s,%s,'%s','%s','%s', '%s');\n" \
                    % (str(lat),str(lng),letter,str(link),str(title),str(target))

        def gmarkeraddr(address, letter='', link='', title=''):
            if not title:
                title = link
            if not letter:
                letter = ''
            else:
                letter = str(letter).upper()
                if str(letter).startswith('.'):
                    letter = ''
                else:
                    letter = letter[0]
            return "SetMarkerByAddress(map,'%s','%s','%s','%s','%s',geocoder);\n" \
                    % (str(address),letter,str(link),str(title),str(target))

        # Set initial map type
        type = 'NORMAL'
        types = []
        types_str = None
        if 'types' in kwargs:
            types = unicode(kwargs['types']).upper().split(':')
            types_str = ','.join(map(gtyp, types))
            type = types[0]

        if 'type' in kwargs:
            type = unicode(kwargs['type']).upper()
            if 'types' in kwargs and not type in types:
                types_str += ',' + type
                types.insert(0, type)
            elif not type in _supported_map_types:
                type = 'NORMAL'
            # if types aren't set and a type is set which is supported
            # but not a default type:
            if not 'types' in kwargs and type in _supported_map_types and not type in _default_map_types:
                # enable type (and all default types):
                types = _default_map_types + [type]
                types_str = ','.join(map(gtyp, types))

        if types_str:
            types_str = '[' + types_str + ']'
        else:
            types_str = 'G_DEFAULT_MAP_TYPES'

        # Produce controls
        control_str = ""
        controls = ['LargeMap', 'MapType']
        if 'controls' in kwargs:
            controls = []
            for control in unicode(kwargs['controls']).upper().split(':'):
                if control in _supported_controls:
                    controls.append(_supported_controls[control])
        controls_str = ''.join(map(gcontrol, controls))

        # Produce markers
        markers_str = ""
        if not 'marker' in kwargs:
            kwargs['marker'] = []
        if 'markers' in kwargs:
            kwargs['marker'].extend(
                parse_args(unicode(kwargs['markers']),
                           delim='|',
                           listonly=True))
        if kwargs['marker']:
            markers = []
            for marker in kwargs['marker']:
                location, letter, link, title = parse_args(marker,
                                                           delim=';',
                                                           listonly=True,
                                                           minlen=4)[:4]
                if not title:
                    title = link

                # Convert wiki to HTML link:
                link = extract_link(self.env, formatter.context, link)
                if isinstance(link, Element):
                    link = link.attrib.get('href')
                else:
                    link = ''

                location = self._format_address(location)
                if _reCOORDS.match(location):
                    coord = location.split(':')
                    markers.append(
                        gmarker(coord[0], coord[1], letter, link, title))
                else:
                    if self.geocoding_server:
                        coord = []
                        if location == 'center':
                            if address:
                                coord = self._get_coords(address)
                            else:
                                coord = center.split(',')
                        else:
                            coord = self._get_coords(location)
                        markers.append(
                            gmarker(coord[0], coord[1], letter, link, title))
                    else:
                        if location == 'center':
                            if address:
                                markers.append(
                                    gmarkeraddr(address, letter, link, title))
                            else:
                                coord = center.split(',')
                                markers.append(
                                    gmarker(coord[0], coord[1], letter, link,
                                            title))
                        else:
                            markers.append(
                                gmarkeraddr(location, letter, link, title))
            markers_str = ''.join(markers)

        # Get macro count from request object
        req = formatter.req
        count = getattr(req, COUNT, 0)
        id = 'tracgooglemap-%s' % count
        setattr(req, COUNT, count + 1)

        # Canvas for this map
        mapdiv = tag.div("Google Map is loading ... (JavaScript enabled?)",
                         id=id,
                         style="width: %s; height: %s;" % (width, height),
                         class_="tracgooglemap")

        if 'from' in kwargs and 'to' in kwargs:
            directions = "from: %s to: %s" % (kwargs['from'], ' to: '.join(
                list(kwargs['to'])))
            mapnmore = tag.table(tag.tr(
                tag.td(
                    tag.div("",
                            class_='tracgooglemap-directions',
                            id='tracgooglemap-directions-%s' % count),
                    style="vertical-align:top;",
                ), tag.td(
                    mapdiv,
                    style="vertical-align:top;",
                )),
                                 class_='tracgooglemaps')

        else:
            directions = ""
            mapnmore = mapdiv

        # put everything in a tidy div
        html = tag.div(
            [
                # Initialization script for this map
                tag.script(Markup(
                    _javascript_code % {
                        'id': id,
                        'center': center,
                        'zoom': zoom,
                        'address': address,
                        'type': type,
                        'width': width,
                        'height': height,
                        'types_str': types_str,
                        'controls_str': controls_str,
                        'markers_str': markers_str,
                        'directions': directions,
                    }),
                           type="text/javascript"),
                mapnmore
            ],
            class_="tracgooglemap-parent")

        return html
Example #27
0
def extract_url (env, context, wikilink, raw=False):
    """
= Description for `extract_url()` =
Extracts an URL from an Wiki link, e.g. to used in macro produced HTML code.

Website: http://trac-hacks.org/wiki/ExtractUrlPlugin

`$Id$`

== Description ==
Returns an (possible relative) URL which can be used in HTML code.

If `raw` is true the returned link will point to a downloadable
version of the linked resource otherwise the same link is returned
which would be used in the resulting Wiki page.

The raw links are also usable as online resouces, e.g. if the link target
is to be used as input for a flash application etc.

== Usage ==
General:
{{{
from tracextracturl import extract_url
# ...
  url = extract_url (env, context, wikilink, raw=False)
}}}

Inside WikiMacros:
{{{
#!python
from tracextracturl import extract_url

def MyMacro(WikiMacroBase):
  def expand_macro (self, formatter, name, content):
     # e.g. wikilink = 'wiki:WikiStart' or 'attachment:file.ext'
     url = extract_url(self.env, formatter.context, wikilink)
     rawurl = extract_url(self.env, formatter.context, wikilink, True)
}}}

== Example ==
Inside a Trac macro called from the wiki page 'ExamplePage' of project
'project1' on a multi-project trac server:
{{{
    extract_url(self.env, formatter, 'attachment:file.js', True)
}}}
will return `/project1/raw-attachment/wiki/ExamplePage/file.js`,
which could be directly accessed by the browser inside some javascript 
or flash HTML object code produced by the macro.
    """
    from genshi.builder import Element, Fragment
    from trac.wiki.formatter import extract_link

    if not wikilink:
        return ''

    link = extract_link(env, context, '[' + wikilink + ' x]')
    #env.log.debug("link = " + str(link.__class__) + ' ' + str(link))

    if isinstance(link, Element):
        href = link.attrib.get('href')
        #env.log.debug("href1 = " + href)
    elif isinstance(link, Fragment):
        link = link.children[0]
        href = link.attrib.get('href')
        #env.log.debug("href2 = " + href)
    else:
        href = None

    if not href:
        return ''

    if raw:
        # rewrite URL to point to downloadable/exportable/raw version of the 
        # linked resource

        # Remove existing project URL part for later string search
        base_path = context.req.base_path
        if base_path and href.startswith(base_path):
            # href relative to base path
            rhref = href[len(base_path):]
        else:
            rhref = href

        # For browser links add the 'format=raw' URL parameter.
        # The alternative '/export' target isn't used because a revision number
        # would be needed.
        if rhref.startswith('/browser/'):
            if rhref.find('?') == -1:
                # If no other parameter exists, simply append:
                href += r'?format=raw'
            else:
                # Otherwise add to existing parameters if this one doesn't
                # exists yet:
                if href.find(r'?format=') == -1 and href.find(r'&format=') == -1:
                    href += r'&format=raw'
        # Change 'attachment' links to 'raw-attachment' links:
        elif rhref.startswith('/attachment/'):
            href = href.replace('/attachment/','/raw-attachment/', 1)
        # All other link types should be already fine for file export (if
        # applicable)
    return href
Example #28
0
    def expand_macro(self, formatter, name, content):
        # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = content.split(',')
        if len(args) == 0:
            raise Exception("No argument.")
        # strip unicode white-spaces and ZWSPs are copied from attachments
        # section (#10668)
        filespec = stripws(args.pop(0))

        # style information
        size_re = re.compile('[0-9]+(%|px)?$')
        attr_re = re.compile('(align|valign|border|width|height|alt'
                             '|margin(?:-(?:left|right|top|bottom))?'
                             '|title|longdesc|class|id|usemap)=(.+)')
        quoted_re = re.compile("(?:[\"'])(.*)(?:[\"'])$")
        attr = {}
        style = {}
        link = ''
        # helper for the special case `source:`
        #
        from trac.versioncontrol.web_ui import BrowserModule
        # FIXME: somehow use ResourceSystem.get_known_realms()
        #        ... or directly trac.wiki.extract_link
        try:
            browser_links = [
                res[0] for res in BrowserModule(self.env).get_link_resolvers()
            ]
        except Exception:
            browser_links = []
        while args:
            arg = stripws(args.pop(0))
            if size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
            elif arg == 'nolink':
                link = None
            elif arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                elt = find_element(elt, 'href')
                link = None
                if elt is not None:
                    link = elt.attrib.get('href')
            elif arg in ('left', 'right'):
                style['float'] = arg
            elif arg == 'center':
                style['margin-left'] = style['margin-right'] = 'auto'
                style['display'] = 'block'
                style.pop('margin', '')
            elif arg in ('top', 'bottom', 'middle'):
                style['vertical-align'] = arg
            else:
                match = attr_re.match(arg)
                if match:
                    key, val = match.groups()
                    if (key == 'align' and
                            val in ('left', 'right', 'center')) or \
                        (key == 'valign' and \
                            val in ('top', 'middle', 'bottom')):
                        args.append(val)
                    elif key in ('margin-top', 'margin-bottom'):
                        style[key] = ' %dpx' % int(val)
                    elif key in ('margin', 'margin-left', 'margin-right') \
                             and 'display' not in style:
                        style[key] = ' %dpx' % int(val)
                    elif key == 'border':
                        style['border'] = ' %dpx solid' % int(val)
                    else:
                        m = quoted_re.search(val)  # unquote "..." and '...'
                        if m:
                            val = m.group(1)
                        attr[str(key)] = val  # will be used as a __call__ kwd

        # parse filespec argument to get realm and id if contained.
        parts = [
            i.strip('''['"]''')
            for i in self._split_filespec_re.split(filespec)
        ]
        url = raw_url = desc = None
        attachment = None
        if (parts and parts[0] in ('http', 'https', 'ftp')):  # absolute
            raw_url = url = filespec
            desc = url.rsplit('?')[0]
        elif filespec.startswith('//'):  # server-relative
            raw_url = url = filespec[1:]
            desc = url.rsplit('?')[0]
        elif filespec.startswith('/'):  # project-relative
            params = ''
            if '?' in filespec:
                filespec, params = filespec.rsplit('?', 1)
            url = formatter.href(filespec)
            if params:
                url += '?' + params
            raw_url, desc = url, filespec
        elif len(parts) == 3:  # realm:id:attachment-filename
            #                                 # or intertrac:realm:id
            realm, id, filename = parts
            intertrac_target = "%s:%s" % (id, filename)
            it = formatter.get_intertrac_url(realm, intertrac_target)
            if it:
                url, desc = it
                raw_url = url + unicode_quote('?format=raw')
            else:
                attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            realm, filename = parts
            if realm in browser_links:  # source:path
                # TODO: use context here as well
                rev = None
                if '@' in filename:
                    filename, rev = filename.rsplit('@', 1)
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename,
                                                 rev=rev,
                                                 format='raw')
                desc = filespec
            else:  # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                elif id == 'shared':
                    raw_url = url = formatter.href.chrome('shared', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm,
                                          id).child('attachment', filename)
        elif len(parts) == 1:  # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            raise TracError('No filespec given')
        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            raw_url = get_resource_url(self.env,
                                       attachment,
                                       formatter.href,
                                       format='raw')
            try:
                desc = get_resource_summary(self.env, attachment)
            except ResourceNotFound as e:
                raw_url = formatter.href.chrome('common/attachment.png')
                desc = _('No image "%(id)s" attached to %(parent)s',
                         id=attachment.id,
                         parent=get_resource_name(self.env, attachment.parent))
        for key in ('title', 'alt'):
            if desc and not key in attr:
                attr[key] = desc
        if style:
            attr['style'] = '; '.join('%s:%s' % (k, escape(v))
                                      for k, v in style.iteritems())
        result = tag.img(src=raw_url, **attr)
        if link is not None:
            result = tag.a(result,
                           href=link or url,
                           style='padding:0; border:none')
        return result
Example #29
0
    def expand_macro(self, formatter, name, content, args=None):
        content = content.replace('\n',',')
        largs, kwargs = parse_args(content, multi=['marker','to'])
        if len(largs) > 0:
            arg = unicode(largs[0])
            if _reCOORDS.match(arg):
                if not 'center' in kwargs:
                    kwargs['center'] = arg
            else:
                if not 'address' in kwargs:
                    kwargs['address'] = arg
        if 'from' in kwargs and not 'address' in kwargs and not 'center' in kwargs:
            arg = unicode(kwargs['from'])
            if _reCOORDS.match(arg):
                if not 'center' in kwargs:
                    kwargs['center'] = arg
            else:
                if not 'address' in kwargs:
                    kwargs['address'] = arg

        # Check if Google API key is set (if not the Google Map script file
        # wasn't inserted by `post_process_request` and the map wont load)
        if not self.api_key:
            raise TracError("No Google Maps API key given! Tell your web admin to get one at http://code.google.com/apis/maps/signup.html .\n")

        # Use default values if needed
        zoom = None
        size = None
        try:
            if 'zoom' in kwargs:
                zoom = unicode( int( kwargs['zoom'] ) )
            else:
                zoom = unicode( self.default_zoom )
        except:
            raise TracError("Invalid value for zoom given! Please provide an integer from 0 to 19.")

        if 'size' in kwargs:
            size = unicode( kwargs['size'] )
        else:
            size = unicode( self.default_size )

        # Set target for hyperlinked markers
        target = ""
        if not 'target' in kwargs:
            kwargs['target'] = self.default_target
        if kwargs['target'] in ('new','newwindow','_blank'):
            target = "newwindow"

        # Get height and width
        width  = None
        height = None
        try:
            if size.find(':') != -1:
                (width,height) = size.lower().split(':')
                # Check for correct units:
                if    not width[-2:]  in _css_units \
                   or not height[-2:] in _css_units:
                       raise TracError("Wrong unit(s)!")
                # The rest must be a number:
                float( width[:-2]  )
                float( height[:-2] )
            else:
                (width,height) = size.lower().split('x')
                width  = str( int( width  ) ) + "px"
                height = str( int( height ) ) + "px"
        except:
            raise TracError("Invalid value for size given! Please provide "
                            "{width}x{height} in pixels (without unit) or "
                            "{width}{unit}:{height}{unit} in CSS units (%s)." \
                                    % ', '.join(_css_units) )


        # Correct separator for 'center' argument because comma isn't allowed in
        # macro arguments
        center = ""
        if 'center' in kwargs:
            center = unicode(kwargs['center']).replace(':',',').strip(' "\'')
            if not _reCOORDS.match(center):
                raise TracError("Invalid center coordinates given!")

        # Format address
        address = ""
        if 'address' in kwargs:
            address = self._format_address(kwargs['address'])
            if self.geocoding_server:
                coord = self._get_coords(address)
                center = ",".join(coord[0:2])
                address = ""
                if not 'zoom' in kwargs:
                    zoom = _accuracy_to_zoom[ int( coord[2] ) ]

        # Internal formatting functions:
        def gtyp (stype):
            return "G_%s_MAP" % str(stype)
        def gcontrol (control):
            return "map.addControl(new G%sControl());\n" % str(control)
        def gmarker (lat,lng,letter='',link='',title=''):
            if not title:
                title = link
            if not letter:
                letter = ''
            else:
                letter = str(letter).upper()
                if str(letter).startswith('.'):
                    letter = ''
                else:
                    letter = letter[0]
            return "SetMarkerByCoords(map,%s,%s,'%s','%s','%s', '%s');\n" \
                    % (str(lat),str(lng),letter,str(link),str(title),str(target))
        def gmarkeraddr (address,letter='',link='',title=''):
            if not title:
                title = link
            if not letter:
                letter = ''
            else:
                letter = str(letter).upper()
                if str(letter).startswith('.'):
                    letter = ''
                else:
                    letter = letter[0]
            return "SetMarkerByAddress(map,'%s','%s','%s','%s','%s',geocoder);\n" \
                    % (str(address),letter,str(link),str(title),str(target))

        # Set initial map type
        type = 'NORMAL'
        types = []
        types_str = None
        if 'types' in kwargs:
            types = unicode(kwargs['types']).upper().split(':')
            types_str = ','.join(map(gtyp,types))
            type = types[0]

        if 'type' in kwargs:
            type = unicode(kwargs['type']).upper()
            if 'types' in kwargs and not type in types:
                types_str += ',' + type
                types.insert(0, type)
            elif not type in _supported_map_types:
                type = 'NORMAL'
            # if types aren't set and a type is set which is supported 
            # but not a default type:
            if not 'types' in kwargs and type in _supported_map_types and not type in _default_map_types:
                   # enable type (and all default types):
                   types = _default_map_types + [type]
                   types_str = ','.join(map(gtyp,types))

        if types_str:
            types_str = '[' + types_str + ']'
        else:
            types_str = 'G_DEFAULT_MAP_TYPES'

        # Produce controls
        control_str = ""
        controls = ['LargeMap','MapType']
        if 'controls' in kwargs:
            controls = []
            for control in unicode(kwargs['controls']).upper().split(':'):
                if control in _supported_controls:
                    controls.append( _supported_controls[control] )
        controls_str = ''.join(map(gcontrol,controls))

        # Produce markers
        markers_str = ""
        if not 'marker' in kwargs:
            kwargs['marker'] = []
        if 'markers' in kwargs:
            kwargs['marker'].extend( parse_args( unicode(kwargs['markers']), delim='|',
                                      listonly=True) )
        if kwargs['marker']:
            markers = []
            for marker in kwargs['marker']:
                location, letter, link, title = parse_args( marker,
                        delim=';', listonly=True, minlen=4 )[:4]
                if not title:
                    title = link

                # Convert wiki to HTML link:
                link = extract_link(self.env, formatter.context, link)
                if isinstance(link, Element):
                    link = link.attrib.get('href')
                else:
                    link = ''

                location = self._format_address(location)
                if _reCOORDS.match(location):
                    coord = location.split(':')
                    markers.append( gmarker( coord[0], coord[1], letter, link, title ) )
                else:
                    if self.geocoding_server:
                        coord = []
                        if location == 'center':
                            if address:
                                coord = self._get_coords(address)
                            else:
                                coord = center.split(',')
                        else:
                            coord = self._get_coords(location)
                        markers.append( gmarker( coord[0], coord[1], letter, link, title ) )
                    else:
                        if location == 'center':
                            if address:
                                markers.append( gmarkeraddr( address, letter, link, title ) )
                            else:
                                coord = center.split(',')
                                markers.append( gmarker( coord[0], coord[1], letter, link, title ) )
                        else:
                            markers.append( gmarkeraddr( location, letter, link, title) )
            markers_str = ''.join( markers )

        # Get macro count from request object
        req = formatter.req
        count = getattr (req, COUNT, 0)
        id = 'tracgooglemap-%s' % count
        setattr (req, COUNT, count + 1)

        # Canvas for this map
        mapdiv = tag.div (
                    "Google Map is loading ... (JavaScript enabled?)",
                    id=id,
                    style = "width: %s; height: %s;" % (width,height),
                    class_ = "tracgooglemap"
                )

        if 'from' in kwargs and 'to' in kwargs:
            directions = "from: %s to: %s" % (kwargs['from'],' to: '.join(list(kwargs['to'])))
            mapnmore = tag.table(
                            tag.tr(
                                tag.td(
                                    tag.div( "", 
                                        class_ = 'tracgooglemap-directions',
                                        id     = 'tracgooglemap-directions-%s' % count
                                    ),
                                    style="vertical-align:top;",
                                ),
                                tag.td(
                                    mapdiv,
                                    style="vertical-align:top;",
                                )
                            ),
                          class_ = 'tracgooglemaps'
                       )

        else:
            directions = ""
            mapnmore = mapdiv

        # put everything in a tidy div
        html = tag.div(
                [
                    # Initialization script for this map
                    tag.script ( Markup( _javascript_code % { 'id':id,
                        'center':center,
                        'zoom':zoom, 'address':address,
                        'type':type, 'width':width, 'height':height,
                        'types_str':types_str, 'controls_str':controls_str,
                        'markers_str':markers_str, 'directions':directions,
                        } ),
                        type = "text/javascript"),
                    mapnmore
                    ],
                class_ = "tracgooglemap-parent"
                );

        return html;
Example #30
0
    def expand_macro(self, formatter, name, content):
        # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = [stripws(arg) for arg
                             in self._split_args_re.split(content)[1::2]]
        # strip unicode white-spaces and ZWSPs are copied from attachments
        # section (#10668)
        filespec = args.pop(0)

        # style information
        attr = {}
        style = {}
        link = ''
        # helper for the special case `source:`
        #
        from trac.versioncontrol.web_ui import BrowserModule
        # FIXME: somehow use ResourceSystem.get_known_realms()
        #        ... or directly trac.wiki.extract_link
        try:
            browser_links = [res[0] for res in
                             BrowserModule(self.env).get_link_resolvers()]
        except Exception:
            browser_links = []
        while args:
            arg = args.pop(0)
            if self._size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
            elif arg == 'nolink':
                link = None
            elif arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                elt = find_element(elt, 'href')
                link = None
                if elt is not None:
                    link = elt.attrib.get('href')
            elif arg in ('left', 'right'):
                style['float'] = arg
            elif arg == 'center':
                style['margin-left'] = style['margin-right'] = 'auto'
                style['display'] = 'block'
                style.pop('margin', '')
            elif arg in ('top', 'bottom', 'middle'):
                style['vertical-align'] = arg
            else:
                match = self._attr_re.match(arg)
                if match:
                    key, val = match.groups()
                    if (key == 'align' and
                            val in ('left', 'right', 'center')) or \
                        (key == 'valign' and
                            val in ('top', 'middle', 'bottom')):
                        args.append(val)
                    elif key in ('margin-top', 'margin-bottom'):
                        style[key] = ' %dpx' % int(val)
                    elif key in ('margin', 'margin-left', 'margin-right') \
                             and 'display' not in style:
                        style[key] = ' %dpx' % int(val)
                    elif key == 'border':
                        style['border'] = ' %dpx solid' % int(val)
                    else:
                        m = self._quoted_re.search(val)  # unquote "..." and '...'
                        if m:
                            val = m.group(1)
                        attr[str(key)] = val  # will be used as a __call__ kwd

        if self._quoted_re.match(filespec):
            filespec = filespec.strip('\'"')
        # parse filespec argument to get realm and id if contained.
        parts = [i.strip('''['"]''')
                 for i in self._split_filespec_re.split(filespec)[1::2]]
        url = raw_url = desc = None
        attachment = None
        if parts and parts[0] in ('http', 'https', 'ftp', 'data'):  # absolute
            raw_url = url = filespec
            desc = url.rsplit('?')[0]
        elif filespec.startswith('//'):       # server-relative
            raw_url = url = filespec[1:]
            desc = url.rsplit('?')[0]
        elif filespec.startswith('/'):        # project-relative
            params = ''
            if '?' in filespec:
                filespec, params = filespec.rsplit('?', 1)
            url = formatter.href(filespec)
            if params:
                url += '?' + params
            raw_url, desc = url, filespec
        elif len(parts) == 3:                 # realm:id:attachment-filename
            #                                 # or intertrac:realm:id
            realm, id, filename = parts
            intertrac_target = "%s:%s" % (id, filename)
            it = formatter.get_intertrac_url(realm, intertrac_target)
            if it:
                url, desc = it
                raw_url = url + unicode_quote('?format=raw')
            else:
                attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            realm, filename = parts
            if realm in browser_links:  # source:path
                # TODO: use context here as well
                rev = None
                if '@' in filename:
                    filename, rev = filename.rsplit('@', 1)
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename, rev=rev,
                                                 format='raw')
                desc = filespec
            else:  # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                elif id == 'shared':
                    raw_url = url = formatter.href.chrome('shared', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm, id).child('attachment',
                                                           filename)
        elif len(parts) == 1:  # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            raise TracError(_("No filespec given"))
        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            raw_url = get_resource_url(self.env, attachment, formatter.href,
                                       format='raw')
            try:
                desc = get_resource_summary(self.env, attachment)
            except ResourceNotFound:
                raw_url = chrome_resource_path(formatter.context.req,
                                               'common/attachment.png')
                desc = _('No image "%(id)s" attached to %(parent)s',
                         id=attachment.id,
                         parent=get_resource_name(self.env, attachment.parent))
        for key in ('title', 'alt'):
            if desc and key not in attr:
                attr[key] = desc
        if style:
            attr['style'] = '; '.join('%s:%s' % (k, escape(v))
                                      for k, v in style.iteritems())
        result = tag.img(src=raw_url, **attr)
        if link is not None:
            result = tag.a(result, href=link or url,
                           style='padding:0; border:none')
        return result
Example #31
0
    def expand_macro(self, formatter, name, content):
        # args will be null if the macro is called without parenthesis.
        if not content:
            return ''
        # parse arguments
        # we expect the 1st argument to be a filename (filespec)
        args = content.split(',')
        if len(args) == 0:
            raise Exception("No argument.")
        # strip unicode white-spaces and ZWSPs are copied from attachments
        # section (#10668)
        filespec = stripws(args.pop(0))

        # style information
        size_re = re.compile('[0-9]+(%|px)?$')
        attr_re = re.compile('(align|valign|border|width|height|alt'
                             '|margin(?:-(?:left|right|top|bottom))?'
                             '|title|longdesc|class|id|usemap)=(.+)')
        quoted_re = re.compile("(?:[\"'])(.*)(?:[\"'])$")
        attr = {}
        style = {}
        link = ''
        # helper for the special case `source:`
        #
        from trac.versioncontrol.web_ui import BrowserModule
        # FIXME: somehow use ResourceSystem.get_known_realms()
        #        ... or directly trac.wiki.extract_link
        try:
            browser_links = [res[0] for res in
                             BrowserModule(self.env).get_link_resolvers()]
        except Exception:
            browser_links = []
        while args:
            arg = args.pop(0).strip()
            if size_re.match(arg):
                # 'width' keyword
                attr['width'] = arg
            elif arg == 'nolink':
                link = None
            elif arg.startswith('link='):
                val = arg.split('=', 1)[1]
                elt = extract_link(self.env, formatter.context, val.strip())
                elt = find_element(elt, 'href')
                link = None
                if elt is not None:
                    link = elt.attrib.get('href')
            elif arg in ('left', 'right'):
                style['float'] = arg
            elif arg == 'center':
                style['margin-left'] = style['margin-right'] = 'auto'
                style['display'] = 'block'
                style.pop('margin', '')
            elif arg in ('top', 'bottom', 'middle'):
                style['vertical-align'] = arg
            else:
                match = attr_re.match(arg)
                if match:
                    key, val = match.groups()
                    if (key == 'align' and
                            val in ('left', 'right', 'center')) or \
                        (key == 'valign' and \
                            val in ('top', 'middle', 'bottom')):
                        args.append(val)
                    elif key in ('margin-top', 'margin-bottom'):
                        style[key] = ' %dpx' % int(val)
                    elif key in ('margin', 'margin-left', 'margin-right') \
                             and 'display' not in style:
                        style[key] = ' %dpx' % int(val)
                    elif key == 'border':
                        style['border'] = ' %dpx solid' % int(val)
                    else:
                        m = quoted_re.search(val) # unquote "..." and '...'
                        if m:
                            val = m.group(1)
                        attr[str(key)] = val # will be used as a __call__ kwd

        # parse filespec argument to get realm and id if contained.
        parts = filespec.split(':')
        url = raw_url = desc = None
        attachment = None
        if (parts and parts[0] in ('http', 'https', 'ftp')): # absolute
            raw_url = url = filespec
            desc = url.rsplit('?')[0]
        elif filespec.startswith('//'):       # server-relative
            raw_url = url = filespec[1:]
            desc = url.rsplit('?')[0]
        elif filespec.startswith('/'):        # project-relative
            params = ''
            if '?' in filespec:
                filespec, params = filespec.rsplit('?', 1)
            url = formatter.href(filespec)
            if params:
                url += '?' + params
            raw_url, desc = url, filespec
        elif len(parts) == 3:                 # realm:id:attachment-filename
            #                                 # or intertrac:realm:id
            realm, id, filename = parts
            intertrac_target = "%s:%s" % (id, filename)
            it = formatter.get_intertrac_url(realm, intertrac_target)
            if it:
                url, desc = it
                raw_url = url + unicode_quote('?format=raw')
            else:
                attachment = Resource(realm, id).child('attachment', filename)
        elif len(parts) == 2:
            realm, filename = parts
            if realm in browser_links:   # source:path
                # TODO: use context here as well
                rev = None
                if '@' in filename:
                    filename, rev = filename.rsplit('@', 1)
                url = formatter.href.browser(filename, rev=rev)
                raw_url = formatter.href.browser(filename, rev=rev,
                                                 format='raw')
                desc = filespec
            else: # #ticket:attachment or WikiPage:attachment
                # FIXME: do something generic about shorthand forms...
                realm = None
                id, filename = parts
                if id and id[0] == '#':
                    realm = 'ticket'
                    id = id[1:]
                elif id == 'htdocs':
                    raw_url = url = formatter.href.chrome('site', filename)
                    desc = os.path.basename(filename)
                else:
                    realm = 'wiki'
                if realm:
                    attachment = Resource(realm, id).child('attachment',
                                                           filename)
        elif len(parts) == 1: # it's an attachment of the current resource
            attachment = formatter.resource.child('attachment', filespec)
        else:
            raise TracError('No filespec given')
        if attachment and 'ATTACHMENT_VIEW' in formatter.perm(attachment):
            url = get_resource_url(self.env, attachment, formatter.href)
            raw_url = get_resource_url(self.env, attachment, formatter.href,
                                       format='raw')
            try:
                desc = get_resource_summary(self.env, attachment)
            except ResourceNotFound, e:
                raw_url = formatter.href.chrome('common/attachment.png')
                desc = _('No image "%(id)s" attached to %(parent)s',
                         id=attachment.id,
                         parent=get_resource_name(self.env, attachment.parent))
Example #32
0
def get_absolute_url(url, formatter=None, base=None):
    """ Generate an absolute url from the url with the special schemes
        {htdocs,chrome,ticket,wiki,source} simply return the url if given with
        {http,https,ftp} schemes. Also supports TracLinks.
        
        Examples:
            http://example.com/filename.ext
                ie. http://www.google.com/logo.jpg
            
            htdocs://site/filename.ext
            htdocs://plugin/dir/filename.ext
                note: `chrome` is an alias for `htdocs`
            
            ticket://number/attachment.pdf
                ie. ticket://123/specification.pdf
            
            wiki://WikiWord/attachment.jpg
            
            source://changeset/path/filename.ext
                ie. source://1024/trunk/docs/README
    """
    def ujoin(*parts):
        """ Remove double slashes.
        """
        parts = [part.strip('/') for part in parts]
        return '/' + '/'.join(parts)
    
    # You must supply a formatter or a base.
    if not base:
        base = formatter.href.base
    
    if url.find('://') > 0:
        scheme, netloc, path, query, params, fragment = urlparse.urlparse(url)
        
        if scheme in ('ftp', 'http', 'https'):
            return url
        
        if scheme in ('htdocs', 'chrome'):
            return ujoin(base, 'chrome', path)
        
        if scheme in ('source',):
            return ujoin(base, 'export', path)
        
        if scheme in ('ticket',):
            return ujoin(base, 'raw-attachment/ticket', path)
        
        if scheme in ('wiki',):
            return ujoin(base, 'raw-attachment/wiki', path)
        
        return url
    
    # You'll need a formatter for this, code from #3938, serious testing needed.
    else:
        link = extract_link(formatter.env, formatter.context, url)
        
        if isinstance(link, Element):
            url = link.attrib.get('href')
            
            scheme, netloc, path, query, params, fragment = urlparse.urlparse(url)
            if path.startswith('/browser/'):
                query_dict = xform_query(query)
                query_dict['format'] = 'raw'
                query = xfrom_query(query_dict)
                url = urlparse.urlunparse((scheme, netloc, path, query, params, fragment))
            
            elif path.startswith('/attachement/'):
                url = url.replace('/attachment/', '/raw-attachment/', 1)
            
            return url