1
0
mirror of https://github.com/vitalif/viewvc-4intranet synced 2019-04-16 04:14:59 +03:00

Compare commits

..

2 Commits
1.1.5 ... 1.1.4

Author SHA1 Message Date
cmpilato
b97d2d49fa Retroactively "peg" the svn:externals property on these tags which
pulls in the 'templates-contrib' area.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/tags/1.1.4@2451 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-08 16:51:21 +00:00
cmpilato
3f43d12ee4 Tag the 1.1.4 final release.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/tags/1.1.4@2333 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-03-10 21:25:25 +00:00
7 changed files with 54 additions and 56 deletions

View File

@@ -1,7 +1,3 @@
Version 1.1.5 (released 29-Mar-2010)
* security fix: escape user-provided search_re input to avoid XSS attack
Version 1.1.4 (released 10-Mar-2010) Version 1.1.4 (released 10-Mar-2010)
* security fix: escape user-provided query form input to avoid XSS attack * security fix: escape user-provided query form input to avoid XSS attack

View File

@@ -15,7 +15,7 @@
<blockquote> <blockquote>
<p><strong>Copyright &copy; 1999-2010 The ViewCVS Group. All rights <p><strong>Copyright &copy; 1999-2009 The ViewCVS Group. All rights
reserved.</strong></p> reserved.</strong></p>
<p>By using ViewVC, you agree to the terms and conditions set forth <p>By using ViewVC, you agree to the terms and conditions set forth
@@ -60,7 +60,6 @@
<li>April 10, 2007 &mdash; copyright years updated</li> <li>April 10, 2007 &mdash; copyright years updated</li>
<li>February 22, 2008 &mdash; copyright years updated</li> <li>February 22, 2008 &mdash; copyright years updated</li>
<li>March 18, 2009 &mdash; copyright years updated</li> <li>March 18, 2009 &mdash; copyright years updated</li>
<li>March 29, 2010 &mdash; copyright years updated</li>
</ul> </ul>
</body> </body>

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*-python-*- # -*-python-*-
# #
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved. # Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org> # Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
# #
# By using this file, you agree to the terms and conditions set forth in # By using this file, you agree to the terms and conditions set forth in
@@ -32,8 +32,9 @@ import os
import re import re
import time import time
import math import math
import cgi
import vclib import vclib
import sapi
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"') re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
@@ -81,7 +82,7 @@ class HTMLBlameSource:
diff_url = None diff_url = None
if item.prev_rev: if item.prev_rev:
diff_url = '%sr1=%s&amp;r2=%s' % (self.diff_url, item.prev_rev, item.rev) diff_url = '%sr1=%s&amp;r2=%s' % (self.diff_url, item.prev_rev, item.rev)
thisline = link_includes(sapi.escape(item.text), self.repos, thisline = link_includes(cgi.escape(item.text), self.repos,
self.path_parts, self.include_url) self.path_parts, self.include_url)
return _item(text=thisline, line_number=item.line_number, return _item(text=thisline, line_number=item.line_number,
rev=item.rev, prev_rev=item.prev_rev, rev=item.rev, prev_rev=item.prev_rev,

View File

@@ -1,6 +1,6 @@
# -*-python-*- # -*-python-*-
# #
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved. # Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
# #
# By using this file, you agree to the terms and conditions set forth in # By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC # the LICENSE.html file which can be found at the top level of the ViewVC
@@ -20,7 +20,7 @@ import difflib
import sys import sys
import re import re
import ezt import ezt
import sapi import cgi
def sidebyside(fromlines, tolines, context): def sidebyside(fromlines, tolines, context):
"""Generate side by side diff""" """Generate side by side diff"""
@@ -49,18 +49,18 @@ def _mdiff_split(flag, (line_number, text)):
while True: while True:
m = _re_mdiff.search(text, pos) m = _re_mdiff.search(text, pos)
if not m: if not m:
segments.append(_item(text=sapi.escape(text[pos:]), type=None)) segments.append(_item(text=cgi.escape(text[pos:]), type=None))
break break
if m.start() > pos: if m.start() > pos:
segments.append(_item(text=sapi.escape(text[pos:m.start()]), type=None)) segments.append(_item(text=cgi.escape(text[pos:m.start()]), type=None))
if m.group(1) == "+": if m.group(1) == "+":
segments.append(_item(text=sapi.escape(m.group(2)), type="add")) segments.append(_item(text=cgi.escape(m.group(2)), type="add"))
elif m.group(1) == "-": elif m.group(1) == "-":
segments.append(_item(text=sapi.escape(m.group(2)), type="remove")) segments.append(_item(text=cgi.escape(m.group(2)), type="remove"))
elif m.group(1) == "^": elif m.group(1) == "^":
segments.append(_item(text=sapi.escape(m.group(2)), type="change")) segments.append(_item(text=cgi.escape(m.group(2)), type="change"))
pos = m.end() pos = m.end()
@@ -166,12 +166,12 @@ def _differ_split(row, guide):
for m in _re_differ.finditer(guide, pos): for m in _re_differ.finditer(guide, pos):
if m.start() > pos: if m.start() > pos:
segments.append(_item(text=sapi.escape(line[pos:m.start()]), type=None)) segments.append(_item(text=cgi.escape(line[pos:m.start()]), type=None))
segments.append(_item(text=sapi.escape(line[m.start():m.end()]), segments.append(_item(text=cgi.escape(line[m.start():m.end()]),
type="change")) type="change"))
pos = m.end() pos = m.end()
segments.append(_item(text=sapi.escape(line[pos:]), type=None)) segments.append(_item(text=cgi.escape(line[pos:]), type=None))
return _item(gap=ezt.boolean(gap), type=type, segments=segments, return _item(gap=ezt.boolean(gap), type=type, segments=segments,
left_number=left_number, right_number=right_number) left_number=left_number, right_number=right_number)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*-python-*- # -*-python-*-
# #
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved. # Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
# #
# By using this file, you agree to the terms and conditions set forth in # By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC # the LICENSE.html file which can be found at the top level of the ViewVC
@@ -439,11 +439,11 @@ def main(server, cfg, viewvc_link):
'cfg' : cfg, 'cfg' : cfg,
'address' : cfg.general.address, 'address' : cfg.general.address,
'vsn' : viewvc.__version__, 'vsn' : viewvc.__version__,
'repository' : server.escape(form_data.repository), 'repository' : server.escape(form_data.repository, 1),
'branch' : server.escape(form_data.branch), 'branch' : server.escape(form_data.branch, 1),
'directory' : server.escape(form_data.directory), 'directory' : server.escape(form_data.directory, 1),
'file' : server.escape(form_data.file), 'file' : server.escape(form_data.file, 1),
'who' : server.escape(form_data.who), 'who' : server.escape(form_data.who, 1),
'docroot' : cfg.options.docroot is None \ 'docroot' : cfg.options.docroot is None \
and viewvc_link + '/' + viewvc.docroot_magic_path \ and viewvc_link + '/' + viewvc.docroot_magic_path \
or cfg.options.docroot, or cfg.options.docroot,

View File

@@ -1,6 +1,6 @@
# -*-python-*- # -*-python-*-
# #
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved. # Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
# #
# By using this file, you agree to the terms and conditions set forth in # By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC # the LICENSE.html file which can be found at the top level of the ViewVC
@@ -20,7 +20,6 @@ import string
import os import os
import sys import sys
import re import re
import cgi
# global server object. It will be either a CgiServer or a proxy to # global server object. It will be either a CgiServer or a proxy to
@@ -28,18 +27,6 @@ import cgi
server = None server = None
# Simple HTML string escaping. Note that we always escape the
# double-quote character -- ViewVC shouldn't ever need to preserve
# that character as-is, and sometimes needs to embed escaped values
# into HTML attributes.
def escape(s):
s = string.replace(s, '&', '&amp;')
s = string.replace(s, '>', '&gt;')
s = string.replace(s, '<', '&lt;')
s = string.replace(s, '"', "&quot;")
return s
class Server: class Server:
def __init__(self): def __init__(self):
self.pageGlobals = {} self.pageGlobals = {}
@@ -47,9 +34,6 @@ class Server:
def self(self): def self(self):
return self return self
def escape(self, s):
return escape(s)
def close(self): def close(self):
pass pass
@@ -145,6 +129,9 @@ class CgiServer(Server):
global server global server
server = self server = self
global cgi
import cgi
def addheader(self, name, value): def addheader(self, name, value):
self.headers.append((name, value)) self.headers.append((name, value))
@@ -173,6 +160,9 @@ class CgiServer(Server):
self.header(status='301 Moved') self.header(status='301 Moved')
sys.stdout.write('This document is located <a href="%s">here</a>.\n' % url) sys.stdout.write('This document is located <a href="%s">here</a>.\n' % url)
def escape(self, s, quote = None):
return cgi.escape(s, quote)
def getenv(self, name, value=None): def getenv(self, name, value=None):
ret = os.environ.get(name, value) ret = os.environ.get(name, value)
if self.iis and name == 'PATH_INFO' and ret: if self.iis and name == 'PATH_INFO' and ret:
@@ -229,6 +219,9 @@ class AspServer(ThreadedServer):
def redirect(self, url): def redirect(self, url):
self.response.Redirect(url) self.response.Redirect(url)
def escape(self, s, quote = None):
return self.server.HTMLEncode(str(s))
def getenv(self, name, value = None): def getenv(self, name, value = None):
ret = self.request.ServerVariables(name)() ret = self.request.ServerVariables(name)()
if not type(ret) is types.UnicodeType: if not type(ret) is types.UnicodeType:
@@ -290,6 +283,9 @@ class ModPythonServer(ThreadedServer):
self.request = request self.request = request
self.headerSent = 0 self.headerSent = 0
global cgi
import cgi
def addheader(self, name, value): def addheader(self, name, value):
self.request.headers_out.add(name, value) self.request.headers_out.add(name, value)
@@ -312,6 +308,9 @@ class ModPythonServer(ThreadedServer):
self.request.write("You are being redirected to <a href=\"%s\">%s</a>" self.request.write("You are being redirected to <a href=\"%s\">%s</a>"
% (url, url)) % (url, url))
def escape(self, s, quote = None):
return cgi.escape(s, quote)
def getenv(self, name, value = None): def getenv(self, name, value = None):
try: try:
return self.request.subprocess_env[name] return self.request.subprocess_env[name]

View File

@@ -14,7 +14,7 @@
# #
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
__version__ = '1.1.5' __version__ = '1.1.4'
# this comes from our library; measure the startup time # this comes from our library; measure the startup time
import debug import debug
@@ -24,6 +24,7 @@ debug.t_start('imports')
# standard modules that we know are in the path or builtin # standard modules that we know are in the path or builtin
import sys import sys
import os import os
import cgi
import gzip import gzip
import mimetypes import mimetypes
import re import re
@@ -431,8 +432,7 @@ class Request:
action = self.server.escape(urllib.quote(url, _URL_SAFE_CHARS)) action = self.server.escape(urllib.quote(url, _URL_SAFE_CHARS))
hidden_values = [] hidden_values = []
for name, value in params.items(): for name, value in params.items():
hidden_values.append(_item(name=self.server.escape(name), hidden_values.append(_item(name=name, value=value))
value=self.server.escape(value)))
return action, hidden_values return action, hidden_values
def get_link(self, view_func=None, where=None, pathtype=None, params=None): def get_link(self, view_func=None, where=None, pathtype=None, params=None):
@@ -1075,6 +1075,9 @@ def get_file_view_info(request, where, rev=None, mime_type=None, pathrev=-1):
revision_href=revision_href, revision_href=revision_href,
prefer_markup=ezt.boolean(prefer_markup)) prefer_markup=ezt.boolean(prefer_markup))
def htmlify(html):
return html and cgi.escape(html) or html
# Matches URLs # Matches URLs
_re_rewrite_url = re.compile('((http|https|ftp|file|svn|svn\+ssh)' _re_rewrite_url = re.compile('((http|https|ftp|file|svn|svn\+ssh)'
@@ -1107,8 +1110,8 @@ class HtmlFormatter:
""" """
s = mobj.group(0) s = mobj.group(0)
trunc_s = maxlen and s[:maxlen] or s trunc_s = maxlen and s[:maxlen] or s
return '<a href="%s">%s</a>' % (sapi.escape(s), return '<a href="%s">%s</a>' % (cgi.escape(s),
sapi.escape(trunc_s)), \ cgi.escape(trunc_s)), \
len(trunc_s) len(trunc_s)
def format_email(self, mobj, userdata, maxlen=0): def format_email(self, mobj, userdata, maxlen=0):
@@ -1159,7 +1162,7 @@ class HtmlFormatter:
- the number of characters returned. - the number of characters returned.
""" """
trunc_s = maxlen and s[:maxlen] or s trunc_s = maxlen and s[:maxlen] or s
return sapi.escape(trunc_s), len(trunc_s) return cgi.escape(trunc_s), len(trunc_s)
def add_formatter(self, regexp, conv, userdata=None): def add_formatter(self, regexp, conv, userdata=None):
"""Register a formatter which finds instances of strings matching """Register a formatter which finds instances of strings matching
@@ -1464,7 +1467,7 @@ def copy_stream(src, dst, htmlize=0):
if not chunk: if not chunk:
break break
if htmlize: if htmlize:
chunk = sapi.escape(chunk) chunk = htmlify(chunk)
dst.write(chunk) dst.write(chunk)
class MarkupPipeWrapper: class MarkupPipeWrapper:
@@ -1493,7 +1496,7 @@ def markup_stream_pygments(request, cfg, blame_data, fp, filename, mime_type):
blame_source = [] blame_source = []
if blame_data: if blame_data:
for i in blame_data: for i in blame_data:
i.text = sapi.escape(i.text) i.text = cgi.escape(i.text)
i.diff_href = None i.diff_href = None
if i.prev_rev: if i.prev_rev:
i.diff_href = request.get_url(view_func=view_diff, i.diff_href = request.get_url(view_func=view_diff,
@@ -1556,7 +1559,7 @@ def markup_stream_pygments(request, cfg, blame_data, fp, filename, mime_type):
if not line: if not line:
break break
line_no = line_no + 1 line_no = line_no + 1
line = sapi.escape(string.expandtabs(line, cfg.options.tabsize)) line = cgi.escape(string.expandtabs(line, cfg.options.tabsize))
item = vclib.Annotation(line, line_no, None, None, None, None) item = vclib.Annotation(line, line_no, None, None, None, None)
item.diff_href = None item.diff_href = None
lines.append(item) lines.append(item)
@@ -2031,7 +2034,7 @@ def view_directory(request):
'entries' : rows, 'entries' : rows,
'sortby' : sortby, 'sortby' : sortby,
'sortdir' : sortdir, 'sortdir' : sortdir,
'search_re' : request.server.escape(search_re), 'search_re' : htmlify(search_re),
'dir_pagestart' : None, 'dir_pagestart' : None,
'sortby_file_href' : request.get_url(params={'sortby': 'file', 'sortby_file_href' : request.get_url(params={'sortby': 'file',
'sortdir': None}, 'sortdir': None},
@@ -2763,7 +2766,7 @@ class DiffSource:
hr_breakable = self.cfg.options.hr_breakable hr_breakable = self.cfg.options.hr_breakable
# in the code below, "\x01" will be our stand-in for "&". We don't want # in the code below, "\x01" will be our stand-in for "&". We don't want
# to insert "&" because it would get escaped by sapi.escape(). Similarly, # to insert "&" because it would get escaped by htmlify(). Similarly,
# we use "\x02" as a stand-in for "<br>" # we use "\x02" as a stand-in for "<br>"
if hr_breakable > 1 and len(text) > hr_breakable: if hr_breakable > 1 and len(text) > hr_breakable:
@@ -2773,7 +2776,7 @@ class DiffSource:
text = string.replace(text, ' ', ' \x01nbsp;') text = string.replace(text, ' ', ' \x01nbsp;')
else: else:
text = string.replace(text, ' ', '\x01nbsp;') text = string.replace(text, ' ', '\x01nbsp;')
text = sapi.escape(text) text = htmlify(text)
text = string.replace(text, '\x01', '&') text = string.replace(text, '\x01', '&')
text = string.replace(text, '\x02', text = string.replace(text, '\x02',
'<span style="color:red">\</span><br />') '<span style="color:red">\</span><br />')
@@ -3154,7 +3157,7 @@ def view_diff(request):
else: else:
changes = DiffSource(fp, cfg) changes = DiffSource(fp, cfg)
else: else:
raw_diff_fp = MarkupPipeWrapper(fp, request.server.escape(headers), None, 1) raw_diff_fp = MarkupPipeWrapper(fp, htmlify(headers), None, 1)
no_format_params = request.query_dict.copy() no_format_params = request.query_dict.copy()
no_format_params['diff_format'] = None no_format_params['diff_format'] = None
@@ -3701,7 +3704,7 @@ def english_query(request):
ret.append('on all branches ') ret.append('on all branches ')
comment = request.query_dict.get('comment', '') comment = request.query_dict.get('comment', '')
if comment: if comment:
ret.append('with comment <i>%s</i> ' % request.server.escape(comment)) ret.append('with comment <i>%s</i> ' % htmlify(comment))
if who: if who:
ret.append('by <em>%s</em> ' % request.server.escape(who)) ret.append('by <em>%s</em> ' % request.server.escape(who))
date = request.query_dict.get('date', 'hours') date = request.query_dict.get('date', 'hours')