mercurial/hgweb/hgweb_mod.py
changeset 5596 20b07b68a865
parent 5595 b95b2525c6e8
child 5597 e7f99a3ed008
equal deleted inserted replaced
5595:b95b2525c6e8 5596:20b07b68a865
   116         req = wsgirequest(env, respond)
   116         req = wsgirequest(env, respond)
   117         self.run_wsgi(req)
   117         self.run_wsgi(req)
   118         return req
   118         return req
   119 
   119 
   120     def run_wsgi(self, req):
   120     def run_wsgi(self, req):
   121         def header(**map):
   121 
   122             header_file = cStringIO.StringIO(
   122         self.refresh()
   123                 ''.join(self.t("header", encoding=self.encoding, **map)))
   123 
   124             msg = mimetools.Message(header_file, 0)
   124         # expand form shortcuts
   125             req.header(msg.items())
   125 
   126             yield header_file.read()
   126         shortcuts = {
   127 
   127             'cl': [('cmd', ['changelog']), ('rev', None)],
   128         def rawfileheader(**map):
   128             'sl': [('cmd', ['shortlog']), ('rev', None)],
   129             req.header([('Content-type', map['mimetype']),
   129             'cs': [('cmd', ['changeset']), ('node', None)],
   130                         ('Content-disposition', 'filename=%s' % map['file']),
   130             'f': [('cmd', ['file']), ('filenode', None)],
   131                         ('Content-length', str(len(map['raw'])))])
   131             'fl': [('cmd', ['filelog']), ('filenode', None)],
   132             yield ''
   132             'fd': [('cmd', ['filediff']), ('node', None)],
   133 
   133             'fa': [('cmd', ['annotate']), ('filenode', None)],
   134         def footer(**map):
   134             'mf': [('cmd', ['manifest']), ('manifest', None)],
   135             yield self.t("footer", **map)
   135             'ca': [('cmd', ['archive']), ('node', None)],
   136 
   136             'tags': [('cmd', ['tags'])],
   137         def motd(**map):
   137             'tip': [('cmd', ['changeset']), ('node', ['tip'])],
   138             yield self.config("web", "motd", "")
   138             'static': [('cmd', ['static']), ('file', None)]
   139 
   139         }
   140         def expand_form(form):
   140 
   141             shortcuts = {
   141         for k in shortcuts.iterkeys():
   142                 'cl': [('cmd', ['changelog']), ('rev', None)],
   142             if k in req.form:
   143                 'sl': [('cmd', ['shortlog']), ('rev', None)],
   143                 for name, value in shortcuts[k]:
   144                 'cs': [('cmd', ['changeset']), ('node', None)],
   144                     if value is None:
   145                 'f': [('cmd', ['file']), ('filenode', None)],
   145                         value = req.form[k]
   146                 'fl': [('cmd', ['filelog']), ('filenode', None)],
   146                     req.form[name] = value
   147                 'fd': [('cmd', ['filediff']), ('node', None)],
   147                 del req.form[k]
   148                 'fa': [('cmd', ['annotate']), ('filenode', None)],
   148 
   149                 'mf': [('cmd', ['manifest']), ('manifest', None)],
   149         # work with CGI variables to create coherent structure
   150                 'ca': [('cmd', ['archive']), ('node', None)],
   150         # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME
   151                 'tags': [('cmd', ['tags'])],
   151 
   152                 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
   152         req.url = req.env['SCRIPT_NAME']
   153                 'static': [('cmd', ['static']), ('file', None)]
   153         if not req.url.endswith('/'):
   154             }
   154             req.url += '/'
   155 
   155         if req.env.has_key('REPO_NAME'):
   156             for k in shortcuts.iterkeys():
   156             req.url += req.env['REPO_NAME'] + '/'
   157                 if form.has_key(k):
   157 
   158                     for name, value in shortcuts[k]:
   158         if req.env.get('PATH_INFO'):
   159                         if value is None:
   159             parts = req.env.get('PATH_INFO').strip('/').split('/')
   160                             value = form[k]
   160             repo_parts = req.env.get('REPO_NAME', '').split('/')
   161                         form[name] = value
   161             if parts[:len(repo_parts)] == repo_parts:
   162                     del form[k]
   162                 parts = parts[len(repo_parts):]
   163 
   163             query = '/'.join(parts)
   164         def rewrite_request(req):
   164         else:
   165             '''translate new web interface to traditional format'''
   165             query = req.env['QUERY_STRING'].split('&', 1)[0]
   166 
   166             query = query.split(';', 1)[0]
   167             req.url = req.env['SCRIPT_NAME']
   167 
   168             if not req.url.endswith('/'):
   168         # translate user-visible url structure to internal structure
   169                 req.url += '/'
   169 
   170             if req.env.has_key('REPO_NAME'):
   170         args = query.split('/', 2)
   171                 req.url += req.env['REPO_NAME'] + '/'
   171         if 'cmd' not in req.form and args and args[0]:
   172             
       
   173             if req.env.get('PATH_INFO'):
       
   174                 parts = req.env.get('PATH_INFO').strip('/').split('/')
       
   175                 repo_parts = req.env.get('REPO_NAME', '').split('/')
       
   176                 if parts[:len(repo_parts)] == repo_parts:
       
   177                     parts = parts[len(repo_parts):]
       
   178                 query = '/'.join(parts)
       
   179             else:
       
   180                 query = req.env['QUERY_STRING'].split('&', 1)[0]
       
   181                 query = query.split(';', 1)[0]
       
   182 
       
   183             if req.form.has_key('cmd'):
       
   184                 # old style
       
   185                 return
       
   186 
       
   187             args = query.split('/', 2)
       
   188             if not args or not args[0]:
       
   189                 return
       
   190 
   172 
   191             cmd = args.pop(0)
   173             cmd = args.pop(0)
   192             style = cmd.rfind('-')
   174             style = cmd.rfind('-')
   193             if style != -1:
   175             if style != -1:
   194                 req.form['style'] = [cmd[:style]]
   176                 req.form['style'] = [cmd[:style]]
   195                 cmd = cmd[style+1:]
   177                 cmd = cmd[style+1:]
       
   178 
   196             # avoid accepting e.g. style parameter as command
   179             # avoid accepting e.g. style parameter as command
   197             if hasattr(webcommands, cmd):
   180             if hasattr(webcommands, cmd):
   198                 req.form['cmd'] = [cmd]
   181                 req.form['cmd'] = [cmd]
   199 
   182 
   200             if args and args[0]:
   183             if args and args[0]:
   211                     ext = spec[2]
   194                     ext = spec[2]
   212                     if fn.endswith(ext):
   195                     if fn.endswith(ext):
   213                         req.form['node'] = [fn[:-len(ext)]]
   196                         req.form['node'] = [fn[:-len(ext)]]
   214                         req.form['type'] = [type_]
   197                         req.form['type'] = [type_]
   215 
   198 
   216         def sessionvars(**map):
   199         # determine scheme, port and server name
   217             fields = []
   200         # this is needed to create absolute urls
   218             if req.form.has_key('style'):
       
   219                 style = req.form['style'][0]
       
   220                 if style != self.config('web', 'style', ''):
       
   221                     fields.append(('style', style))
       
   222 
       
   223             separator = req.url[-1] == '?' and ';' or '?'
       
   224             for name, value in fields:
       
   225                 yield dict(name=name, value=value, separator=separator)
       
   226                 separator = ';'
       
   227 
       
   228         self.refresh()
       
   229 
       
   230         expand_form(req.form)
       
   231         rewrite_request(req)
       
   232 
       
   233         style = self.config("web", "style", "")
       
   234         if req.form.has_key('style'):
       
   235             style = req.form['style'][0]
       
   236         mapfile = style_map(self.templatepath, style)
       
   237 
   201 
   238         proto = req.env.get('wsgi.url_scheme')
   202         proto = req.env.get('wsgi.url_scheme')
   239         if proto == 'https':
   203         if proto == 'https':
   240             proto = 'https'
   204             proto = 'https'
   241             default_port = "443"
   205             default_port = "443"
   247         port = port != default_port and (":" + port) or ""
   211         port = port != default_port and (":" + port) or ""
   248         urlbase = '%s://%s%s' % (proto, req.env['SERVER_NAME'], port)
   212         urlbase = '%s://%s%s' % (proto, req.env['SERVER_NAME'], port)
   249         staticurl = self.config("web", "staticurl") or req.url + 'static/'
   213         staticurl = self.config("web", "staticurl") or req.url + 'static/'
   250         if not staticurl.endswith('/'):
   214         if not staticurl.endswith('/'):
   251             staticurl += '/'
   215             staticurl += '/'
       
   216 
       
   217         # some functions for the templater
       
   218 
       
   219         def header(**map):
       
   220             header_file = cStringIO.StringIO(
       
   221                 ''.join(self.t("header", encoding=self.encoding, **map)))
       
   222             msg = mimetools.Message(header_file, 0)
       
   223             req.header(msg.items())
       
   224             yield header_file.read()
       
   225 
       
   226         def rawfileheader(**map):
       
   227             req.header([('Content-type', map['mimetype']),
       
   228                         ('Content-disposition', 'filename=%s' % map['file']),
       
   229                         ('Content-length', str(len(map['raw'])))])
       
   230             yield ''
       
   231 
       
   232         def footer(**map):
       
   233             yield self.t("footer", **map)
       
   234 
       
   235         def motd(**map):
       
   236             yield self.config("web", "motd", "")
       
   237 
       
   238         def sessionvars(**map):
       
   239             fields = []
       
   240             if req.form.has_key('style'):
       
   241                 style = req.form['style'][0]
       
   242                 if style != self.config('web', 'style', ''):
       
   243                     fields.append(('style', style))
       
   244 
       
   245             separator = req.url[-1] == '?' and ';' or '?'
       
   246             for name, value in fields:
       
   247                 yield dict(name=name, value=value, separator=separator)
       
   248                 separator = ';'
       
   249 
       
   250         style = self.config("web", "style", "")
       
   251         if req.form.has_key('style'):
       
   252             style = req.form['style'][0]
       
   253         mapfile = style_map(self.templatepath, style)
   252 
   254 
   253         if not self.reponame:
   255         if not self.reponame:
   254             self.reponame = (self.config("web", "name")
   256             self.reponame = (self.config("web", "name")
   255                              or req.env.get('REPO_NAME')
   257                              or req.env.get('REPO_NAME')
   256                              or req.url.strip('/') or self.repo.root)
   258                              or req.url.strip('/') or self.repo.root)