Hello community, here is the log from the commit of package viewvc for openSUSE:Factory checked in at Thu May 19 09:39:09 CEST 2011.
-------- --- viewvc/viewvc.changes 2011-03-15 23:22:12.000000000 +0100 +++ /mounts/work_src_done/STABLE/viewvc/viewvc.changes 2011-05-18 07:11:54.000000000 +0200 @@ -1,0 +2,14 @@ +Tue May 17 23:39:16 UTC 2011 - pascal.ble...@opensuse.org + +- update to 1.1.11: + * security fix: remove user-reachable override of cvsdb row limit + * fix broken standalone.py -c and -d options handling + * add --help option to standalone.py + * fix stack trace when asked to checkout a directory (issue #478) + * improve memory usage and speed of revision log markup (issue #477) + * fix broken annotation view in CVS keyword-bearing files (issue #479) + * warn users when query results are incomplete (issue #443) + * avoid parsing errors on RCS newphrases in the admin section (issue #483) + * make rlog parsing code more robust in certain error cases (issue #444) + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- viewvc-1.1.10.tar.bz2 New: ---- viewvc-1.1.11.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ viewvc.spec ++++++ --- /var/tmp/diff_new_pack.TO4eMK/_old 2011-05-19 09:37:23.000000000 +0200 +++ /var/tmp/diff_new_pack.TO4eMK/_new 2011-05-19 09:37:23.000000000 +0200 @@ -20,7 +20,7 @@ Name: viewvc BuildRequires: apache2-devel python-devel -Version: 1.1.10 +Version: 1.1.11 Release: 1 # %define apxs /usr/sbin/apxs2 ++++++ viewvc-1.1.10.tar.bz2 -> viewvc-1.1.11.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/CHANGES new/viewvc-1.1.11/CHANGES --- old/viewvc-1.1.10/CHANGES 2011-03-15 15:57:50.000000000 +0100 +++ new/viewvc-1.1.11/CHANGES 2011-05-17 14:23:20.000000000 +0200 @@ -1,3 +1,15 @@ +Version 1.1.11 (released 17-May-2011) + + * security fix: remove user-reachable override of cvsdb row limit + * fix broken standalone.py -c and -d options handling + * add --help option to standalone.py + * fix stack trace when asked to checkout a directory (issue #478) + * improve memory usage and speed of revision log markup (issue #477) + * fix broken annotation view in CVS keyword-bearing files (issue #479) + * warn users when query results are incomplete (issue #443) + * avoid parsing errors on RCS newphrases in the admin section (issue #483) + * make rlog parsing code more robust in certain error cases (issue #444) + Version 1.1.10 (released 15-Mar-2011) * fix stack trace in Subversion revision info logic (issue #475, issue #476) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/bin/standalone.py new/viewvc-1.1.11/bin/standalone.py --- old/viewvc-1.1.10/bin/standalone.py 2010-12-02 21:34:29.000000000 +0100 +++ new/viewvc-1.1.11/bin/standalone.py 2011-05-12 21:01:48.000000000 +0200 @@ -17,7 +17,7 @@ __author__ = "Peter Funk <p...@artcom-gmbh.de>" __date__ = "11 November 2001" -__version__ = "$Revision: 2482 $" +__version__ = "$Revision: 2567 $" __credits__ = """Guido van Rossum, for an excellent programming language. Greg Stein, for writing ViewCVS in the first place. Ka-Ping Yee, for the GUI code and the framework stolen from pydoc.py. @@ -76,8 +76,6 @@ class Options: port = 49152 # default TCP/IP port used for the server - start_gui = 0 # No GUI unless requested. - daemon = 0 # stay in the foreground by default repositories = {} # use default repositories specified in config host = sys.platform == 'mac' and '127.0.0.1' or 'localhost' script_alias = 'viewvc' @@ -707,13 +705,66 @@ # --- command-line interface: ---------------------------------------------- -def cli(argv): + +def usage(): + clean_options = Options() + cmd = os.path.basename(sys.argv[0]) + port = clean_options.port + host = clean_options.host + script_alias = clean_options.script_alias + sys.stderr.write("""Usage: %(cmd)s [OPTIONS] + +Run a simple, standalone HTTP server configured to serve up ViewVC requests. + +Options: + + --config-file=FILE (-c) Read configuration options from FILE. If not + specified, ViewVC will look for a configuration + file in its installation tree, falling back to + built-in default values. (Not valid in GUI mode.) + + --daemon (-d) Background the server process. + + --gui (-g) Pop up a graphical configuration interface. + Requires a valid X11 display connection. + + --help Show this usage message and exit. + + --host=HOSTNAME (-h) Listen on HOSTNAME. Required for access from a + remote machine. [default: %(host)s] + + --htpasswd-file=FILE Authenticate incoming requests, validating against + against FILE, which is an Apache HTTP Server + htpasswd file. (CRYPT only; no DIGEST support.) + + --port=PORT (-p) Listen on PORT. [default: %(port)d] + + --repository=PATH (-r) Serve the Subversion or CVS repository located + at PATH. This option may be used more than once. + + --script-alias=PATH (-s) Use PATH as the virtual script location (similar + to Apache HTTP Server's ScriptAlias directive). + For example, "--script-alias=repo/view" will serve + ViewVC at "http://HOSTNAME:PORT/repo/view". + [default: %(script_alias)s] +""" % locals()) + sys.exit(0) + + +def badusage(errstr): + cmd = os.path.basename(sys.argv[0]) + sys.stderr.write("ERROR: %s\n\n" + "Try '%s --help' for detailed usage information.\n" + % (errstr, cmd)) + sys.exit(1) + + +def main(argv): """Command-line interface (looks at argv to decide what to do).""" import getopt - class BadUsage(Exception): pass - short_opts = string.join(['c', - 'd:', + short_opts = string.join(['c:', + 'd', 'g', 'h:', 'p:', @@ -723,6 +774,7 @@ long_opts = ['daemon', 'config-file=', 'gui', + 'help', 'host=', 'htpasswd-file=', 'port=', @@ -730,113 +782,98 @@ 'script-alias=', ] - try: + opt_daemon = 0 + opt_gui = 0 + opt_host = None + opt_port = None + opt_htpasswd_file = None + opt_config_file = None + opt_script_alias = None + opt_repositories = [] + + # Parse command-line options. + try: opts, args = getopt.getopt(argv[1:], short_opts, long_opts) for opt, val in opts: - if opt in ('-g', '--gui'): - options.start_gui = 1 - elif opt in ('-r', '--repository'): - if options.repositories: # option may be used more than once: - num = len(options.repositories.keys())+1 - symbolic_name = "Repository"+str(num) - options.repositories[symbolic_name] = val - else: - options.repositories["Development"] = val - elif opt in ('-d', '--daemon'): - options.daemon = 1 - elif opt in ('-p', '--port'): - try: - options.port = int(val) - except ValueError: - raise BadUsage, "Port '%s' is not a valid port number" % (val) - elif opt in ('-h', '--host'): - options.host = val - elif opt in ('-s', '--script-alias'): - options.script_alias = \ - string.join(filter(None, string.split(val, '/')), '/') - elif opt in ('-c', '--config-file'): - if not os.path.isfile(val): - raise BadUsage, "'%s' does not appear to be a valid " \ - "configuration file." % (val) - options.config_file = val - elif opt in ('-c', '--htpasswd-file'): - if not os.path.isfile(val): - raise BadUsage, "'%s' does not appear to be a valid " \ - "htpasswd file." % (val) - if not has_crypt: - raise BadUsage, "Unable to locate suitable `crypt' module for use " \ - "with --htpasswd-file option. If your Python " \ - "distribution does not include this module (as is " \ - "the case on many non-Unix platforms), consider " \ - "installing the `fcrypt' module instead (see " \ - "http://carey.geek.nz/code/python-fcrypt/)." - options.htpasswd_file = val - if options.start_gui and options.config_file: - raise BadUsage, "--config-file option is not valid in GUI mode." - if not options.start_gui and not options.port: - raise BadUsage, "You must supply a valid port, or run in GUI mode." - if options.daemon: - pid = os.fork() - if pid != 0: - sys.exit() - if options.start_gui: - gui(options.host, options.port) - return - elif options.port: - def ready(server): - print 'server ready at %s%s' % (server.url, options.script_alias) - serve(options.host, options.port, ready) - return - except (getopt.error, BadUsage), err: - cmd = os.path.basename(sys.argv[0]) - port = options.port - host = options.host - script_alias = options.script_alias - if str(err): - sys.stderr.write("ERROR: %s\n\n" % (str(err))) - sys.stderr.write("""Usage: %(cmd)s [OPTIONS] - -Run a simple, standalone HTTP server configured to serve up ViewVC -requests. - -Options: - - --config-file=PATH (-c) Use the file at PATH as the ViewVC configuration - file. If not specified, ViewVC will try to use - the configuration file in its installation tree; - otherwise, built-in default values are used. - (Not valid in GUI mode.) - - --daemon (-d) Background the server process. - - --host=HOST (-h) Start the server listening on HOST. You need - to provide the hostname if you want to - access the standalone server from a remote - machine. [default: %(host)s] + if opt in ['--help']: + usage() + elif opt in ['-g', '--gui']: + opt_gui = 1 + elif opt in ['-r', '--repository']: # may be used more than once + opt_repositories.append(val) + elif opt in ['-d', '--daemon']: + opt_daemon = 1 + elif opt in ['-p', '--port']: + opt_port = val + elif opt in ['-h', '--host']: + opt_host = val + elif opt in ['-s', '--script-alias']: + opt_script_alias = val + elif opt in ['-c', '--config-file']: + opt_config_file = val + elif opt in ['--htpasswd-file']: + opt_htpasswd_file = val + except getopt.error, err: + badusage(str(err)) - --port=PORT (-p) Start the server on the given PORT. - [default: %(port)d] - - --repository=PATH (-r) Serve up the Subversion or CVS repository located - at PATH. This option may be used more than once. - - --script-alias=PATH (-s) Specify the ScriptAlias, the artificial path - location that at which ViewVC appears to be - located. For example, if your ScriptAlias is - "cgi-bin/viewvc", then ViewVC will be accessible - at "http://%(host)s:%(port)s/cgi-bin/viewvc". - [default: %(script_alias)s] + # Validate options that need validating. + class BadUsage(Exception): pass + try: + if opt_port is not None: + try: + options.port = int(opt_port) + except ValueError: + raise BadUsage("Port '%s' is not a valid port number" % (opt_port)) + if not options.port: + raise BadUsage("You must supply a valid port.") + if opt_htpasswd_file is not None: + if not os.path.isfile(opt_htpasswd_file): + raise BadUsage("'%s' does not appear to be a valid htpasswd file." + % (opt_htpasswd_file)) + if not has_crypt: + raise BadUsage("Unable to locate suitable `crypt' module for use " + "with --htpasswd-file option. If your Python " + "distribution does not include this module (as is " + "the case on many non-Unix platforms), consider " + "installing the `fcrypt' module instead (see " + "http://carey.geek.nz/code/python-fcrypt/).") + options.htpasswd_file = opt_htpasswd_file + if opt_config_file is not None: + if not os.path.isfile(opt_config_file): + raise BadUsage("'%s' does not appear to be a valid configuration file." + % (opt_config_file)) + options.config_file = opt_config_file + if opt_host is not None: + options.host = opt_host + if opt_script_alias is not None: + options.script_alias = string.join(filter(None, + string.split(opt_script_alias, + '/')), + '/') + for repository in opt_repositories: + if not options.repositories.has_key('Development'): + rootname = 'Development' + else: + rootname = 'Repository%d' % (len(options.repositories.keys()) + 1) + options.repositories[rootname] = repository + except BadUsage, err: + badusage(str(err)) + + # Fork if we're in daemon mode. + if opt_daemon: + pid = os.fork() + if pid != 0: + sys.exit() + + # Finaly, start the server. + if opt_gui: + gui(options.host, options.port) + else: + def ready(server): + print 'server ready at %s%s' % (server.url, options.script_alias) + serve(options.host, options.port, ready) - --htpasswd-file=FILE Demand authentication from clients, validating - authentication credentials against FILE, which is - an Apache htpasswd file that employs CRYPT - encryption. (Sorry, no DIGEST support yet.) - - --gui (-g) Pop up a graphical interface for serving and - testing ViewVC. NOTE: this requires a valid - X11 display connection. -""" % locals()) if __name__ == '__main__': options = Options() - cli(sys.argv) + main(sys.argv) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/conf/viewvc.conf.dist new/viewvc-1.1.11/conf/viewvc.conf.dist --- old/viewvc-1.1.10/conf/viewvc.conf.dist 2011-02-18 19:28:55.000000000 +0100 +++ new/viewvc-1.1.11/conf/viewvc.conf.dist 2011-04-20 16:56:39.000000000 +0200 @@ -797,6 +797,14 @@ ## row_limit: Maximum number of rows returned by a given normal query ## to the database. ## +## NOTE: This limits the amount of data provided to ViewVC by the +## database. It is from this already-reduced data set that ViewVC +## builds the query response it presents to the user, which may or may +## not include still more limiting via the query form's 'limit' +## parameter. In other words, there is no value which the user can use +## in the query form's 'limit' parameter which will cause more data to +## be returned by the database for ViewVC to process. +## #row_limit = 1000 ## rss_row_limit: Maximum number of rows returned by a given query to @@ -804,6 +812,9 @@ ## that RSS readers tend to poll regularly for new data, you might want ## to keep this set to a conservative number.) ## +## See also the `NOTE' for the 'row_limit' option, which applies here +## as well. +## #rss_row_limit = 100 ## check_database_for_root: Check if the repository is found in the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/docs/template-authoring-guide.html new/viewvc-1.1.11/docs/template-authoring-guide.html --- old/viewvc-1.1.10/docs/template-authoring-guide.html 2011-02-18 16:29:11.000000000 +0100 +++ new/viewvc-1.1.11/docs/template-authoring-guide.html 2011-04-20 16:56:39.000000000 +0200 @@ -1822,6 +1822,14 @@ <tt>date</tt>, <tt>author</tt>, and <tt>file</tt>.</td> </tr> <tr class="varlevel1"> + <td class="varname">row_limit_reached</td> + <td>Boolean</td> + <td>Indicates whether the internal database row limit threshold (set + via the <code>cvsdb.row_limit</code> + and <code>cvsdb.rss_row_limit</code> configuration options) was + reached by the query.</td> +</tr> +<tr class="varlevel1"> <td class="varname">show_branch</td> <td>Boolean</td> <td>Indicates whether or not to list branch names in the results. True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/docs/url-reference.html new/viewvc-1.1.11/docs/url-reference.html --- old/viewvc-1.1.10/docs/url-reference.html 2009-06-15 22:12:15.000000000 +0200 +++ new/viewvc-1.1.11/docs/url-reference.html 2011-04-19 22:44:05.000000000 +0200 @@ -1193,13 +1193,6 @@ page</td> </tr> <tr> - <td><code>limit=<var>LIMIT</var></code></td> - <td>optional</td> - <td>maximum number of file-revisions to process during a - query. Default is value of <code>row_limit</code> configuration - option</td> - </tr> - <tr> <td><code>limit_changes=<var>LIMIT_CHANGES</var></code></td> <td>optional</td> <td>maximum number of files to list per commit in query diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/cvsdb.py new/viewvc-1.1.11/lib/cvsdb.py --- old/viewvc-1.1.10/lib/cvsdb.py 2009-06-08 17:53:47.000000000 +0200 +++ new/viewvc-1.1.11/lib/cvsdb.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # # 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 @@ -38,13 +38,12 @@ ## complient database interface class CheckinDatabase: - def __init__(self, host, port, user, passwd, database, row_limit): + def __init__(self, host, port, user, passwd, database): self._host = host self._port = port self._user = user self._passwd = passwd self._database = database - self._row_limit = row_limit self._version = None ## database lookup caches @@ -169,6 +168,9 @@ return list + def GetCommitsTable(self): + return self._version >= 1 and 'commits' or 'checkins' + def GetTableList(self): sql = "SHOW TABLES" cursor = self.db.cursor() @@ -309,8 +311,7 @@ minus_count = commit.GetMinusCount() or '0' description_id = self.GetDescriptionID(commit.GetDescription()) - commits_table = self._version >= 1 and 'commits' or 'checkins' - sql = "REPLACE INTO %s" % (commits_table) + sql = "REPLACE INTO %s" % (self.GetCommitsTable()) sql = sql + \ " (type,ci_when,whoid,repositoryid,dirid,fileid,revision,"\ " stickytag,branchid,addedlines,removedlines,descid)"\ @@ -363,8 +364,8 @@ return "(%s)" % (string.join(sqlList, " OR ")) - def CreateSQLQueryString(self, query): - commits_table = self._version >= 1 and 'commits' or 'checkins' + def CreateSQLQueryString(self, query, detect_leftover=0): + commits_table = self.GetCommitsTable() tableList = [(commits_table, None)] condList = [] @@ -444,13 +445,14 @@ conditions = string.join(joinConds + condList, " AND ") conditions = conditions and "WHERE %s" % conditions - ## limit the number of rows requested or we could really slam - ## a server with a large database + ## apply the query's row limit, if any (so we avoid really + ## slamming a server with a large database) limit = "" if query.limit: - limit = "LIMIT %s" % (str(query.limit)) - elif self._row_limit: - limit = "LIMIT %s" % (str(self._row_limit)) + if detect_leftover: + limit = "LIMIT %s" % (str(query.limit + 1)) + else: + limit = "LIMIT %s" % (str(query.limit)) sql = "SELECT %s.* FROM %s %s %s %s" \ % (commits_table, tables, conditions, order_by, limit) @@ -458,14 +460,20 @@ return sql def RunQuery(self, query): - sql = self.CreateSQLQueryString(query) + sql = self.CreateSQLQueryString(query, 1) cursor = self.db.cursor() cursor.execute(sql) + query.SetExecuted() + row_count = 0 while 1: row = cursor.fetchone() if not row: break + row_count = row_count + 1 + if query.limit and (row_count > query.limit): + query.SetLimitReached() + break (dbType, dbCI_When, dbAuthorID, dbRepositoryID, dbDirID, dbFileID, dbRevision, dbStickyTag, dbBranchID, dbAddedLines, @@ -504,13 +512,12 @@ if file_id == None: return None - commits_table = self._version >= 1 and 'commits' or 'checkins' sql = "SELECT * FROM %s WHERE "\ " repositoryid=%%s "\ " AND dirid=%%s"\ " AND fileid=%%s"\ " AND revision=%%s"\ - % (commits_table) + % (self.GetCommitsTable()) sql_args = (repository_id, dir_id, file_id, commit.GetRevision()) cursor = self.db.cursor() @@ -527,10 +534,9 @@ def sql_delete(self, table, key, value, keep_fkey = None): sql = "DELETE FROM %s WHERE %s=%%s" % (table, key) sql_args = (value, ) - commits_table = self._version >= 1 and 'commits' or 'checkins' if keep_fkey: sql += " AND %s NOT IN (SELECT %s FROM %s WHERE %s = %%s)" \ - % (key, keep_fkey, commits_table, keep_fkey) + % (key, keep_fkey, self.GetCommitsTable(), keep_fkey) sql_args = (value, value) cursor = self.db.cursor() cursor.execute(sql, sql_args) @@ -769,8 +775,9 @@ self.data = data self.match = match -## CheckinDatabaseQueryData is a object which contains the search parameters -## for a query to the CheckinDatabase +## CheckinDatabaseQuery is an object which contains the search +## parameters for a query to the Checkin Database and -- after the +## query is executed -- the data returned by the query. class CheckinDatabaseQuery: def __init__(self): ## sorting @@ -790,7 +797,8 @@ ## limit on number of rows to return self.limit = None - + self.limit_reached = 0 + ## list of commits -- filled in by CVS query self.commit_list = [] @@ -798,6 +806,9 @@ ## are added self.commit_cb = None + ## has this query been run? + self.executed = 0 + def SetRepository(self, repository, match = "exact"): self.repository_list.append(QueryEntry(repository, match)) @@ -843,6 +854,20 @@ def AddCommit(self, commit): self.commit_list.append(commit) + def SetExecuted(self): + self.executed = 1 + + def SetLimitReached(self): + self.limit_reached = 1 + + def GetLimitReached(self): + assert self.executed + return self.limit_reached + + def GetCommitList(self): + assert self.executed + return self.commit_list + ## ## entrypoints @@ -861,7 +886,7 @@ user = cfg.cvsdb.user passwd = cfg.cvsdb.passwd db = CheckinDatabase(cfg.cvsdb.host, cfg.cvsdb.port, user, passwd, - cfg.cvsdb.database_name, cfg.cvsdb.row_limit) + cfg.cvsdb.database_name) db.Connect() return db diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/query.py new/viewvc-1.1.11/lib/query.py --- old/viewvc-1.1.10/lib/query.py 2010-09-09 17:31:52.000000000 +0200 +++ new/viewvc-1.1.11/lib/query.py 2011-04-20 16:56:39.000000000 +0200 @@ -217,8 +217,9 @@ else: return "exact" -def form_to_cvsdb_query(form_data): +def form_to_cvsdb_query(cfg, form_data): query = cvsdb.CreateCheckinQuery() + query.SetLimit(cfg.cvsdb.row_limit) if form_data.repository: for cmd, str in listparse_string(form_data.repository): @@ -377,12 +378,15 @@ return ob def run_query(server, cfg, form_data, viewvc_link): - query = form_to_cvsdb_query(form_data) + query = form_to_cvsdb_query(cfg, form_data) db = cvsdb.ConnectDatabaseReadOnly(cfg) db.RunQuery(query) - if not query.commit_list: - return [ ] + commit_list = query.GetCommitList() + if not commit_list: + return [ ], 0 + + row_limit_reached = query.GetLimitReached() commits = [ ] files = [ ] @@ -393,8 +397,8 @@ for key, value in rootitems: cvsroots[cvsdb.CleanRepository(value)] = key - current_desc = query.commit_list[0].GetDescription() - for commit in query.commit_list: + current_desc = commit_list[0].GetDescription() + for commit in commit_list: desc = commit.GetDescription() if current_desc == desc: files.append(commit) @@ -417,7 +421,7 @@ return len(commit.files) > 0 commits = filter(_only_with_files, commits) - return commits + return commits, row_limit_reached def main(server, cfg, viewvc_link): try: @@ -426,10 +430,12 @@ form_data = FormData(form) if form_data.valid: - commits = run_query(server, cfg, form_data, viewvc_link) + commits, row_limit_reached = run_query(server, cfg, + form_data, viewvc_link) query = None else: commits = [ ] + row_limit_reached = 0 query = 'skipped' docroot = cfg.options.docroot @@ -449,6 +455,7 @@ 'sortby' : form_data.sortby, 'date' : form_data.date, 'query' : query, + 'row_limit_reached' : ezt.boolean(row_limit_reached), 'commits' : commits, 'num_commits' : len(commits), 'rss_href' : None, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vcauth/__init__.py new/viewvc-1.1.11/lib/vcauth/__init__.py --- old/viewvc-1.1.10/lib/vcauth/__init__.py 2010-12-09 17:22:05.000000000 +0100 +++ new/viewvc-1.1.11/lib/vcauth/__init__.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 2006-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 2006-2010 The ViewCVS Group. All Rights Reserved. # # 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vcauth/forbidden/__init__.py new/viewvc-1.1.11/lib/vcauth/forbidden/__init__.py --- old/viewvc-1.1.10/lib/vcauth/forbidden/__init__.py 2010-12-09 17:22:05.000000000 +0100 +++ new/viewvc-1.1.11/lib/vcauth/forbidden/__init__.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 2006-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 2006-2010 The ViewCVS Group. All Rights Reserved. # # 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vcauth/forbiddenre/__init__.py new/viewvc-1.1.11/lib/vcauth/forbiddenre/__init__.py --- old/viewvc-1.1.10/lib/vcauth/forbiddenre/__init__.py 2010-12-09 17:22:05.000000000 +0100 +++ new/viewvc-1.1.11/lib/vcauth/forbiddenre/__init__.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 2008-2010 The ViewCVS Group. All Rights Reserved. # # 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/__init__.py new/viewvc-1.1.11/lib/vclib/__init__.py --- old/viewvc-1.1.10/lib/vclib/__init__.py 2010-06-15 17:20:50.000000000 +0200 +++ new/viewvc-1.1.11/lib/vclib/__init__.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # # 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 @@ -76,7 +76,7 @@ """ pass - def openfile(self, path_parts, rev): + def openfile(self, path_parts, rev, options): """Open a file object to read file contents at a given path and revision. The return value is a 2-tuple of containg the file object and revision @@ -86,6 +86,8 @@ of the repository. e.g. ["subdir1", "subdir2", "filename"] rev is the revision of the file to check out + + options is a dictionary of implementation specific options """ def listdir(self, path_parts, rev, options): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/ccvs/bincvs.py new/viewvc-1.1.11/lib/vclib/ccvs/bincvs.py --- old/viewvc-1.1.10/lib/vclib/ccvs/bincvs.py 2010-12-09 17:22:05.000000000 +0100 +++ new/viewvc-1.1.11/lib/vclib/ccvs/bincvs.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # # 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 @@ -167,7 +167,14 @@ return revs[-1] return None - def openfile(self, path_parts, rev): + def openfile(self, path_parts, rev, options): + """see vclib.Repository.openfile docstring + + Option values recognized by this implementation: + + cvs_oldkeywords + boolean. true to use the original keyword substitution values. + """ if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check raise vclib.Error("Path '%s' is not a file." % (string.join(path_parts, "/"))) @@ -175,12 +182,14 @@ rev_flag = '-p' else: rev_flag = '-p' + rev + if options.get('cvs_oldkeywords', 0): + kv_flag = '-ko' + else: + kv_flag = '-kkv' full_name = self.rcsfile(path_parts, root=1, v=0) - used_rlog = 0 tip_rev = None # used only if we have to fallback to using rlog - - fp = self.rcs_popen('co', (rev_flag, full_name), 'rb') + fp = self.rcs_popen('co', (kv_flag, rev_flag, full_name), 'rb') try: filename, revision = _parse_co_header(fp) except COMissingRevision: @@ -1027,16 +1036,16 @@ file.errors.append("rlog error: %s" % msg) continue + tag = None if view_tag == 'MAIN' or view_tag == 'HEAD': tag = Tag(None, default_branch) elif taginfo.has_key(view_tag): tag = Tag(None, taginfo[view_tag]) - elif view_tag: - # the tag wasn't found, so skip this file + elif view_tag and (eof != _EOF_FILE): + # the tag wasn't found, so skip this file (unless we already + # know there's nothing left of it to read) _skip_file(rlog) - eof = 1 - else: - tag = None + eof = _EOF_FILE # we don't care about the specific values -- just the keys and whether # the values point to branches or revisions. this the fastest way to diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/ccvs/blame.py new/viewvc-1.1.11/lib/vclib/ccvs/blame.py --- old/viewvc-1.1.10/lib/vclib/ccvs/blame.py 2009-03-18 17:45:10.000000000 +0100 +++ new/viewvc-1.1.11/lib/vclib/ccvs/blame.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*-python-*- # -# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # Copyright (C) 2000 Curt Hagenlocher <c...@hagenlocher.org> # # By using this file, you agree to the terms and conditions set forth in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/ccvs/ccvs.py new/viewvc-1.1.11/lib/vclib/ccvs/ccvs.py --- old/viewvc-1.1.10/lib/vclib/ccvs/ccvs.py 2008-08-21 15:37:46.000000000 +0200 +++ new/viewvc-1.1.11/lib/vclib/ccvs/ccvs.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # # 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 @@ -127,9 +127,9 @@ % (string.join(path_parts2, "/"))) temp1 = tempfile.mktemp() - open(temp1, 'wb').write(self.openfile(path_parts1, rev1)[0].getvalue()) + open(temp1, 'wb').write(self.openfile(path_parts1, rev1, {})[0].getvalue()) temp2 = tempfile.mktemp() - open(temp2, 'wb').write(self.openfile(path_parts2, rev2)[0].getvalue()) + open(temp2, 'wb').write(self.openfile(path_parts2, rev2, {})[0].getvalue()) r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1] r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1] @@ -152,7 +152,7 @@ def revinfo(self, rev): raise vclib.UnsupportedFeature - def openfile(self, path_parts, rev=None): + def openfile(self, path_parts, rev, options): if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check raise vclib.Error("Path '%s' is not a file." % (string.join(path_parts, "/"))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/ccvs/rcsparse/common.py new/viewvc-1.1.11/lib/vclib/ccvs/rcsparse/common.py --- old/viewvc-1.1.10/lib/vclib/ccvs/rcsparse/common.py 2009-03-18 17:45:10.000000000 +0100 +++ new/viewvc-1.1.11/lib/vclib/ccvs/rcsparse/common.py 2011-05-17 14:21:27.000000000 +0200 @@ -1,6 +1,6 @@ # -*-python-*- # -# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved. +# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved. # # 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 @@ -194,7 +194,8 @@ else: # Chew up "newphrase" # warn("Unexpected RCS token: $token\n") - pass + while self.ts.get() != ';': + pass else: if f is None: self.ts.unget(token) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/svn/svn_ra.py new/viewvc-1.1.11/lib/vclib/svn/svn_ra.py --- old/viewvc-1.1.10/lib/vclib/svn/svn_ra.py 2011-02-18 20:27:50.000000000 +0100 +++ new/viewvc-1.1.11/lib/vclib/svn/svn_ra.py 2011-04-01 19:02:07.000000000 +0200 @@ -241,7 +241,7 @@ raise vclib.ItemNotFound(path_parts) return pathtype - def openfile(self, path_parts, rev): + def openfile(self, path_parts, rev, options): path = self._getpath(path_parts) if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check raise vclib.Error("Path '%s' is not a file." % path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/vclib/svn/svn_repos.py new/viewvc-1.1.11/lib/vclib/svn/svn_repos.py --- old/viewvc-1.1.10/lib/vclib/svn/svn_repos.py 2011-03-11 21:22:58.000000000 +0100 +++ new/viewvc-1.1.11/lib/vclib/svn/svn_repos.py 2011-04-01 19:02:07.000000000 +0200 @@ -400,7 +400,7 @@ raise vclib.ItemNotFound(path_parts) return pathtype - def openfile(self, path_parts, rev): + def openfile(self, path_parts, rev, options): path = self._getpath(path_parts) if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check raise vclib.Error("Path '%s' is not a file." % path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/lib/viewvc.py new/viewvc-1.1.11/lib/viewvc.py --- old/viewvc-1.1.10/lib/viewvc.py 2011-03-15 17:23:58.000000000 +0100 +++ new/viewvc-1.1.11/lib/viewvc.py 2011-05-17 14:27:03.000000000 +0200 @@ -14,7 +14,7 @@ # # ----------------------------------------------------------------------- -__version__ = '1.1.10' +__version__ = '1.1.11' # this comes from our library; measure the startup time import debug @@ -703,7 +703,6 @@ 'mindate' : _re_validate_datetime, 'maxdate' : _re_validate_datetime, 'format' : _re_validate_alpha, - 'limit' : _re_validate_number, # for redirect_pathrev 'orig_path' : None, @@ -1131,7 +1130,7 @@ linkified email address, with no more than MAXLEN characters in the non-HTML-tag bits. If MAXLEN is 0, there is no maximum. - the number of non-HTML-tag characters returned. - """ + """ s = mobj.group(0) trunc_s = maxlen and s[:maxlen] or s return '<a href="mailto:%s">%s</a>' % (urllib.quote(s), @@ -1232,45 +1231,51 @@ def _tokenize_text(self, s): tokens = [] - while s: - best_match = best_conv = best_userdata = None - for test in self._formatters: - match = test[0].search(s) - # If we find and match and (a) its our first one, or (b) it - # matches text earlier than our previous best match, or (c) it - # matches text at the same location as our previous best match - # but extends to cover more text than that match, then this is - # our new best match. - # - # Implied here is that when multiple formatters match exactly - # the same text, the first formatter in the registration list wins. - if match \ - and ((best_match is None) \ - or (match.start() < best_match.start()) - or ((match.start() == best_match.start()) \ - and (match.end() > best_match.end()))): - best_match = match - best_conv = test[1] - best_userdata = test[2] - # If we found a match... - if best_match: - # ... add any non-matching stuff first, then the matching bit. - start = best_match.start() - end = best_match.end() - if start > 0: - tokens.append(_item(match=s[:start], + # We could just have a "while s:" here instead of "for line: while + # line:", but for really large log messages with heavy + # tokenization, the cost in both performance and memory + # consumption of the approach taken was atrocious. + for line in string.split(string.replace(s, '\r\n', '\n'), '\n'): + line = line + '\n' + while line: + best_match = best_conv = best_userdata = None + for test in self._formatters: + match = test[0].search(line) + # If we find and match and (a) its our first one, or (b) it + # matches text earlier than our previous best match, or (c) it + # matches text at the same location as our previous best match + # but extends to cover more text than that match, then this is + # our new best match. + # + # Implied here is that when multiple formatters match exactly + # the same text, the first formatter in the registration list wins. + if match \ + and ((best_match is None) \ + or (match.start() < best_match.start()) + or ((match.start() == best_match.start()) \ + and (match.end() > best_match.end()))): + best_match = match + best_conv = test[1] + best_userdata = test[2] + # If we found a match... + if best_match: + # ... add any non-matching stuff first, then the matching bit. + start = best_match.start() + end = best_match.end() + if start > 0: + tokens.append(_item(match=line[:start], + converter=self.format_text, + userdata=None)) + tokens.append(_item(match=best_match, + converter=best_conv, + userdata=best_userdata)) + line = line[end:] + else: + # Otherwise, just add the rest of the string. + tokens.append(_item(match=line, converter=self.format_text, userdata=None)) - tokens.append(_item(match=best_match, - converter=best_conv, - userdata=best_userdata)) - s = s[end:] - else: - # Otherwise, just add the rest of the string. - tokens.append(_item(match=s, - converter=self.format_text, - userdata=None)) - s = '' + line = '' return tokens @@ -1739,7 +1744,7 @@ # Is this a viewable image type? if is_viewable_image(mime_type) \ and 'co' in cfg.options.allowed_views: - fp, revision = request.repos.openfile(path, rev) + fp, revision = request.repos.openfile(path, rev, {}) fp.close() if check_freshness(request, None, revision, weak=1): return @@ -1762,7 +1767,7 @@ except: annotation = 'error' - fp, revision = request.repos.openfile(path, rev) + fp, revision = request.repos.openfile(path, rev, {'cvs_oldkeywords' : 1}) if check_freshness(request, None, revision, weak=1): fp.close() return @@ -2662,9 +2667,12 @@ if 'co' not in cfg.options.allowed_views: raise debug.ViewVCException('Checkout view is disabled', '403 Forbidden') - + if request.pathtype != vclib.FILE: + raise debug.ViewVCException('Unsupported feature: checkout view on ' + 'directory', '400 Bad Request') + path, rev = _orig_path(request) - fp, revision = request.repos.openfile(path, rev) + fp, revision = request.repos.openfile(path, rev, {}) # The revision number acts as a strong validator. if not check_freshness(request, None, revision): @@ -2750,7 +2758,7 @@ # Read in each line of a checked-out file, and then use re.search to # search line. - fp = repos.openfile(path_parts, rev)[0] + fp = repos.openfile(path_parts, rev, {})[0] matches = 0 while 1: line = fp.readline() @@ -3210,13 +3218,13 @@ if (cfg.options.hr_intraline and idiff and ((human_readable and idiff.sidebyside) or (not human_readable and diff_type == vclib.UNIFIED))): - f1 = request.repos.openfile(p1, rev1)[0] + f1 = request.repos.openfile(p1, rev1, {})[0] try: lines_left = f1.readlines() finally: f1.close() - f2 = request.repos.openfile(p2, rev2)[0] + f2 = request.repos.openfile(p2, rev2, {})[0] try: lines_right = f2.readlines() finally: @@ -3429,7 +3437,7 @@ ### FIXME: Read the whole file into memory? Bad... better to do ### 2 passes. - fp = request.repos.openfile(rep_path + [file.name], request.pathrev)[0] + fp = request.repos.openfile(rep_path + [file.name], request.pathrev, {})[0] contents = fp.read() fp.close() @@ -4078,7 +4086,6 @@ mindate = request.query_dict.get('mindate', '') maxdate = request.query_dict.get('maxdate', '') format = request.query_dict.get('format') - limit = int(request.query_dict.get('limit', 0)) limit_changes = int(request.query_dict.get('limit_changes', cfg.options.limit_changes)) @@ -4148,29 +4155,32 @@ query.SetFromDateObject(mindate) if maxdate is not None: query.SetToDateObject(maxdate) - if limit: - query.SetLimit(limit) - elif format == 'rss': + + # Set the admin-defined (via configuration) row limits. This is to avoid + # slamming the database server with a monster query. + if format == 'rss': query.SetLimit(cfg.cvsdb.rss_row_limit) + else: + query.SetLimit(cfg.cvsdb.row_limit) # run the query db.RunQuery(query) - - sql = request.server.escape(db.CreateSQLQueryString(query)) - + commit_list = query.GetCommitList() + row_limit_reached = query.GetLimitReached() + # gather commits commits = [] plus_count = 0 minus_count = 0 mod_time = -1 - if query.commit_list: + if commit_list: files = [] limited_files = 0 - current_desc = query.commit_list[0].GetDescriptionID() - current_rev = query.commit_list[0].GetRevision() + current_desc = commit_list[0].GetDescriptionID() + current_rev = commit_list[0].GetRevision() dir_strip = _path_join(repos_dir) - for commit in query.commit_list: + for commit in commit_list: commit_desc = commit.GetDescriptionID() commit_rev = commit.GetRevision() @@ -4239,7 +4249,7 @@ data = common_template_data(request) data.merge(ezt.TemplateData({ - 'sql': sql, + 'sql': request.server.escape(db.CreateSQLQueryString(query)), 'english_query': english_query(request), 'queryform_href': request.get_url(view_func=view_queryform, escape=1), 'backout_href': backout_href, @@ -4248,6 +4258,7 @@ 'show_branch': show_branch, 'querysort': querysort, 'commits': commits, + 'row_limit_reached' : ezt.boolean(row_limit_reached), 'limit_changes': limit_changes, 'limit_changes_href': limit_changes_href, 'rss_link_href': request.get_url(view_func=view_query, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/templates/docroot/styles.css new/viewvc-1.1.11/templates/docroot/styles.css --- old/viewvc-1.1.10/templates/docroot/styles.css 2010-06-15 17:20:50.000000000 +0200 +++ new/viewvc-1.1.11/templates/docroot/styles.css 2011-04-20 16:56:39.000000000 +0200 @@ -269,3 +269,14 @@ .vc_query_form { background-color: #e6e6e6; } + + +/*** Warning! ***/ +.vc_warning { + border-width: 1px 2px 2px 2px; + border-color: black; + border-style: solid; + background-color: red; + color: white; + padding: 0.5em; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/templates/query.ezt new/viewvc-1.1.11/templates/query.ezt --- old/viewvc-1.1.10/templates/query.ezt 2010-09-09 17:31:52.000000000 +0200 +++ new/viewvc-1.1.11/templates/query.ezt 2011-04-20 17:02:08.000000000 +0200 @@ -158,7 +158,15 @@ [is query "skipped"] [else] <p><strong>[num_commits]</strong> matches found.</p> - +[if-any row_limit_reached] +<p class="vc_warning">WARNING: These query results have been + artificially limited by an administrative threshold value and do + <em>not</em> represent the entirety of the data set which matches + the query. Consider modifying your query to be more specific</a>, + using your version control tool's query capabilities, or asking + your administrator to raise the database response size + threshold.</p> +[end] [if-any commits] <table cellspacing="0" cellpadding="2"> <thead> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/viewvc-1.1.10/templates/query_results.ezt new/viewvc-1.1.11/templates/query_results.ezt --- old/viewvc-1.1.10/templates/query_results.ezt 2007-03-27 21:03:37.000000000 +0200 +++ new/viewvc-1.1.11/templates/query_results.ezt 2011-04-20 17:02:08.000000000 +0200 @@ -7,6 +7,15 @@ <p><strong>[english_query]</strong></p> [# <!-- {sql} --> ] +[if-any row_limit_reached] +<p class="vc_warning">WARNING: These query results have been + artificially limited by an administrative threshold value and do + <em>not</em> represent the entirety of the data set which matches + the query. Consider <a href="[queryform_href]">modifying your + query to be more specific</a>, using your version control tool's + query capabilities, or asking your administrator to raise the + database response size threshold.</p> +[end] <p><a href="[queryform_href]">Modify query</a></p> <p><a href="[backout_href]">Show commands which could be used to back out these changes</a></p> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org