No changes between revisions
/WebSVN/form.php
File deleted
/WebSVN/templates.txt
File deleted
/WebSVN/wsvn.php
File deleted
/WebSVN/install.txt
File deleted
/WebSVN/licence.txt
File deleted
/WebSVN/README.md
0,0 → 1,9
# WebSVN - Online Subversion repository browser
 
This is a Fork from WebSVN
 
WebSVN offers a view onto your Subversion repositories that's been designed to reflect the Subversion methodology.
You can view the log of any file or directory and see a list of all the files changed, added or deleted in any given revision.
You can also view the differences between two versions of a file so as to see exactly what was changed in a particular revision.
 
More information in project site. https://websvnphp.github.io/
/WebSVN/blame.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
25,107 → 23,241
// Show the blame information of a file.
//
 
require_once 'include/setup.inc';
require_once 'include/svnlook.inc';
require_once 'include/utils.inc';
require_once 'include/template.inc';
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
 
$vars['action'] = $lang['BLAME'];
 
// Make sure that we have a repository
if (!$rep)
{
renderTemplate404('blame','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, '', '', true);
$youngest = $history->entries[0]->rev;
$history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg);
 
if (empty($rev))
$rev = $youngest;
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg);
 
if ($path{0} != '/')
$ppath = '/'.$path;
else
$ppath = $path;
if (!$history)
{
renderTemplate404('blame','NOPATH');
}
}
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
 
if (empty($rev))
{
$rev = $youngest;
}
else
{
$history = $svnrep->getLog($path, $rev, '', false, 2, $peg);
if (!$history)
{
renderTemplate404('blame','NOPATH');
}
}
 
if ($path[0] != '/')
{
$ppath = '/'.$path;
}
else
{
$ppath = $path;
}
 
// Find the parent path (or the whole path if it's already a directory)
$pos = strrpos($ppath, '/');
$parent = substr($ppath, 0, $pos + 1);
 
$vars['repname'] = $rep->getDisplayName();
$vars['rev'] = $rev;
$vars['path'] = $ppath;
$vars['peg'] = $peg;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
 
createDirLinks($rep, $ppath, $rev, $showchanged);
if (isset($history->entries[0]))
{
$vars['log'] = xml_entities($history->entries[0]->msg);
$vars['date'] = $history->entries[0]->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
$vars['author'] = $history->entries[0]->author;
}
 
$listing = array();
createPathLinks($rep, $ppath, $passrev, $peg);
$passRevString = createRevAndPegString($rev, $peg);
 
// Get the contents of the file
$tfname = tempnam('temp', '');
$svnrep->getFileContents($path, $tfname, $rev, '', true);
if ($rev != $youngest)
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'blame').createRevAndPegString('', $peg);
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
}
 
$filecache = array();
$revurl = $config->getURL($rep, $path, 'blame');
 
if ($file = fopen($tfname, 'r'))
if ($rev < $youngest)
{
// Get the blame info
$tbname = tempnam('temp', '');
$svnrep->getBlameDetails($path, $tbname, $rev);
$ent = true;
$extension = strrchr(basename($path), '.');
if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript))
$ent = false;
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg);
 
if ($blame = fopen($tbname, 'r'))
{
// Create an array of version/author/line
$index = 0;
while (!feof($blame) && !feof($file))
{
$blameline = fgets($blame);
if ($blameline != '')
{
list($revision, $author) = sscanf($blameline, '%d %s');
$listing[$index]['lineno'] = $index + 1;
$url = $config->getURL($rep, $parent, 'dir');
$listing[$index]['revision'] = "<a href=\"${url}rev=$revision&amp;sc=1\">$revision</a>";
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg);
}
}
 
$listing[$index]['author'] = $author;
if ($ent)
$line = replaceEntities(rtrim(fgets($file)), $rep);
else
$line = rtrim(fgets($file));
unset($vars['error']);
}
 
$listing[$index]['line'] = hardspace($line);
if (trim($listing[$index]['line']) == '')
$listing[$index]['line'] = '&nbsp;';
$index++;
}
}
fclose($blame);
}
fclose($file);
if (isset($history->entries[1]))
{
$prevRev = $history->entries[1]->rev;
$prevPath = $history->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg);
}
 
unlink($tfname);
unlink($tbname);
$vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
 
$vars['version'] = $version;
$vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
if (!$rep->hasReadAccess($path, false))
$vars['noaccess'] = true;
$vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
$vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
 
parseTemplate($rep->getTemplatePath().'header.tmpl', $vars, $listing);
parseTemplate($rep->getTemplatePath().'blame.tmpl', $vars, $listing);
parseTemplate($rep->getTemplatePath().'footer.tmpl', $vars, $listing);
?>
if ($history == null || count($history->entries) > 1)
{
$vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString;
$vars['difflink'] = '<a href="'.$vars['diffurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
// Check for binary file type before grabbing blame information.
$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev, $peg);
 
if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType))
{
$vars['warning'] = 'Cannot display blame info for binary file. (svn:mime-type = '.$svnMimeType.')';
$vars['javascript'] = '';
}
else
{
// Get the contents of the file
$tfname = tempnamWithCheck($config->getTempDir(), '');
$highlighted = $svnrep->getFileContents($path, $tfname, $rev, $peg, '', 'line');
 
if ($file = fopen($tfname, 'r'))
{
// Get the blame info
$tbname = tempnamWithCheck($config->getTempDir(), '');
 
$svnrep->getBlameDetails($path, $tbname, $rev, $peg);
 
if ($blame = fopen($tbname, 'r'))
{
// Create an array of version/author/line
 
$index = 0;
$seen_rev = array();
$last_rev = '';
$row_class = '';
 
while (!feof($blame) && !feof($file))
{
$blameline = rtrim(fgets($blame), "\n\r");
 
if ($blameline != '')
{
list($revision, $author, $remainder) = sscanf($blameline, '%d %s %s');
$empty = !$remainder;
 
$listvar = &$listing[$index];
$listvar['lineno'] = $index + 1;
 
if ($last_rev != $revision)
{
$listvar['revision'] = '<a id="l'.$index.'-rev" class="blame-revision" href="'.$config->getURL($rep, $path, 'blame').createRevAndPegString($revision, $peg ? $peg : $rev).'">'.$revision.'</a>';
$seen_rev[$revision] = 1;
$row_class = ($row_class == 'light') ? 'dark' : 'light';
$listvar['author'] = $author;
}
else
{
$listvar['revision'] = '';
$listvar['author'] = '';
}
 
$listvar['row_class'] = $row_class;
$last_rev = $revision;
 
$line = rtrim(fgets($file), "\n\r");
if (!$highlighted)
{
$line = escape(toOutputEncoding($line));
}
$listvar['line'] = ($empty) ? '&nbsp;' : wrapInCodeTagIfNecessary($line);
$index++;
}
}
fclose($blame);
}
 
fclose($file);
@unlink($tbname);
}
@unlink($tfname);
 
// Build the necessary JavaScript as an array of lines, then join them with \n
$javascript = array();
$javascript[] = '<script type="text/javascript" src="'.$locwebsvnhttp.'/javascript/blame-popup.js"></script>';
$javascript[] = '<script type="text/javascript">';
$javascript[] = '/* <![CDATA[ */';
$javascript[] = 'var rev = new Array();';
 
ksort($seen_rev); // Sort revisions in descending order by key
if (empty($peg))
{
$peg = $rev;
}
if (!isset($vars['warning']))
{
foreach ($seen_rev as $key => $val)
{
$history = $svnrep->getLog($path, $key, $key, false, 1, $peg);
 
if ($history && $history->curEntry)
{
$javascript[] = 'rev['.$key.'] = \'<div class="date">'.$history->curEntry->date.'</div><div class="msg">'.addslashes(preg_replace('/\n/', ' ', $history->curEntry->msg)).'</div>\';';
}
}
}
 
$javascript[] = '/* ]]> */';
$javascript[] = '</script>';
$vars['javascript'] = implode("\n", $javascript);
}
 
if (!$rep->hasReadAccess($path, false))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
renderTemplate('blame');
/WebSVN/browse.php
0,0 → 1,40
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// browse.php
//
// Stub for MultiViewsIndex
 
// --- CONFIGURE THESE VARIABLES ---
 
// Location of websvn directory via HTTP
//
// e.g. For "http://www.example.com/websvn" use '/websvn'
//
// Note that browse.php need not be in the /websvn directory (and often isn't).
// If you want to use the root server directory, just use a blank string ('').
$locwebsvnhttp = !empty($_SERVER['CONTEXT_PREFIX']) ? $_SERVER['CONTEXT_PREFIX'] : '/websvn';
 
// Physical location of websvn directory. Change this if your browse.php is not in
// the same directory as the rest of the distribution
$locwebsvnreal = dirname(__FILE__);
 
require $locwebsvnreal.'/multiviews.php';
 
/WebSVN/cache/tmp
1,0 → 0,0
This file is here so that the directory gets included in the ZIP files
This file is here so that the directory gets included in the ZIP files.
/WebSVN/changes.txt
1,20 → 1,147
2.1 alpha 1
2.4.0+
 
* Changed: many cleanups and optimisations.
* Added: more documentation for *.inc files.
* Removed: extraneous bits.
* New: PHP_Compat usage to allow some new PHP5 functionality and remain
backwards-compatible.
* Changed: line endings now use UNIX-style across the board.
This file is discontinued in favor of using milestones per release on GitHub.
 
https://github.com/websvnphp/websvn/releases
https://github.com/websvnphp/websvn/issues/29
 
2.3.3
 
* Fixed security issue (only affecting Windows with enabled downloads)
* Added option to override bugtraq properties in config file (#315)
* Added support for using complete filenames (instead of extensions only) for enscript and GeSHi highlighting (e.g. CMakeLists.txt)
* Added option to ignore whitespaces in diff as default
* Added proper notification if temporary folder is not writable
* Improved path-column in log-view to show most precise path containing all modifications of revision (#313)
* Improved handling of non-existing resources, returning HTTP status code 404 with an error message not containing SVN commands (#321)
* Fixed URLs when using revision form and listing view (partially #314)
* Fixed downloading folders containing whitespaces (#308)
* Fixed inline diff when ignoring whitespaces with PHP 4 (#309)
* Fixed keeping flag to regard/ignore whitespaces in diff when moving to previous/next/youngest revision
* Updated translation: Swedish (#320)
 
2.3.2
 
* Added ability to use plain PHP for creating templates
* Added config option to show last modification in repository list
* Added config option to trust all server certificates
* Added support for using multiple access files
* Added translation: Macedonian, Russian
* Improved navigation through items deleted in recent revision
* Improved ignoring whitespaces (including different newlines) in compare-view
* Updated translation: Dutch
* Updated libraries: GeSHi 1.0.8.9
* Fixed parsing SVN version
* Fixed comparing two revisions
* Fixed regression in revision form
* Fixed issues: 292, 294, 296, 298, 302, 304, 306, 307
 
2.3.1
 
* Added in-line highlighting of diff
* Added links to previous/next revision in various views
* Added config option to block bots from indexing
* Added returning correct http status 403/404 in some cases
* Improved check for path-based authorization
* Fixed usage of Enscript
* Fixed diff of just moved/renamed files
* Fixed strict messages when using PHP 5.3
* Updated libraries: GeSHi 1.0.8.6, PEAR Archive_Tar 1.3.6, PEAR Text_Diff 1.1.1
* Updated install documentation
* Updated translations: Hindi, Marathi, Slovenian
* Fixed issues: 98, 235, 250, 260, 262, 263, 264, 265, 266, 267, 268, 269,
270, 271, 273, 274, 275, 276, 278, 280, 283, 284, 285, 287, 288, 290
 
2.3.0
 
* Better support for moved, renamed and deleted items.
* Improved handling of errors, show useful messages without exposing auth data.
* Improved handling of different character encodings.
Replaced manual per-repository configuration with automatic handling
(using either multibyte string or iconv extension).
* Modified various things in templates (see doc/templates.html).
* Added new theme called "Elegant".
* Added combobox to select template on a per-user base.
* Fixed plain file downloading.
* Added http header 500 for errors with downloading archives/files.
* Updated rss generation.
* Updated french translation.
* Fixed issues: 64, 84, 151, 155, 236, 240, 242, 243, 244, 245, 246, 247, 248,
251, 253, 254, 255, 256, 257, 259
 
2.2.1
 
* Fixed downloading tar-gz-archives when using .gz extension.
* Improved output when svn-command could not be executed correctly.
* Added config option to fully alphabetize, independent of folder or file type.
* Fixed multiple links and minor issues.
* Fixed issues: 212, 213, 214, 215, 216, 217, 219, 222, 223, 224, 225, 227, 228,
229, 230, 231, 232, 234, 237, 238
 
2.2.0
 
* Fixed revision handling to use PEG revision instead of OPERATIVE revision.
* This fixes many (but not all) cases of viewing moved/renamed/deleted files.
* Removed dependencies to external command.
* Added PEAR Archive_Tar.
* Added PEAR Text_Diff.
* Added usage of gzip (.gz extension) if available.
* Added usage of PHP touch function.
* Improved scalability of parent path handling.
* Added support for upcoming PHP 5.3 release.
 
* Added separate customizable extension mapping for GeSHi.
* Added links for choosing whether to ignore whitespace on compare and diff.
* Added support for aliases in auth file; handles continuation lines correctly.
* Added config option to set custom config path.
* Added config option to exclude repositories from those included by parentPath.
* Added config option to add a subpath of a repository (not just at root level).
* Added config option to switch between showing age and date in log and listing
view (the other is displayed in the title attribute and shown when hovering).
* Added auto detection of Windows.
* Added message when config file does not exist.
* Added new logo and favicon.
 
* Fixed some broken links when navigating through a repository.
* Fixed created archive to be identical (for the same revision) across requests.
* This works under Linux with any PHP version and under Windows with PHP 5.3.
* Fixed parsing of access file to support usernames containing equal characters.
 
* Updated translations
* Dutch
* French
* Italian
 
2.1.0
 
* Fixed: Several security fixes.
* Added: Added GeSHi for code highlighting.
* Added: New languages.
* Changed: Separated modified files and directory listing.
* Changed: Updated used libraries.
 
CHANGES
FIX: Patched several XSS vulnerabilities. (Issue 179)
FIX: Hide modified files in revision view based on authentication.
FIX: Numerous other security problems.
NEW: Added translations: hungarian, indonesian, slovak, uzbek.
CHANGED: Some code cleanup.
 
NEW: Template files may now be specified on a per repository basis
NEW: Add RSS 'alternate' <link> elements to the HTML headers in
directory listings. This lets you, for example, easily create a
'live bookmark' in Firefox to monitor commits to a particular SVN path.
NEW: Russian translation.
2.0
 
* Added: More documentation for *.php files.
* Removed: Extraneous bits.
* Changed: Many cleanups and optimisations.
* Changed: Line endings now use UNIX-style across the board.
 
CHANGES
NEW: New default template theme offered by Erik Pöhler.
NEW: Template files may now be specified on a per repository basis.
NEW: RSS 'alternate' <link> elements in HTML headers links to directory listing.
This lets you, for example, easily create an RSS 'live bookmark' to monitor
commits to a particular SVN path.
NEW: Russian translation
 
CHANGE: Bugtraq handling has been updated to account for the latest spec.
 
FIX: Syntax highlighting across lines has been fixed (Issue 85)
21,181 → 148,174
 
2.00 beta 8
 
CHANGE: Remove path comparison boxes when using the flat view display
CHANGE: Tidy up URLs generated from the listing view (Remove default parameters).
CHANGE: wsvn now selectes either the listing or file view automatically when the op parameter
isn't present. This allows for nicer URLS (eg. /http://example.com/wsvn/repo1/myfile.doc)
FIX: Fix warnings when using an access file that didn't define a groups section
FIX: Fix tarballing of directories with spaces
CHANGE: Remove path comparison boxes when using the flat view display.
CHANGE: Tidied URLs generated from the listing view (remove default parameters).
CHANGE: wsvn now selects either the listing or file view automatically when the
"op" parameter isn't present. This allows for simpler, shorter URLS.
(eg. /http://example.com/wsvn/repo1/myfile.txt)
 
FIX: Fix warnings when using an access file that didn't define a groups section.
FIX: Fix tarballing of directories with spaces.
FIX: Path history information in the log view of a file was incorrect.
 
2.00 beta 7
 
NEW: Projects may now be assigned to groups, to simplify the index view
NEW: The index may be displayed as a collapsable tree of groups
NEW: Projects may now be assigned to groups to simplify the index view.
NEW: The index may be displayed as a collapsible tree of groups.
 
CHANGE: The syntax for the per repository configurations has changed. It's now much simpler and
will work on all versions of PHP
CHANGE: The syntax for per-repository configurations has changed is now much
simpler and will work on all versions of PHP.
 
FIX: Various bug fixes for the access rights module
FIX: Language choice selection with MultiViews enabled didn't work
FIX: Various small bugs introduced during 2.0 development
FIX: Various bug fixes for the access rights module.
FIX: Language choice selection with MultiViews enabled didn't work.
FIX: Various small bugs introduced during 2.0 development.
 
2.00 beta 6
 
Note: the $config->addRepository command now takes a URL and not a filesystem path!
Note: $config->addRepository() now takes a URL, not a filesystem path!
 
NEW: WebSVN can now host remote repositories!
 
FIX: The access rights handling didn't work if you had give a repository a display name
different from it's "real" svn name.
FIX: The deleted file list no longer links to non-existant files!
FIX: Neaten the directory display when the download/compare links aren't available
FIX: The access rights handling didn't work if you had give a repository a
display name different from it's "real" svn name.
FIX: The deleted file list no longer links to nonexistent files.
FIX: Tidied the directory display when download/compare links aren't available.
 
2.00 beta 5
 
NEW: Access rights files can now be specified on a per repository basis
NEW: Access rights files can now be specified on a per-repository basis.
 
CHANGE: Further improvements have been made to character encoding handling. In particular,
it is now possible to specify the encoding of the repository contents separately
from the system encoding. This is the case for windows users, whereby the command
line tools typically returning CP850 encoded strings, whereas the source files are
encoded as iso-8859-1. Now, when displaying text files, WebSVN will convert them
from the content encoding to the output encoding (UTF-8).
CHANGE: Further improvements have been made to character encoding handling. In
particular, it is now possible to specify the encoding of the repository
contents separately from the system encoding. This is the case for
Windows users; the command line tools typically returning CP850-encoded
strings, whereas the source files are encoded as iso-8859-1. Now, when
displaying text files, WebSVN will convert from the content encoding to
the output encoding (UTF-8).
CHANGE: Updated Danish translation.
CHANGE: The log display has a "max number of revisions to show" filter option,
which defaults to 30. This significantly improves log view performance.
 
CHANGE: Update Danish translation
CHANGE: The log display has a "max number of revisions to show" fiter option, which defaults
to 30. This significantly improves performance of the log display.
FIX: Correctly display the contents of a file which had brackets in the name.
FIX: Correct problem with download of tarballs containing special characters.
FIX: Improve time display.
FIX: Remove non-UTF8 language options from distconfig.php.
FIX: Fix recent bug where the log messages contained unnecessary blank lines.
FIX: Auth file section groups without a trailing / are now treated correctly.
 
FIX: It wasn't possible to display the contents of a file which had brackets in the name.
FIX: Correct problem with download of tarballs containing special characters
FIX: Improve time display
FIX: Remove non-UTF8 language options from distconfig.inc
FIX: Fix recent bug whereby the log messages would contain unnecessary blank lines
FIX: Access right file section groups without a trailing / are no correctly treated
 
2.00 beta 4
 
NEW: The log display may now be filtered to show a range of revisions
NEW: You can now have control over the specification of directories that can or
cannot be tarball'ed. Tarballing can be turned on only after a certain directory
depth and directories can be allow/disallowed on a per directory/repository basis.
NEW: The user can now choose their language via a drop down box
NEW: The log display may now be filtered to show a range of revisions.
NEW: You can now specify directories that can or cannot be tarballed. Tarballing
can be enabled after only a certain directory depth, and directories can be
(dis)allowed on a per-directory/per-repository basis.
NEW: The user can now choose their language via a drop down box.
 
CHANGE: Character encodings are now handled differently. The output encoding is ALWAYS
defined as UTF-8, and the setOutputEncoding option has been removed.
CHANGE: Character encodings are now handled differently. The output encoding is
always UTF-8, and the setOutputEncoding option has been removed.
 
FIX: Diff had been broken by 1.70 beta 2
FIX: Download of tarballs is prohibited if the user doesn't have read access to the directory
AND all of its subdirectories
FIX: The character set type is now sent in the HTTP header. No need to hack the Apache config
FIX: Diff was broken by 1.70 beta 2.
FIX: Download of a directory is prohibited if the user doesn't have read access
to the directory AND all of its subdirectories.
FIX: The character set type is now sent in the HTTP header automatically.
 
2.00 beta 3
 
NEW: WebSVN may now be configured to display a flat view rather than a tree view
NEW: Config option to display a flat view rather than a tree view.
 
FIX: Only use --limit option on svn 1.2 or greater
FIX: Correct spelling of "danish" in distconfig
FIX: Fix RSS, previously broken 1.7 beta 1
FIX: Only use --limit option on SVN 1.2 or greater.
FIX: Correct spelling of "danish" in distconfig.php.
FIX: RSS was previously broken in 1.7 beta 1.
 
2.00 beta 2
 
CHANGE: WebSVN no longer requires the entire revision history when accessing a directory,
resulting in a faster access for large repositories
CHANGE: No longer requires entire revision history when accessing a directory,
resulting in a faster access for large repositories.
 
FIX: The new access rights module didn't always hide directories
FIX: Tree icons have been fixed (broken in 1.70 beta 1)
FIX: The new access rights module didn't always hide directories.
FIX: Tree icons have been fixed (broken in 1.70 beta 1).
 
2.00 beta 1
 
NEW: Access rights module (Finally!) - see install.txt for details
NEW: Added language file for Danish, Finnish, Turkish, Norwegian and Simplified Chinese
NEW: The "View Log" link is now available for templates to use from the file view
NEW: Added bugtraq:logregex support
NEW: The "View Log" link is now available for templates to use in the file view.
NEW: Added support for "bugtraq:logregex" property.
NEW: Translations for Danish, Finnish, Turkish, Norwegian, Simplified Chinese.
 
CHANGE: Ages are now displayed with higher resolution
CHANGE: Update German translation
CHANGE: Tex file are no longer delivered as binary by defaut, but displayed by enscript
CHANGE: The last modified files display now shows the most recently modified files of
the current directory
CHANGE: Improve diff colours of Blue Grey Scheme for better readability
CHANGE: WebSVN no longer requires the entire revision history when accessing a directory,
resulting in a faster access for large repositories
CHANGE: Ages are now displayed with higher resolution.
CHANGE: Updated German translation.
CHANGE: Text files are no longer delivered as binary by default, but displayed
by Enscript.
CHANGE: The last modified files display now shows the most recently modified
files of the current directory.
CHANGE: Improved diff colours of BlueGrey template for better readability.
 
FIX: Directories containing accents weren't always displayed
FIX: File version can be compared via the log display (as oppoed to just directories)
FIX: Corrected RSS encoding issue
FIX: Corrected bug whereby diff lines would be displayed twice
FIX: svn: Can't check path '/root/.subversion': Permission denied
FIX: Sometimes files delivered (as opposed to disaplyed) by WebSVN were empty
FIX: Fix problem with large tarball delivery
FIX: Compare with previous always used HEAD
FIX: .sh files are now viewable
FIX: Allow special characters in repository names
FIX: It wasn't possible to go into a module if another module starts with the same name.
FIX: Directories containing accents weren't always displayed.
FIX: File revisions can be compared via the log display (not just directories).
FIX: Corrected RSS encoding issue.
FIX: Corrected bug where diff lines would be displayed twice.
FIX: "svn: Can't check path '/root/.subversion': Permission denied"
FIX: Sometimes files delivered (as opposed to displayed) by WebSVN were empty.
FIX: Fix problem with large tarball delivery.
FIX: Compare with previous always used HEAD.
FIX: .sh files are now viewable.
FIX: Allow special characters in repository names.
FIX: Now able to go into a module if another module starts with the same name.
FIX: Remove hard-coded timezone from the RSS feed creator.
FIX: Caching of RSS feeds wasn't working
FIX: Caching of RSS feeds wasn't working.
 
1.62
 
NEW: RSS feed can now list changed files
NEW: Templates can now show an open folder icon
NEW: RSS feed can now list changed files.
NEW: Templates can now show an open folder icon.
NEW: Polish translation
NEW: Dutch translation
 
CHANGE: Window is scrolled to appropriate location when opening a new directory
CHANGE: Window is scrolled to appropriate location when opening a new directory.
 
FIX: Allow repository names containing '/'
FIX: Fixed sloppy HTML in diff templates
FIX: Fix problems with the diff output
FIX: Allow repository names containing '/'.
FIX: Fixed sloppy HTML in diff templates.
FIX: Fix problems with the diff output.
FIX: Repositories on Windows network shares can now be accessed.
FIX: Accented characters weren't shown correctly in the directory comparison
view.
FIX: Remove error when only one revision was available
FIX: Accented characters now display correctly in the directory comparison view.
FIX: Remove error when only one revision was available.
 
1.61
 
NEW: Multibyte encodings are considered when urlencoding path names
NEW: Multibyte encodings are considered when urlencoding path names.
 
CHANGE: The listing view will now always show the revision asked for
(HEAD by default), but the log message will show the log
string for the latest modification to the current directory).
This means the the parent directory structure won't change as you
browse through old directories.
CHANGE: The listing view will now always show the requested revision (HEAD by
default), but the log message will show the log string for the latest
modification to the current directory). This means the parent directory
structure won't change as you browse through old directories.
 
FIX: A bug prevented downloading of tarballs from working
FIX: A bug prevented downloading of tarballs from working.
 
1.60
1.60
 
NEW: Directory displays are now shown in tree view (so that it's harder
to get lost). Many thanks to Brent Lu for this excellent patch.
The prettiest result are available in the BlueGrey scheme.
NEW: Comparison of entire directories
NEW: Directory displays are now shown in tree view (so that it's harder to get
lost). Many thanks to Brent Lu for this excellent patch.
NEW: Comparison of entire directories.
NEW: Tarballs of directories may now be downloaded.
Set $config->allowdownload(); in config.inc to allow this.
NEW: New style 'Zinn' based on the templates created for
http://www.projectzinn.org/. Thanks to Justin Doran.
NEW: File delivery now looks at the defined Mime-Type. Thanks to
Peter Valdemar Mørch for this patch.
NEW: Various configuration options may now be applied on a per project
basis. Look in distconfig for instructions.
Set $config->allowdownload(); in config.php to allow this.
NEW: New 'Zinn' template from http://projectzinn.org/. Thanks to Justin Doran.
NEW: File delivery now looks at the defined Mime-Type. Thanks to
Peter Valdemar Mřrch for this patch.
NEW: Various configuration options may now be applied on a per-project basis.
NEW: Support for using 'bugtraq' properties when display log entries.
See http://svn.collab.net/repos/tortoisesvn/trunk/doc/issuetrackers.txt
NEW: Traditional Chinese translation
NEW: Spanish translation
 
CHANGE: Style information removed from RSS feed
CHANGE: Changed files are now hidden by defaut (since the directory
CHANGE: Changed files are now hidden by default (since the directory
comparison link is far more useful)
 
FIX: File listing were't being shown with the correct accented characters
under windows.
FIX: File listing sometimes failed when there were spaces in the filename
FIX: Some setups wouldn't allow diff generations with enscript
enabled.
FIX: Filenames are URL encoded correctly before calling svn file:///
FIX: Keywords weren't expanded in file view when enscript was disabled
FIX: File listing are now shown with the correct accented characters on Windows.
FIX: File listing sometimes failed when there were spaces in the filename.
FIX: Some setups wouldn't allow diff generations with Enscript enabled.
FIX: Filenames are URL encoded correctly before calling "svn file:///".
FIX: Keywords weren't expanded in file view when Enscript was disabled.
 
1.51
 
202,159 → 322,141
NEW: Korean translation
NEW: Russian translation
 
FIX: Repositories may now have spaces in their path (eg: c:\my reps)
FIX: Diff now works when the file name has changed between versions
FIX: RSS feed now generates Content-Type header for XML so that IE can display
the contents
FIX: Diff and Blame didn't work properly for php files when enscript wasn't used
FIX: Use svn --non-interactive to ensure that svn doesn't prompt WebSVN for input
FIX: Corrections to the French translation
FIX: Display an explanatory message when the user hasn't configured any
repository paths
FIX: When using Multiviews, change to the WebSVN directory before executing
commands so that tempnam works. This used to cause problems on some
systems when running diff and blame.
FIX: Repositories may now have spaces in their path. (eg: c:\my reps)
FIX: Diff now works when the file name has changed between versions.
FIX: RSS feed now generates Content-Type header for XML so IE can display it.
FIX: Diff and blame now work properly for PHP files when Enscript isn't used.
FIX: Use 'svn --non-interactive' so that SVN never prompts WebSVN for input.
FIX: Corrections to the French translation.
FIX: Display a message when no repository paths have been configured.
FIX: Under Multiviews, change to the WebSVN directory before executing commands
so that tempnam() works, so diff and blame work correctly on all systems.
 
1.50
 
Notes: Before installing this version you should delete all the existing
cache files.
wsvn.php has changed. You should redo any appropriate configuration
Notes: Before installing this version you should delete existing cache files.
 
wsvn.php has changed. You should redo any appropriate configuration
changes inside this file.
 
NEW: Blame information for a file can now be viewed
NEW: The cached files are now compressed
NEW: The project selection box shows the current project by default
NEW: Blame information for a file can now be viewed.
NEW: The cached files are now compressed.
NEW: The project selection box shows the current project by default.
NEW: Swedish translation
NEW: Japanese translation
NEW: The install file explains how to set up permission based repository
access such that access via the web interface is the same as access
via a client (assuming Apache2).
NEW: SVN keywords are now expanded in file listings
NEW: The install file explains how to set up permission-based repository access,
such that access via the web interface is the same as access via a client.
NEW: SVN keywords are now expanded in file listings.
 
CHANGE: The extraction of the directory listings is now accomplished using
the svn command via file:/// access rather than svnlook. This has
the advantage of being non-recursive, and thereby eliminates the need
for caching the entire directory listing, and is much quicker on
complex direcory structures. No more 50Mb directory caches!
CHANGE: The extraction of the directory listings is now accomplished using the
'svn' command via file:/// access rather than 'svnlook'. This has the
advantage of being non-recursive, and thereby eliminates the need for
caching the entire directory listing, and is much quicker on complex
directory structures. (Also, no more 50MB directory caches!)
 
FIX: Deleted directories are now viewable.
FIX: SHOWALL was being redefined in the language files
FIX: The directory listing view sometimes showed [lang:DELETEDFILES
FIX: SHOWALL was being redefined in the language files.
FIX: The directory listing view sometimes showed [lang:DELETEDFILES].
FIX: Under Windows, links in the RSS output would start with "\" if WebSVN
was installed in the server's root directory.
FIX: Sed wouldn't work under all versions of Windows due to the use of single
quotes around the paramters
quotes around the parameters.
FIX: Improved character encoding support for log messages etc.
FIX: Paths passed by URL are encoded
FIX: Generated HTML code is strictly 4.01
FIX: Paths passed by URL are encoded.
FIX: Generated HTML code is strictly 4.01.
 
1.40
 
NEW: RSS feed support (thanks to Lübbe Onken for his work on this)
NEW: Translatations for French and Portuguese
NEW: .exe is recognised by default as having content-type
application/x-msdownload
NEW: Recognised links are now 'linkified' in the log messages
NEW: Tabs in file/diff listings are now expanded by a user
configurable number of spaces.
NEW: WebSVN URLs now access the repository by name rather than number.
This means that bookmarks will stay the same when new projects
are added. The old behaviour can be configured in config.inc.
NEW: RSS feed support. (Thanks to Lübbe Onken for his work on this.)
NEW: Translatations for French and Portuguese.
NEW: .exe files now default to content-type "application/x-msdownload".
NEW: Recognised links are now 'linkified' in the log messages.
NEW: Option to change number of spaces to use for tabs in file/diff listings.
NEW: URLs now access the repository by name rather than number. This means that
bookmarks will stay the same when new projects are added. The old behaviour
can be configured in config.php.
 
FIX: Removed the revision 0 that has appeared since the previous version
FIX: Repositories were not sorted alphabetically when using ParentPath
FIX: The PNG support script needed for IE (and the BlueGrey scheme) is
now only loaded with IE
FIX: Removed the revision 0 that has appeared since the previous version.
FIX: Repositories were not sorted alphabetically when using ParentPath.
FIX: The PNG support script (and the BlueGrey scheme) is now only loaded for IE.
 
1.39
 
CHANGE: In the human-readable date strings, display up to 119 minutes,
47 hours, 13 days or 23 months before moving up to the next
quantity, like ViewCVS.
CHANGE: In the human-readable date strings, display up to 119 minutes, 47 hours,
13 days or 23 months before moving up to the next unit, like ViewCVS.
 
FIX: Links followed after viewing the contents of a file go to the
revision of the repository previously being viewed
FIX: Paths with spaces are now correctly showed in the log view
FIX: Blank lines in the diff output are set to &nbsp; so the browser
won't compress them
FIX: Links from file detail view now go to the current (not previous) revision.
FIX: Paths with spaces are now correctly showed in the log view.
FIX: Blank lines in diff output are set to &nbsp; so browsers will display them.
FIX: A blank author field is set to an &nbsp; cell.
FIX: A year is 365 days, not 356.
FIX: Base ages correctly upon GMT
FIX: The diff output did not escape html entities when enscript was
enabled and the file extension was not recognised for enscript.
FIX: distconfig.inc has a few minor errors in the examples.
FIX: It wasn't possible to call ParentPath multiple times
FIX: Base ages correctly upon GMT.
FIX: The diff output did not escape html entities when Enscript was enabled and
the file extension was not recognised for Enscript.
FIX: distconfig.php had a few minor errors in the examples.
FIX: It wasn't possible to call ParentPath multiple times.
 
1.38
 
NEW: Templates can now define icons for particular file types
(see BlueGrey scheme for an example)
NEW: Display of PHP files with syntax highlighting
NEW: Improve site navigation with links to each directory level on all
pages.
NEW: Templates can now define icons for particular file types (see BlueGrey).
NEW: Display of PHP files with syntax highlighting.
NEW: Improve site navigation with links to each directory level on all pages.
 
1.37
 
NEW: Display a message when there are no results found
NEW: Display a message when there are no results found.
 
CHANGE: Aesthetic changes to the BlueGrey scheme
CHANGE: Sort entries more naturally
CHANGE: Aesthetic changes to the BlueGrey scheme.
CHANGE: Sort entries more naturally.
 
FIX: Really make sure that we redirect to the right place when using the
drop-down box to select projects.
FIX: Nested [webtest]'s didn't always work
FIX: Fixed use of "standard" and "Standard", which caused problems on
non-windows machines
FIX: Redirect to the right URL when using the drop-down box to select projects.
FIX: Nested [websvn-test] elements didn't always work.
FIX: Fixed use of "standard" vs "Standard", problematic on non-Windows machines.
 
1.36
 
NEW: Log message search feature
NEW: Diff display tries to display changed lines as changed, rather than
showing the line deleted then added.
NEW: Log message search feature.
NEW: Diff display tries to display changed lines as changed, rather than showing
the line as deleted then added.
 
FIX: Problem surrounding the quoting of commands and command line arguments
on Windows machines.
FIX: Problem with quoting of commands and command line arguments on Windows.
 
1.35
 
NEW: You can now specify a list of file types (extensions) for files which
should be delivered to the user in a GZIP'd archive rather than
displayed as ASCII in the browser window.
NEW: You can now specify a list of file types (extensions) for files that should
be delivered to the user in a GZIP'd archive rather than displayed as ASCII
in the browser window.
 
CHANGE: Files delived with a MIME Content type are now sent as "inline".
The browser will try to display them in the browser window, offering
a save box only if they can't be displayed in this mannor.
CHANGE: Files delivered with a MIME Content type are now sent as "inline". The
browser will try to display them in the browser window, offering a save
box only if they can't be displayed in this manner.
 
FIX: Detect use of the HTTPS protocol when using the drop-down box to
select projects. (-- FIX INCORRECT. USE v1.36 -- )
FIX: The PNGs in the BlueGrey style are now transparent under Internet
Explorer 5.5 and higher.
FIX: Detect use of the HTTPS protocol when using the drop-down box to select
projects. (-- FIX INCORRECT. USE v1.36 -- )
FIX: The PNGs in the BlueGrey style are now transparent under IE 5.5 and higher.
 
1.34
 
NEW: Support for switching between projects using a drop-down box control
(MultiViews users - note that wsvn.php has been changed)
NEW: Sort the repositories alphabetically when using parentPath
NEW: Better support for internationalisation
(Template writers: Please note the use of the new variable 'charset')
NEW: More useful info in browser titles with the standard templates
NEW: Support for switching between projects using a drop-down box control.
(MultiViews users - note that wsvn.php has been changed.)
NEW: Sort the repositories alphabetically when using parentPath.
NEW: Better support for internationalisation.
(Template writers: Please note the use of the new variable 'charset'.)
NEW: More useful info in browser titles with the standard templates.
 
FIX: Accented characters should now be displayed correctly (I hope).
FIX: HTML files now display correcly on all machines
FIX: Removed spurious BRs from the file listings
FIX: HTML files now display correctly on all machines.
FIX: Removed spurious BRs from the file listings.
 
1.33
 
There are a few changes to the config file in this release. Copy
distconfig.inc to config.inc and redo any configuration changes that you
had made.
There are a few changes to the config file in this release. Copy distconfig.php
to config.php and redo any configuration changes that you had made.
 
NEW: Recognised non-text files are now delivered to the user as attachments.
The list of files types to be sent back to the user (rather than displayed
using WebSVN) is user configurable.
NEW: File comparisons are now colourised based on the file extension
NEW: The list of files types to be sent to the user (rather than displayed with
WebSVN) is now user-configurable.
NEW: File comparisons are now colourised based on the file extension.
 
CHANGE: Only the Enscript file extensions that the user wishes to override are
now listed in the config file.
361,102 → 463,94
 
1.32
 
FIX: Links no longer functionned correctly when used in basic
(non-multiviews) mode.
FIX: Links now function correctly when used in basic (not multiviews) mode.
FIX: Stop diff from comparing space changes
 
1.31
 
FIX: Directory view had disappeared!
FIX: Included missing file setup.inc
FIX: Handle spaces in filenames
FIX: Included missing setup.php file.
FIX: Handle spaces in filenames.
 
1.30
 
There are a few changes to the config file in this release. Copy
distconfig.inc to config.inc and redo any configuration changes that you
had made.
There are a few changes to the config file in this release. Copy distconfig.php
to config.php and redo any configuration changes that you had made.
 
NEW: MultiViews support. You can now set up WebSVN to access the
repositories using a URL such as:
NEW: MultiViews support allows access to repositories using a URL such as:
 
http://server/wsvn/repname/path/to/rep
 
NEW: Colourisation support using Enscript
NEW: [websvn-test] function can now be nested
NEW: locwebsvnhttp variable added in template system
NEW: Bluegrey scheme now has show/hide changed link
NEW: Colourisation support using Enscript.
NEW: [websvn-test] function can now be nested.
NEW: locwebsvnhttp variable added in template system.
NEW: BlueGrey scheme now has show/hide changed link.
 
FIX: Possible security hole with abuse of popen
FIX: WebSVN should now function correctly (again) on non windows servers.
FIX: First character of diff listing was missing
FIX: Possible security hole with abuse of popen().
FIX: Should now function correctly (again) on non-Windows servers.
FIX: First character of diff listing was missing.
 
1.20
 
NEW: Comprehensive templating solution
NEW: Show the age of a revision in the log view
NEW: Comprehensive templating solution.
NEW: Show the age of a revision in the log view.
 
CHANGE: The youngest revision of the current directory is now shown by
default (as opposed to the head revision of the entire repository.
This means that clicking on a directory will show the lastest
changes associated with it. A specific revision can still be
selected from a log view
CHANGE: The youngest revision of the current directory is now shown by default
(as opposed to the head revision of the entire repository). This means
that clicking a directory shows the latest changes associated with it.
Specific revisions can still be selected from a log view.
CHANGE: Only show the leaf name when viewing directory contents
 
FIX: Fixed error concerning use of pclose
FIX: Fixed error concerning use of pclose()
 
1.10/1.10a
 
There are a few changes to the config file in this release. Copy
distconfig.inc to config.inc and redo any configuration changes that you
had made.
There are a few changes to the config file in this release. Copy distconfig.php
to config.php and redo any configuration changes that you had made.
 
NEW: WebSVN now caches information on the repositories. Once a revision
has been viewed subsequent revisions use the cached infomation to
display the directory structure. This significantly improves the
browsing speed.
NEW: WebSVN now caches information on the repositories. Once a revision has been
viewed, subsequent revisions use the cached information to display the
directory structure. This significantly improves the browsing speed.
NEW: German language file (thanks to Stephan Stapel)
 
1.04/1.04a
 
Please note that the config file is now stored in include/
Please note that the config file is now stored in the "include" subdirectory.
 
FIX: Directories in the log view lacked their trailing slashes.
FIX: Diff is now far more efficient with Apache's memory,
and shows the corrrect line numbers.
FIX: Diff is now far more memory-efficient, and shows the correct line numbers.
FIX: setDiffPath now works.
FIX: Bug introduced in 1.03 whereby the revision number always showed '1'
corrected.
FIX: Bug introduced in 1.03 whereby the revision number always showed '1'.
 
Note that you can't view logs with 1.04! Use 1.04a.
Note that you can't view logs with 1.04! Use 1.04a instead.
 
1.03
 
Note that the config.inc file has completely changed in this release, in
order to make it more "future proof" and resiliant. You'll need to copy
distconfig.inc to config.inc redo the appropriate changes are described.
Note that the config.php file has completely changed in this release, in order
to make it more "future proof" and resilient. You'll need to copy distconfig.php
to config.php redo the appropriate changes as described.
 
NEW: A 'ParentPath' can now be specified, rather than having to specify the
directories by hand.
 
FIX: Rewrite of the file list code. Should now be quite a bit faster
FIX: Use a more memory efficient algorithm to list file contents
FIX: Spaces in Windows path to svnlook and diff are now handled properly
FIX: Calls to external commands such as svnlook no longer require Windows
style line endings.
FIX: Rewrite of the file list code. Should now be quite a bit faster.
FIX: Use a more memory efficient algorithm to list file contents.
FIX: Spaces in Windows path to svnlook and diff are now handled properly.
FIX: Calls to external commands such as svnlook no longer require Windows-style
line endings.
 
1.02
 
NEW: Improved command handling to report returned errors. Considerably helps
NEW: Improved command handling to report returned errors. Considerably helps
initial installation problems.
NEW: Show the author of each revision in the log view
NEW: Show the author of each revision in the log view.
 
FIX: Removed the spurious &nbsp that some people were seeing
FIX: Removed the spurious &nbsp; that some people were seeing.
 
1.01 (5 Feb 2004)
 
FIX: Files with HTML content are now shown correcty
FIX: The diff output had the revision lables the wrong way round
FIX: Files with HTML content are now shown correctly.
FIX: The diff output had the revision labels the wrong way round.
 
1.00 (4 Feb 2004)
 
/WebSVN/comp.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,345 → 9,618
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// comp.php
//
// Compare two paths using "svn diff"
// Compare two paths using `svn diff`
//
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
 
$svnrep = new SVNRepository($rep);
function checkRevision($rev)
{
if (is_numeric($rev) && ((int)$rev > 0))
{
return $rev;
}
return 'HEAD';
}
 
function checkRevision($rev)
// Make sure that we have a repository
if (!$rep)
{
if (is_numeric($rev) && ((int)$rev > 0))
return $rev;
$rev = strtoupper($rev);
switch($rev)
{
case "HEAD":
case "PREV":
case "COMMITTED":
return $rev;
}
return "HEAD";
renderTemplate404('compare','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
// Retrieve the request information
$path1 = @$_REQUEST["compare"][0];
$path2 = @$_REQUEST["compare"][1];
$rev1 = @$_REQUEST["compare_rev"][0];
$rev2 = @$_REQUEST["compare_rev"][1];
$path1 = @$_REQUEST['compare'][0];
$path2 = @$_REQUEST['compare'][1];
$rev1 = (int)@$_REQUEST['compare_rev'][0];
$rev2 = (int)@$_REQUEST['compare_rev'][1];
$manualorder = (@$_REQUEST['manualorder'] == 1);
$ignoreWhitespace = $config->getIgnoreWhitespacesInDiff();
 
if (array_key_exists('ignorews', $_REQUEST))
{
$ignoreWhitespace = (bool)$_REQUEST['ignorews'];
}
 
// Some page links put the revision with the path...
if (strpos($path1, "@")) list($path1, $rev1) = explode("@", $path1);
if (strpos($path2, "@")) list($path2, $rev2) = explode("@", $path2);
if ($path1 && strpos($path1, '@'))
{
list($path1, $rev1) = explode('@', $path1);
}
else if ($path1 && (strpos($path1, '@') === 0))
{
// Something went wrong. The path is missing.
$rev1 = substr($path1, 1);
$path1 = '/';
}
 
if ($path2 && strpos($path2, '@'))
{
list($path2, $rev2) = explode('@', $path2);
}
else if ($path2 && (strpos($path2, '@') === 0))
{
$rev2 = substr($path2, 1);
$path2 = '/';
}
 
$rev1 = checkRevision($rev1);
$rev2 = checkRevision($rev2);
 
// Choose a sensible comparison order unless told not to
if (!@$_REQUEST["manualorder"] && is_numeric($rev1) && is_numeric($rev2))
 
if (!$manualorder && is_numeric($rev1) && is_numeric($rev2) && $rev1 > $rev2)
{
if ($rev1 > $rev2)
{
$temppath = $path1;
$temprev = $rev1;
$path1 = $path2;
$rev1 = $rev2;
$path2 = $temppath;
$rev2 = $temprev;
}
$temppath = $path1;
$path1 = $path2;
$path2 = $temppath;
 
$temprev = $rev1;
$rev1 = $rev2;
$rev2 = $temprev;
}
 
$url = $config->getURL($rep, "/", "comp");
$vars["revlink"] = "<a href=\"${url}compare%5B%5D=".urlencode($path2)."@$rev2&amp;compare%5B%5D=".urlencode($path1)."@$rev1&manualorder=1\">${lang["REVCOMP"]}</a>";
$vars['rev1url'] = $config->getURL($rep, $path1, 'dir').createRevAndPegString($rev1, $rev1);
$vars['rev2url'] = $config->getURL($rep, $path2, 'dir').createRevAndPegString($rev2, $rev2);
 
if ($rev1 == 0) $rev1 = "HEAD";
if ($rev2 == 0) $rev2 = "HEAD";
$url = $config->getURL($rep, '', 'comp');
$vars['reverselink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.'&amp;compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;manualorder=1'.($ignoreWhitespace ? '&amp;ignorews=1' : '').'">'.$lang['REVCOMP'].'</a>';
$toggleIgnoreWhitespace = '';
 
$vars["repname"] = $rep->getDisplayName();
$vars["action"] = $lang["PATHCOMPARISON"];
$vars["compare_form"] = "<form action=\"$url\" method=\"post\" name=\"compareform\">";
$vars["compare_path1input"] = "<input type=\"text\" size=\"40\" name=\"compare[0]\" value=\"$path1\" />";
$vars["compare_rev1input"] = "<input type=\"text\" size=\"5\" name=\"compare_rev[0]\" value=\"$rev1\" />";
$vars["compare_path2input"] = "<input type=\"text\" size=\"40\" name=\"compare[1]\" value=\"$path2\" />";
$vars["compare_rev2input"] = "<input type=\"text\" size=\"5\" name=\"compare_rev[1]\" value=\"$rev2\" />";
$vars["compare_submit"] = "<input name=\"comparesubmit\" type=\"submit\" value=\"${lang["COMPAREPATHS"]}\" />";
$vars["compare_endform"] = "<input type=\"hidden\" name=\"op\" value=\"comp\" /><input type=\"hidden\" name=\"manualorder\" value=\"1\" /><input type=\"hidden\" name=\"sc\" value=\"$showchanged\" /></form>";
if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff())
{
$toggleIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '0' : '1');
}
 
# safe paths are a hack for fixing XSS sploit
$vars["path1"] = $path1;
$vars['safepath1'] = htmlentities($path1);
$vars["path2"] = $path2;
$vars['safepath2'] = htmlentities($path2);
if (!$ignoreWhitespace)
{
$vars['ignorewhitespacelink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.($manualorder ? '&amp;manualorder=1' : '').$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>';
}
else
{
$vars['regardwhitespacelink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.($manualorder ? '&amp;manualorder=1' : '').$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>';
}
 
$vars["rev1"] = $rev1;
$vars["rev2"] = $rev2;
if ($rev1 == 0) $rev1 = 'HEAD';
if ($rev2 == 0) $rev2 = 'HEAD';
 
$vars['repname'] = escape($rep->getDisplayName());
$vars['action'] = $lang['PATHCOMPARISON'];
 
$hidden = '<input type="hidden" name="manualorder" value="1" />';
 
if ($config->multiViews)
{
$hidden .= '<input type="hidden" name="op" value="comp"/>';
}
else
{
$hidden .= '<input type="hidden" name="repname" value="'.$repname.'" />';
}
 
$vars['compare_form'] = '<form method="get" action="'.$url.'" id="compare">'.$hidden;
$vars['compare_path1input'] = '<input type="text" size="40" name="compare[0]" value="'.escape($path1).'" />';
$vars['compare_path2input'] = '<input type="text" size="40" name="compare[1]" value="'.escape($path2).'" />';
$vars['compare_rev1input'] = '<input type="text" size="5" name="compare_rev[0]" value="'.$rev1.'" />';
$vars['compare_rev2input'] = '<input type="text" size="5" name="compare_rev[1]" value="'.$rev2.'" />';
$vars['compare_submit'] = '<input name="comparesubmit" type="submit" value="'.$lang['COMPAREPATHS'].'" />';
$vars['compare_endform'] = '</form>';
 
$vars['safepath1'] = escape($path1);
$vars['safepath2'] = escape($path2);
 
$vars['rev1'] = $rev1;
$vars['rev2'] = $rev2;
 
$history1 = $svnrep->getLog($path1, $rev1, 0, false, 1);
if (!$history1)
{
renderTemplate404('compare','NOPATH');
}
else
{
$history2 = $svnrep->getLog($path2, $rev2, 0, false, 1);
 
if (!$history2)
{
renderTemplate404('compare','NOPATH');
}
}
 
// Set variables used for the more recent of the two revisions
$history = ($rev1 >= $rev2 ? $history1 : $history2);
if ($history && $history->curEntry)
{
$logEntry = $history->curEntry;
$vars['rev'] = $logEntry->rev;
$vars['peg'] = $peg;
$vars['date'] = $logEntry->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date));
$vars['author'] = $logEntry->author;
$vars['log'] = xml_entities($logEntry->msg);
}
else
{
$vars['warning'] = 'Problem with comparison.';
}
 
$noinput = empty($path1) || empty($path2);
$listing = array();
 
// Generate the diff listing
$path1 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path1));
$path2 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path2));
 
$relativePath1 = $path1;
$relativePath2 = $path2;
 
$svnpath1 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path1 ?? '')));
$svnpath2 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path2 ?? '')));
 
$debug = false;
 
if (!$noinput)
if (!$noinput)
{
$rawcmd = $config->svn." diff ".$rep->svnParams().quote($path1."@".$rev1)." ".quote($path2."@".$rev2);
$cmd = quoteCommand($rawcmd, true);
if ($debug) echo "$cmd\n";
$cmd = $config->getSvnCommand().$rep->svnCredentials().' diff '.($ignoreWhitespace ? '-x "-w --ignore-eol-style" ' : '').quote($svnpath1.'@'.$rev1).' '.quote($svnpath2.'@'.$rev2);
}
 
function clearVars()
function clearVars()
{
global $listing, $index;
$listing[$index]["newpath"] = null;
$listing[$index]["endpath"] = null;
$listing[$index]["info"] = null;
$listing[$index]["diffclass"] = null;
$listing[$index]["difflines"] = null;
$listing[$index]["enddifflines"] = null;
$listing[$index]["properties"] = null;
}
global $ignoreWhitespace, $listing, $index;
 
$vars["success"] = false;
if ($ignoreWhitespace && $index > 1)
{
$endBlock = false;
$previous = $index - 1;
if ($listing[$previous]['endpath']) $endBlock = 'newpath';
else if ($listing[$previous]['enddifflines']) $endBlock = 'difflines';
 
if (!$noinput)
{
if ($diff = popen($cmd, "r"))
{
$index = 0;
$indiff = false;
$indiffproper = false;
$getLine = true;
$node = null;
$vars["success"] = true;
while (!feof($diff))
{
if ($getLine)
$line = fgets($diff);
clearVars();
$getLine = true;
if ($debug) print "Line = '$line'<br />" ;
if ($indiff)
{
// If we're in a diff proper, just set up the line
if ($indiffproper)
{
if ($line[0] == " " || $line[0] == "+" || $line[0] == "-")
{
switch ($line[0])
{
case " ":
$listing[$index]["diffclass"] = "diff";
$subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
if (empty($subline)) $subline = "&nbsp;";
$listing[$index++]["line"] = $subline;
if ($debug) print "Including as diff: $subline<br />";
break;
case "+":
$listing[$index]["diffclass"] = "diffadded";
$subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
if (empty($subline)) $subline = "&nbsp;";
$listing[$index++]["line"] = $subline;
if ($debug) print "Including as added: $subline<br />";
break;
case "-":
$listing[$index]["diffclass"] = "diffdeleted";
$subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
if (empty($subline)) $subline = "&nbsp;";
$listing[$index++]["line"] = $subline;
if ($debug) print "Including as removed: $subline<br />";
break;
}
continue;
}
else
{
$indiffproper = false;
$listing[$index++]["enddifflines"] = true;
$getLine = false;
if ($debug) print "Ending lines<br />";
continue;
}
}
// Check for the start of a new diff area
if (!strncmp($line, "@@", 2))
{
$pos = strpos($line, "+");
$posline = substr($line, $pos);
sscanf($posline, "+%d,%d", $sline, $eline);
if ($debug) print "sline = '$sline', eline = '$eline'<br />";
// Check that this isn't a file deletion
if ($sline == 0 && $eline == 0)
{
$line = fgets($diff);
if ($debug) print "Ignoring: $line<br />" ;
while ($line[0] == " " || $line[0] == "+" || $line[0] == "-")
{
$line = fgets($diff);
if ($debug) print "Ignoring: $line<br />" ;
}
$getLine = false;
if ($debug) print "Unignoring previous - marking as deleted<b>";
$listing[$index++]["info"] = $lang["FILEDELETED"];
}
else
{
$listing[$index++]["difflines"] = $line;
$indiffproper = true;
}
continue;
}
else
{
$indiff = false;
if ($debug) print "Ending diff";
}
}
// Check for a new node entry
if (strncmp(trim($line), "Index: ", 7) == 0)
{
// End the current node
if ($node)
{
$listing[$index++]["endpath"] = true;
clearVars();
}
$node = trim($line);
$node = substr($node, 7);
$listing[$index]["newpath"] = $node;
if ($debug) echo "Creating node $node<br />";
// Skip past the line of ='s
$line = fgets($diff);
if ($debug) print "Skipping: $line<br />" ;
// Check for a file addition
$line = fgets($diff);
if ($debug) print "Examining: $line<br />" ;
if (strpos($line, "(revision 0)"))
$listing[$index]["info"] = $lang["FILEADDED"];
if (strncmp(trim($line), "Cannot display:", 15) == 0)
{
$index++;
clearVars();
$listing[$index++]["info"] = $line;
continue;
}
// Skip second file info
$line = fgets($diff);
if ($debug) print "Skipping: $line<br />" ;
$indiff = true;
$index++;
continue;
}
if (strncmp(trim($line), "Property changes on: ", 21) == 0)
{
$propnode = trim($line);
$propnode = substr($propnode, 21);
if ($debug) print "Properties on $propnode (cur node $ $node)";
if ($propnode != $node)
{
if ($node)
{
$listing[$index++]["endpath"] = true;
clearVars();
}
$node = $propnode;
$listing[$index++]["newpath"] = $node;
clearVars();
}
$listing[$index++]["properties"] = true;
clearVars();
if ($debug) echo "Creating node $node<br />";
// Skip the row of underscores
$line = fgets($diff);
if ($debug) print "Skipping: $line<br />" ;
while ($line = trim(fgets($diff)))
{
$listing[$index++]["info"] = $line;
clearVars();
}
continue;
}
// Check for error messages
if (strncmp(trim($line), "svn: ", 5) == 0)
{
$listing[$index++]["info"] = urldecode($line);
$vars["success"] = false;
continue;
}
$listing[$index++]["info"] = $line;
}
if ($node)
{
clearVars();
$listing[$index++]["endpath"] = true;
}
if ($debug) print_r($listing);
}
if ($endBlock !== false)
{
// check if block ending at previous contains real diff data
$i = $previous;
$containsOnlyEqualDiff = true;
$addedLines = array();
$removedLines = array();
while ($i >= 0 && !$listing[$i - 1][$endBlock])
{
$diffclass = $listing[$i - 1]['diffclass'];
 
if ($diffclass !== 'diffadded' && $diffclass !== 'diffdeleted')
{
if ($addedLines !== $removedLines)
{
$containsOnlyEqualDiff = false;
break;
}
}
 
if (count($addedLines) > 0 && $addedLines === $removedLines)
{
$addedLines = array();
$removedLines = array();
}
 
if ($diffclass === 'diff')
{
$i--;
continue;
}
 
if ($diffclass === null)
{
$containsOnlyEqualDiff = false;
break;;
}
 
if ($diffclass === 'diffdeleted')
{
if (count($addedLines) <= count($removedLines))
{
$containsOnlyEqualDiff = false;
break;;
}
 
array_unshift($removedLines, $listing[$i - 1]['line']);
$i--;
continue;
}
 
if ($diffclass === 'diffadded')
{
if (count($removedLines) > 0)
{
$containsOnlyEqualDiff = false;
break;;
}
 
array_unshift($addedLines, $listing[$i - 1]['line']);
$i--;
continue;
}
 
assert(false);
}
 
if ($containsOnlyEqualDiff)
{
$containsOnlyEqualDiff = $addedLines === $removedLines;
}
 
// remove blocks which only contain diffclass=diff and equal removes and adds
if ($containsOnlyEqualDiff)
{
for ($j = $i - 1; $j < $index; $j++)
{
unset($listing[$j]);
}
 
$index = $i - 1;
}
}
}
 
$listvar = &$listing[$index];
$listvar['newpath'] = null;
$listvar['endpath'] = null;
$listvar['info'] = null;
$listvar['diffclass'] = null;
$listvar['difflines'] = null;
$listvar['enddifflines'] = null;
$listvar['properties'] = null;
}
 
$vars["version"] = $version;
$vars['success'] = false;
 
if (!$rep->hasUnrestrictedReadAccess($path1) || !$rep->hasUnrestrictedReadAccess($path2, false))
$vars["noaccess"] = true;
if (!$noinput)
{
// TODO: Report warning/error if comparison encounters any problems
if ($diff = popenCommand($cmd, 'r'))
{
$listing = array();
$index = 0;
$indiff = false;
$indiffproper = false;
$getLine = true;
$node = null;
$bufferedLine = false;
 
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."compare.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
?>
$vars['success'] = true;
 
while (!feof($diff))
{
if ($getLine)
{
if ($bufferedLine === false)
{
$bufferedLine = rtrim(fgets($diff), "\n\r");
}
 
$newlineR = strpos($bufferedLine, "\r");
$newlineN = strpos($bufferedLine, "\n");
if ($newlineR === false && $newlineN === false)
{
$line = $bufferedLine;
$bufferedLine = false;
}
else
{
$newline = ($newlineR < $newlineN ? $newlineR : $newlineN);
$line = substr($bufferedLine, 0, $newline);
$bufferedLine = substr($bufferedLine, $newline + 1);
}
}
 
clearVars();
$getLine = true;
if ($debug) print 'Line = "'.$line.'"<br />';
if ($indiff)
{
// If we're in a diff proper, just set up the line
if ($indiffproper)
{
if (strlen($line) > 0 && ($line[0] == ' ' || $line[0] == '+' || $line[0] == '-'))
{
$subline = escape(toOutputEncoding(substr($line, 1)));
$subline = rtrim($subline, "\n\r");
$subline = ($subline) ? expandTabs($subline) : '&nbsp;';
$listvar = &$listing[$index];
$listvar['line'] = $subline;
 
switch ($line[0])
{
case ' ':
$listvar['diffclass'] = 'diff';
if ($debug) print 'Including as diff: '.$subline.'<br />';
break;
 
case '+':
$listvar['diffclass'] = 'diffadded';
if ($debug) print 'Including as added: '.$subline.'<br />';
break;
 
case '-':
$listvar['diffclass'] = 'diffdeleted';
if ($debug) print 'Including as removed: '.$subline.'<br />';
break;
}
$index++;
}
else if ($line != '\ No newline at end of file')
{
$indiffproper = false;
$listing[$index++]['enddifflines'] = true;
$getLine = false;
if ($debug) print 'Ending lines<br />';
}
continue;
}
 
// Check for the start of a new diff area
if (!strncmp($line, '@@', 2))
{
$pos = strpos($line, '+');
$posline = substr($line, $pos);
$sline = 0;
$eline = 0;
sscanf($posline, '+%d,%d', $sline, $eline);
 
if ($debug) print 'sline = "'.$sline.'", eline = "'.$eline.'"<br />';
 
// Check that this isn't a file deletion
if ($sline == 0 && $eline == 0)
{
$line = fgets($diff);
if ($debug) print 'Ignoring: "'.$line.'"<br />';
 
while ($line && ($line[0] == ' ' || $line[0] == '+' || $line[0] == '-'))
{
$line = fgets($diff);
if ($debug) print 'Ignoring: "'.$line.'"<br />';
}
 
$getLine = false;
if ($debug) print 'Unignoring previous - marking as deleted<br />';
$listing[$index++]['info'] = $lang['FILEDELETED'];
 
}
else
{
$listvar = &$listing[$index];
$listvar['difflines'] = $line;
$sline = 0;
$slen = 0;
$eline = 0;
$elen = 0;
sscanf($line, '@@ -%d,%d +%d,%d @@', $sline, $slen, $eline, $elen);
$listvar['rev1line'] = $sline;
$listvar['rev1len'] = $slen;
$listvar['rev2line'] = $eline;
$listvar['rev2len'] = $elen;
 
$indiffproper = true;
 
$index++;
}
 
continue;
 
}
else
{
$indiff = false;
if ($debug) print 'Ending diff';
}
}
 
// Check for a new node entry
if (strncmp(trim($line), 'Index: ', 7) == 0)
{
// End the current node
if ($node)
{
$listing[$index++]['endpath'] = true;
clearVars();
}
 
$node = trim(toOutputEncoding($line));
$node = substr($node, 7);
if ($node == '' || $node[0] != '/') $node = '/'.$node;
 
if (substr($path2, -strlen($node)) === $node)
{
$absnode = $path2;
}
else
{
$absnode = $path2;
if (substr($absnode, -1) == '/') $absnode = substr($absnode, 0, -1);
$absnode .= $node;
}
 
$listvar = &$listing[$index];
$listvar['newpath'] = escape($absnode);
 
$listvar['fileurl'] = $config->getURL($rep, $absnode, 'file').'rev='.$rev2;
 
if ($debug) echo 'Creating node '.$node.'<br />';
 
// Skip past the line of ='s
$line = fgets($diff);
if ($debug) print 'Skipping: '.$line.'<br />';
 
// Check for a file addition
$line = fgets($diff);
if ($debug) print 'Examining: '.$line.'<br />';
if (strpos($line, '(revision 0)'))
{
$listvar['info'] = $lang['FILEADDED'];
}
 
if (strncmp(trim($line), 'Cannot display:', 15) == 0)
{
$index++;
clearVars();
$listing[$index++]['info'] = escape(toOutputEncoding(rtrim($line, "\n\r")));
continue;
}
 
// Skip second file info
$line = fgets($diff);
if ($debug) print 'Skipping: '.$line.'<br />';
 
$indiff = true;
$index++;
 
continue;
}
 
if (strncmp(trim($line), 'Property changes on: ', 21) == 0)
{
$propnode = trim($line);
$propnode = substr($propnode, 21);
if ($propnode == '' || $propnode[0] != '/') $propnode = '/'.$propnode;
 
if ($debug) print 'Properties on '.$propnode.' (cur node $ '.$node.')';
if ($propnode != $node)
{
if ($node)
{
$listing[$index++]['endpath'] = true;
clearVars();
}
 
$node = $propnode;
 
$listing[$index++]['newpath'] = escape(toOutputEncoding($node));
clearVars();
}
 
$listing[$index++]['properties'] = true;
clearVars();
if ($debug) echo 'Creating node '.$node.'<br />';
 
// Skip the row of underscores
$line = fgets($diff);
if ($debug) print 'Skipping: '.$line.'<br />';
 
while ($line = rtrim(fgets($diff), "\n\r"))
{
if (!strncmp(trim($line), 'Index: ', 7))
{
break;
}
if (!strncmp(trim($line), '##', 2) || $line == '\ No newline at end of file')
{
continue;
}
$listing[$index++]['info'] = escape(toOutputEncoding($line));
clearVars();
}
$getLine = false;
 
continue;
}
 
// Check for error messages
if (strncmp(trim($line), 'svn: ', 5) == 0)
{
$listing[$index++]['info'] = urldecode($line);
$vars['success'] = false;
continue;
}
 
$listing[$index++]['info'] = escape(toOutputEncoding($line));
if (strlen($line) === 0)
{
if (!isset($vars['warning']))
{
$vars['warning'] = "No changes between revisions";
}
}
}
 
if ($node)
{
clearVars();
$listing[$index++]['endpath'] = true;
}
 
if ($debug) print_r($listing);
 
if (!$rep->hasUnrestrictedReadAccess($relativePath1) || !$rep->hasUnrestrictedReadAccess($relativePath2, false))
{
// check every item for access and remove it if read access is not allowed
$restricted = array();
$inrestricted = false;
foreach ($listing as $i => $item)
{
if ($item['newpath'] !== null)
{
$newpath = $item['newpath'];
$inrestricted = !$rep->hasReadAccess($newpath, false);
}
 
if ($inrestricted)
{
$restricted[] = $i;
}
 
if ($item['endpath'] !== null)
{
$inrestricted = false;
}
}
 
foreach ($restricted as $i)
{
unset($listing[$i]);
}
 
if (count($restricted) && !count($listing))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
}
 
pclose($diff);
}
}
 
renderTemplate('compare');
/WebSVN/composer.json
0,0 → 1,13
{
"name": "websvnphp/websvn",
"description": "Online Subversion repository browser",
"keywords": ["subversion", "svn", "websvn"],
"type": "project",
"require": {
"geshi/geshi": "^1.0.9.1",
"pear/archive_tar": "^1.4.14",
"horde/text_diff": "^3.0.0",
"erusev/parsedown": "1.7.4"
},
"minimum-stability": "alpha"
}
/WebSVN/diff.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
25,334 → 23,212
// Show the differences between 2 revisions of a file.
//
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
 
$context = 5;
require_once 'include/diff_inc.php';
 
$vars["action"] = $lang["DIFF"];
$all = (@$_REQUEST["all"] == 1)?1:0;
$vars['action'] = $lang['DIFF'];
$all = (@$_REQUEST['all'] == 1);
$ignoreWhitespace = $config->getIgnoreWhitespacesInDiff();
 
if (array_key_exists('ignorews', $_REQUEST))
{
$ignoreWhitespace = (bool)$_REQUEST['ignorews'];
}
 
// Make sure that we have a repository
if (!isset($rep))
if (!$rep)
{
echo $lang["NOREP"];
exit;
renderTemplate404('diff','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, "", "", true);
$youngest = $history->entries[0]->rev;
$history = $svnrep->getLog($path, 'HEAD', 1, true, 2, ($path == '/') ? '' : $peg);
 
if (empty($rev))
$rev = $youngest;
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', true, 2, ($path == '/') ? '' : $peg);
}
 
$history = $svnrep->getLog($path, $rev);
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
 
if ($path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
if (empty($rev))
{
$rev = $youngest;
}
 
$history = $svnrep->getLog($path, $rev, 1, false, 2, $peg);
 
if ($path[0] != '/')
{
$ppath = '/'.$path;
}
else
{
$ppath = $path;
}
 
$prevrev = @$history->entries[1]->rev;
 
$vars["repname"] = $rep->getDisplayName();
$vars["rev"] = $rev;
$vars["path"] = $ppath;
$vars["prevrev"] = $prevrev;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
$vars['rev1'] = $rev;
$vars['rev2'] = $prevrev;
$vars['prevrev'] = $prevrev;
 
$vars["rev1"] = $history->entries[0]->rev;
$vars["rev2"] = $prevrev;
if (isset($history->entries[0]))
{
$vars['log'] = xml_entities($history->entries[0]->msg);
$vars['date'] = $history->entries[0]->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
$vars['author'] = $history->entries[0]->author;
$vars['rev'] = $vars['rev1'] = $history->entries[0]->rev;
$vars['peg'] = $peg;
}
 
createDirLinks($rep, $ppath, $rev, $showchanged);
createPathLinks($rep, $ppath, $passrev, $peg);
$passRevString = createRevAndPegString($rev, $peg);
 
$listing = array();
$passIgnoreWhitespace = '';
if ($ignoreWhitespace != $config->getIgnoreWhitespacesInDiff())
{
$passIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '1' : '0');
}
 
if ($prevrev)
if ($rev != $youngest)
{
$url = $config->getURL($rep, $path, "diff");
if (!$all)
{
$vars["showalllink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=1\">${lang["SHOWENTIREFILE"]}</a>";
$vars["showcompactlink"] = "";
}
else
{
$vars["showcompactlink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=0\">${lang["SHOWCOMPACT"]}</a>";
$vars["showalllink"] = "";
}
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'diff').createRevAndPegString('', $peg).$passIgnoreWhitespace;
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
}
 
// Get the contents of the two files
$newtname = tempnam("temp", "");
$new = $svnrep->getFileContents($history->entries[0]->path, $newtname, $history->entries[0]->rev, "", true);
$revurl = $config->getURL($rep, $path, 'diff');
 
$oldtname = tempnam("temp", "");
$old = $svnrep->getFileContents($history->entries[1]->path, $oldtname, $history->entries[1]->rev, "", true);
$ent = true;
$extension = strrchr(basename($path), ".");
if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript))
$ent = false;
if ($rev < $youngest)
{
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD');
 
$file1cache = array();
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$passIgnoreWhitespace;
}
}
 
if ($all)
$context = 1; // Setting the context to 0 makes diff generate the wrong line numbers!
unset($vars['error']);
}
 
// Open a pipe to the diff command with $context lines of context
$cmd = quoteCommand($config->diff." --ignore-all-space -U $context $oldtname $newtname", false);
if ($all)
{
$ofile = fopen($oldtname, "r");
$nfile = fopen($newtname, "r");
}
if (isset($history->entries[1]))
{
$prevRev = $history->entries[1]->rev;
$prevPath = $history->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$passIgnoreWhitespace;
}
 
if ($diff = popen($cmd, "r"))
{
// Ignore the 3 header lines
$line = fgets($diff);
$line = fgets($diff);
$vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
 
// Get the first real line
$line = fgets($diff);
$index = 0;
$listing = array();
$curoline = 1;
$curnline = 1;
while (!feof($diff))
{
// Get the first line of this range
sscanf($line, "@@ -%d", $oline);
$line = substr($line, strpos($line, "+"));
sscanf($line, "+%d", $nline);
if ($all)
{
while ($curoline < $oline || $curnline < $nline)
{
$listing[$index]["rev1diffclass"] = "diff";
$listing[$index]["rev2diffclass"] = "diff";
if ($curoline < $oline)
{
$nl = fgets($ofile);
if ($ent)
$line = replaceEntities(rtrim($nl), $rep);
else
$line = rtrim($nl);
$listing[$index]["rev1line"] = hardspace($line);
$vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
$curoline++;
}
else
$listing[$index]["rev1line"] = "&nbsp;";
if ($curnline < $nline)
{
$nl = fgets($nfile);
$vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
$vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
 
if ($ent)
$line = replaceEntities(rtrim($nl), $rep);
else
$line = rtrim($nl);
$listing[$index]["rev2line"] = hardspace($line);
$curnline++;
}
else
$listing[$index]["rev2line"] = "&nbsp;";
$listing[$index]["rev1lineno"] = 0;
$listing[$index]["rev2lineno"] = 0;
$vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
$vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
 
$index++;
}
}
else
{
// Output the line numbers
$listing[$index]["rev1lineno"] = "$oline";
$listing[$index]["rev2lineno"] = "$nline";
$index++;
}
$fin = false;
while (!feof($diff) && !$fin)
{
$listing[$index]["rev1lineno"] = 0;
$listing[$index]["rev2lineno"] = 0;
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
$line = fgets($diff);
if (!strncmp($line, "@@", 2))
{
$fin = true;
}
else
{
$mod = $line{0};
// Check for binary file type before diffing.
$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev);
 
if ($ent)
$line = replaceEntities(rtrim(substr($line, 1)), $rep);
else
$line = rtrim(substr($line, 1));
$listing[$index]["rev1line"] = hardspace($line);
// If no previous revision exists, bail out before diffing
if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType))
{
$vars['warning'] = 'Cannot display diff of binary file. (svn:mime-type = '.$svnMimeType.')';
 
$text = hardspace($line);
if ($text == "") $text = "&nbsp;";
switch ($mod)
{
case "-":
$listing[$index]["rev1diffclass"] = "diffdeleted";
$listing[$index]["rev2diffclass"] = "diff";
$listing[$index]["rev1line"] = $text;
$listing[$index]["rev2line"] = "&nbsp;";
if ($all)
{
fgets($ofile);
$curoline++;
}
break;
}
else if (!$prevrev)
{
$vars['noprev'] = 1;
}
else
{
$diff = $config->getURL($rep, $path, 'diff').$passRevString;
 
case "+":
// Try to mark "changed" line sensibly
if (!empty($listing[$index-1]) && empty($listing[$index-1]["rev1lineno"]) && @$listing[$index-1]["rev1diffclass"] == "diffdeleted" && @$listing[$index-1]["rev2diffclass"] == "diff")
{
$i = $index - 1;
while (!empty($listing[$i-1]) && empty($listing[$i-1]["rev1lineno"]) && $listing[$i-1]["rev1diffclass"] == "diffdeleted" && $listing[$i-1]["rev2diffclass"] == "diff")
$i--;
$listing[$i]["rev1diffclass"] = "diffchanged";
$listing[$i]["rev2diffclass"] = "diffchanged";
$listing[$i]["rev2line"] = $text;
if ($all)
{
fgets($nfile);
$curnline++;
}
if ($all)
{
$vars['showcompactlink'] = '<a href="'.$diff.$passIgnoreWhitespace.'">'.$lang['SHOWCOMPACT'].'</a>';
}
else
{
$vars['showalllink'] = '<a href="'.$diff.$passIgnoreWhitespace.'&amp;all=1'.'">'.$lang['SHOWENTIREFILE'].'</a>';
}
 
// Don't increment the current index count
$index--;
}
else
{
$listing[$index]["rev1diffclass"] = "diff";
$listing[$index]["rev2diffclass"] = "diffadded";
$listing[$index]["rev1line"] = "&nbsp;";
$listing[$index]["rev2line"] = $text;
$passShowAll = ($all ? '&amp;all=1' : '');
$toggleIgnoreWhitespace = '';
 
if ($all)
{
fgets($nfile);
$curnline++;
}
}
break;
default:
$listing[$index]["rev1diffclass"] = "diff";
$listing[$index]["rev2diffclass"] = "diff";
$listing[$index]["rev1line"] = $text;
$listing[$index]["rev2line"] = $text;
if ($all)
{
fgets($ofile);
fgets($nfile);
$curoline++;
$curnline++;
}
if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff())
{
$toggleIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '0' : '1');
}
 
break;
}
}
if (!$fin)
$index++;
}
}
// Output the rest of the files
if ($all)
{
while (!feof($ofile) || !feof($nfile))
{
$listing[$index]["rev1diffclass"] = "diff";
$listing[$index]["rev2diffclass"] = "diff";
if ($ent)
$line = replaceEntities(rtrim(fgets($ofile)), $rep);
else
$line = rtrim(fgets($ofile));
if ($ignoreWhitespace)
{
$vars['regardwhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>';
}
else
{
$vars['ignorewhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>';
}
 
if (!feof($ofile))
$listing[$index]["rev1line"] = hardspace($line);
else
$listing[$index]["rev1line"] = "&nbsp;";
if ($ent)
$line = replaceEntities(rtrim(fgets($nfile)), $rep);
else
$line = rtrim(fgets($nfile));
// Get the contents of the two files
$newerFile = tempnamWithCheck($config->getTempDir(), '');
$newerFileHl = $newerFile.'highlight';
$normalNew = $svnrep->getFileContents($history->entries[0]->path, $newerFile, $history->entries[0]->rev, $peg, '', 'no');
$highlightedNew = $svnrep->getFileContents($history->entries[0]->path, $newerFileHl, $history->entries[0]->rev, $peg, '', 'line');
 
if (!feof($nfile))
$listing[$index]["rev2line"] = hardspace($line);
else
$listing[$index]["rev2line"] = "&nbsp;";
$listing[$index]["rev1lineno"] = 0;
$listing[$index]["rev2lineno"] = 0;
$olderFile = tempnamWithCheck($config->getTempDir(), '');
$olderFileHl = $olderFile.'highlight';
$normalOld = $svnrep->getFileContents($history->entries[0]->path, $olderFile, $history->entries[1]->rev, $peg, '', 'no');
$highlightedOld = $svnrep->getFileContents($history->entries[0]->path, $olderFileHl, $history->entries[1]->rev, $peg, '', 'line');
// TODO: Figured out why diffs across a move/rename are currently broken.
 
$index++;
}
}
pclose($diff);
}
if ($all)
{
fclose($ofile);
fclose($nfile);
}
$highlighted = ($highlightedNew && $highlightedOld);
 
// Remove our temporary files
unlink($oldtname);
unlink($newtname);
if ($highlighted)
{
$listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, $newerFileHl, $olderFileHl);
}
else
{
$listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, null, null);
}
 
// Remove our temporary files
@unlink($newerFile);
@unlink($olderFile);
@unlink($newerFileHl);
@unlink($olderFileHl);
}
else
 
if (!$rep->hasReadAccess($path, false))
{
$vars["noprev"] = 1;
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
$vars["version"] = $version;
 
if (!$rep->hasReadAccess($path, false))
$vars["noaccess"] = true;
 
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."diff.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
?>
renderTemplate('diff');
/WebSVN/dl.php
1,122 → 1,326
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// dl.php
//
// Create gz/tar files of the requested item
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
 
// Make sure that this operation is allowed
 
if (!$rep->isDownloadAllowed($path))
exit;
 
$svnrep = new SVNRepository($rep);
 
if ($path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, "", "", true);
$youngest = $history->entries[0]->rev;
 
if (empty($rev))
$rev = $youngest;
 
// Create a temporary directory. Here we have an unavoidable but highly
// unlikely to occure race condition
 
if (count(glob("/tmp/wsvn-*"))<=40) // Omezeni na pocet soucasne stahovanych souboru
{
 
// Ošetření doběhnutí skriptu i když klient klikne jinam (smazání tmp)
ignore_user_abort(true);
 
$tmpname1 = tempnam("temp", "wsvn-");
$tmpname = $tmpname1;
$tmpname .= "dir";
if (mkdir($tmpname))
{
// Get the name of the directory being archived
$arcname = substr($path, 0, -1);
$arcname = basename($arcname);
if (empty($arcname))
$arcname = $rep->name;
$svnrep->exportDirectory($path, $tmpname.DIRECTORY_SEPARATOR.$arcname, $rev);
// ZIP it up
chdir($tmpname);
if (! connection_aborted())
exec("zip -r ".quote("$arcname")." .");
$size = filesize("$arcname.zip");
// Give the file to the browser
if (!connection_aborted() && $fp = @fopen("$arcname.zip","rb"))
{
header("Content-Type: application/zip");
header("Content-Length: $size");
header("Content-Disposition: attachment; filename=\"".$rep->name."-$arcname.zip\"");
// Use a loop to transfer the data 4KB at a time.
while(!feof($fp))
{
echo fread($fp, 4096);
ob_flush();
}
}
else
{
print "Unable to open file $arcname.zip";
}
fclose($fp);
chdir("..");
// Delete the directory. Why doesn't PHP have a generic recursive directory
// deletion command? It's stupid.
// if ($config->serverIsWindows)
// {
// $cmd = quoteCommand("rmdir /S /Q ".quote($tmpname), false);
// }
// else
// {
$cmd = quoteCommand("rm -fr ".quote($tmpname), false);
// }
@exec($cmd);
}
unlink($tmpname1); // Pomocny soubor smazeme az po smazani adresare
}
else
{
print "We are sorry. The server is overloaded...";
}
?>
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// dl.php
//
// Allow for file and directory downloads, creating zip/tar/gz files if needed.
 
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
 
if (!defined('USE_AUTOLOADER')) {
@include_once 'Archive/Tar.php';
}
 
function setDirectoryTimestamp($dir, $timestamp) {
global $config;
// Changing the timestamp of a directory in Windows is only supported in PHP 5.3.0+
touch($dir, $timestamp);
if (is_dir($dir)) {
// Set timestamp for all contents, recursing into subdirectories
$handle = opendir($dir);
if ($handle) {
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$f = $dir.DIRECTORY_SEPARATOR.$file;
if (is_dir($f)) {
setDirectoryTimestamp($f, $timestamp);
}
}
closedir($handle);
}
}
}
 
// Make sure that downloading the specified file/directory is permitted
 
if (!$rep)
{
http_response_code(404);
exit;
}
 
if (!$rep->isDownloadAllowed($path)) {
http_response_code(403);
error_log('Unable to download resource at path: '.$path);
print 'Unable to download resource at path: '.xml_entities($path);
exit;
}
 
$svnrep = new SVNRepository($rep);
 
// Fetch information about a revision (if unspecified, the latest) for this path
if (empty($rev))
{
$history = $svnrep->getLog($path, 'HEAD', '', true, 1, $peg);
}
else if ($rev == $peg)
{
$history = $svnrep->getLog($path, '', 1, true, 1, $peg);
}
else
{
$history = $svnrep->getLog($path, $rev, $rev - 1, true, 1, $peg);
}
 
$logEntry = ($history && !empty($history->entries)) ? $history->entries[0] : null;
 
if (!$logEntry)
{
http_response_code(404);
error_log('Unable to download resource at path: '.$path);
print 'Unable to download resource at path: '.xml_entities($path);
exit(0);
}
 
if (empty($rev))
{
$rev = $logEntry->rev;
}
 
// Create a temporary filename to be used for a directory to archive a download.
// Here we have an unavoidable but highly unlikely to occur race condition.
$tempDir = tempnamWithCheck($config->getTempDir(), 'websvn');
 
@unlink($tempDir);
mkdir($tempDir);
// Create the name of the directory being archived
$archiveName = $path;
$isDir = (substr($archiveName, -1) == '/');
 
if ($isDir)
{
$archiveName = substr($archiveName, 0, -1);
}
 
$archiveName = basename($archiveName);
 
if ($archiveName == '')
{
$archiveName = $rep->name;
}
 
$plainfilename = $archiveName;
$archiveName .= '.r'.$rev;
 
// Export the requested path from SVN repository to the temp directory
$svnExportResult = $svnrep->exportRepositoryPath($path, $tempDir.DIRECTORY_SEPARATOR.$archiveName, $rev, $peg);
 
if ($svnExportResult != 0)
{
http_response_code(500);
error_log('svn export failed for: '.$archiveName);
print 'svn export failed for "'.xml_entities($archiveName).'".';
removeDirectory($tempDir);
exit(0);
}
 
// For security reasons, disallow direct downloads of filenames that
// are a symlink, since they may be a symlink to anywhere (/etc/passwd)
// Deciding whether the symlink is relative and legal within the
// repository would be nice but seems to error prone at this moment.
if ( is_link($tempDir.DIRECTORY_SEPARATOR.$archiveName) )
{
http_response_code(500);
error_log('to be downloaded file is symlink, aborting: '.$archiveName);
print 'Download of symlinks disallowed: "'.xml_entities($archiveName).'".';
removeDirectory($tempDir);
exit(0);
}
 
// Set timestamp of exported directory (and subdirectories) to timestamp of
// the revision so every archive of a given revision has the same timestamp.
$revDate = $logEntry->date;
$timestamp = mktime(substr($revDate, 11, 2), // hour
substr($revDate, 14, 2), // minute
substr($revDate, 17, 2), // second
substr($revDate, 5, 2), // month
substr($revDate, 8, 2), // day
substr($revDate, 0, 4)); // year
setDirectoryTimestamp($tempDir, $timestamp);
 
// Change to temp directory so that only relative paths are stored in archive.
$oldcwd = getcwd();
chdir($tempDir);
 
if ($isDir)
{
$downloadMode = $config->getDefaultDirectoryDlMode();
}
else
{
$downloadMode = $config->getDefaultFileDlMode();
}
 
// $_REQUEST parameter can override dlmode
if (!empty($_REQUEST['dlmode']))
{
$downloadMode = $_REQUEST['dlmode'];
 
if (substr($logEntry->path, -1) == '/')
{
if (!in_array($downloadMode, $config->validDirectoryDlModes))
{
$downloadMode = $config->getDefaultDirectoryDlMode();
}
}
else
{
if (!in_array($downloadMode, $config->validFileDlModes))
{
$downloadMode = $config->getDefaultFileDlMode();
}
}
}
 
$downloadArchive = $archiveName;
 
if ($downloadMode == 'plain')
{
$downloadMimeType = 'application/octet-stream';
 
}
else if ($downloadMode == 'zip')
{
$downloadMimeType = 'application/zip';
$downloadArchive .= '.zip';
// Create zip file
$cmd = $config->zip.' --symlinks -r '.quote($downloadArchive).' '.quote($archiveName);
execCommand($cmd, $retcode);
 
if ($retcode != 0)
{
error_log('Unable to call zip command: '.$cmd);
print 'Unable to call zip command. See webserver error log for details.';
}
}
else
{
$downloadMimeType = 'application/gzip';
$downloadArchive .= '.tar.gz';
$tarArchive = $archiveName.'.tar';
 
// Create the tar file
$retcode = 0;
 
if (class_exists('Archive_Tar'))
{
$tar = new Archive_Tar($tarArchive);
$created = $tar->create(array($archiveName));
 
if (!$created)
{
$retcode = 1;
http_response_code(500);
print 'Unable to create tar archive.';
}
}
else
{
$cmd = $config->tar.' -cf '.quote($tarArchive).' '.quote($archiveName);
execCommand($cmd, $retcode);
 
if ($retcode != 0)
{
http_response_code(500);
error_log('Unable to call tar command: '.$cmd);
print 'Unable to call tar command. See webserver error log for details.';
}
}
 
if ($retcode != 0)
{
chdir($oldcwd);
removeDirectory($tempDir);
exit(0);
}
 
// Set timestamp of tar file to timestamp of revision
touch($tarArchive, $timestamp);
 
// GZIP it up
if (function_exists('gzopen'))
{
$srcHandle = fopen($tarArchive, 'rb');
$dstHandle = gzopen($downloadArchive, 'wb');
 
if (!$srcHandle || !$dstHandle)
{
http_response_code(500);
print 'Unable to open file for gz-compression.';
chdir($oldcwd);
removeDirectory($tempDir);
exit(0);
}
 
while (!feof($srcHandle))
{
gzwrite($dstHandle, fread($srcHandle, 1024 * 512));
}
 
fclose($srcHandle);
gzclose($dstHandle);
}
else
{
$cmd = $config->gzip.' '.quote($tarArchive);
$retcode = 0;
execCommand($cmd, $retcode);
 
if ($retcode != 0)
{
http_response_code(500);
error_log('Unable to call gzip command: '.$cmd);
print 'Unable to call gzip command. See webserver error log for details.';
chdir($oldcwd);
removeDirectory($tempDir);
exit(0);
}
}
}
 
// Give the file to the browser
if (is_readable($downloadArchive))
{
if ($downloadMode == 'plain')
{
$downloadFilename = $plainfilename;
}
else
{
$downloadFilename = $rep->name.'-'.$downloadArchive;
}
 
header('Content-Type: '.$downloadMimeType);
header('Content-Length: '.filesize($downloadArchive));
header("Content-Disposition: attachment; filename*=UTF-8''".rawurlencode($downloadFilename));
readfile($downloadArchive);
}
else
{
http_response_code(404);
print 'Unable to open file: '.xml_entities($downloadArchive);
}
 
chdir($oldcwd);
removeDirectory($tempDir);
/WebSVN/filedetails.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
24,151 → 22,227
//
// Simply lists the contents of a file
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
 
// Make sure that we have a repository
if (!isset($rep))
if (!$rep)
{
echo $lang["NOREP"];
exit;
renderTemplate404('file','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
if ($path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
if ($path[0] != '/')
{
$ppath = '/'.$path;
}
else
{
$ppath = $path;
}
 
$passrev = $rev;
$useMime = false;
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, "", "", true);
$youngest = $history->entries[0]->rev;
$history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg);
 
if (empty($rev))
$rev = $youngest;
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg);
if (!$history)
{
renderTemplate404('file','NOPATH');
}
}
 
$extn = strrchr($path, ".");
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
 
if (empty($rev))
{
$rev = !$peg ? $youngest : min($peg, $youngest);
}
 
$extn = strtolower(strrchr($path, '.'));
 
// Check to see if the user has requested that this type be zipped and sent
// to the browser as an attachment
 
if (in_array($extn, $zipped))
if ($history && isset($zipped) && in_array($extn, $zipped) && $rep->hasReadAccess($path, false))
{
$base = basename($path);
header("Content-Type: application/x-gzip");
header("Content-Disposition: attachment; filename=".urlencode($base).".gz");
$base = basename($path);
header('Content-Type: application/gzip');
header("Content-Disposition: attachment; filename*=UTF-8''".rawurlencode($base).'.gz');
 
// Get the file contents and pipe into gzip. All this without creating
// a temporary file. Damn clever.
$svnrep->getFileContents($path, "", $rev, "| ".$config->gzip." -n -f");
exit;
// Get the file contents and pipe into gzip. All this without creating
// a temporary file. Damn clever.
$svnrep->getFileContents($path, '', $rev, $peg, '| '.$config->gzip.' -n -f');
exit;
}
 
// Check to see if we should serve it with a particular content-type.
// The content-type could come from an svn:mime-type property on the
// file, or from the $contentType array in setup.inc.
// file, or from the $contentType array in setup.php.
 
if (!$rep->getIgnoreSvnMimeTypes())
{
$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev);
$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev);
}
 
if (!$rep->getIgnoreWebSVNContentTypes())
{
$setupContentType = @$contentType[$extn];
$setupContentType = @$contentType[$extn];
}
 
// Use this set of priorities when establishing what content-type to
// actually use.
 
// Use the documented priorities when establishing what content-type to use.
if (!empty($svnMimeType) && $svnMimeType != 'application/octet-stream')
{
$cont = $svnMimeType;
$mimeType = $svnMimeType;
}
else if (!empty($setupContentType))
else if (!empty($setupContentType))
{
$cont = $setupContentType;
}
else if (!empty($svnMimeType))
$mimeType = $setupContentType;
}
else if (!empty($svnMimeType))
{
// It now is equal to application/octet-stream due to logic
// above....
$cont = $svnMimeType;
$mimeType = $svnMimeType; // Use SVN's default of 'application/octet-stream'
}
else
{
$mimeType = '';
}
 
// If there's a MIME type associated with this format, then we deliver it
// with this information
$useMime = ($mimeType) ? @$_REQUEST['usemime'] : false;
 
if (!empty($cont))
if ($history && !empty($mimeType) && !$useMime)
{
$base = basename($path);
header("Content-Type: $cont");
//header("Content-Length: $size");
header("Content-Disposition: inline; filename=".urlencode($base));
$svnrep->getFileContents($path, "", $rev);
exit;
$useMime = $mimeType; // Save MIME type for later before possibly clobbering
// If a MIME type exists but is set to be ignored, set it to an empty string.
foreach ($config->inlineMimeTypes as $inlineType)
{
if (preg_match('|'.$inlineType.'|', $mimeType))
{
$mimeType = '';
break;
}
}
}
 
// Explicitly requested file as attachment
if (isset($_REQUEST['getfile']))
// If a MIME type is associated with the file, deliver with Content-Type header.
if ($history && !empty($mimeType) && $rep->hasReadAccess($path, false))
{
$base = basename($path);
$base = basename($path);
header('Content-Type: '.$mimeType);
//header('Content-Length: '.$size);
header("Content-Disposition: inline; filename*=UTF-8''".rawurlencode($base));
$svnrep->getFileContents($path, '', $rev, $peg);
exit;
}
 
header("Content-Type: application/octet-stream");
header("Content-Length: $size");
header("Content-Disposition: inline; filename=".urlencode($base));
// Display the file inline using WebSVN.
 
$svnrep->getFileContents($path, "", $rev);
$vars['action'] = '';
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
 
exit;
if (isset($history->entries[0]))
{
$vars['log'] = xml_entities($history->entries[0]->msg);
$vars['date'] = $history->entries[0]->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
$vars['author'] = $history->entries[0]->author;
}
 
// There's no associated MIME type. Show the file using WebSVN.
createPathLinks($rep, $ppath, !$passrev && $peg ? $rev : $passrev, $peg);
$passRevString = createRevAndPegString($rev, $peg);
 
$url = $config->getURL($rep, $path, "file");
if ($rev != $youngest)
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'file').createRevAndPegString($youngest, $peg);
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
}
 
if ($rev != $youngest)
$vars["goyoungestlink"] = "<a href=\"${url}sc=1\">${lang["GOYOUNGEST"]}</a>";
else
$vars["goyoungestlink"] = "";
$revurl = $config->getURL($rep, $path, 'file');
 
$vars["action"] = "";
$vars["repname"] = $rep->getDisplayName();
$vars["rev"] = $rev;
$vars["path"] = $ppath;
if ($rev < $youngest)
{
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD');
 
createDirLinks($rep, $ppath, $passrev, $showchanged);
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg);
}
}
 
$url = $config->getURL($rep, $path, "log");
$vars["fileviewloglink"] = "<a href=\"${url}rev=$passrev&amp;sc=$showchanged&isdir=0\">${lang["VIEWLOG"]}</a>";
unset($vars['error']);
}
 
$url = $config->getURL($rep, $path, "diff");
$vars["prevdifflink"] = "<a href=\"${url}rev=$passrev&amp;sc=$showchanged\">${lang["DIFFPREV"]}</a>";
$history3 = $svnrep->getLog($path, $rev, 1, true, 2, $peg ? $peg : 'HEAD');
 
$url = $config->getURL($rep, $path, "blame");
$vars["blamelink"] = "<a href=\"${url}rev=$passrev&amp;sc=$showchanged\">${lang["BLAME"]}</a>";
if (isset($history3->entries[1]))
{
$prevRev = $history3->entries[1]->rev;
$prevPath = $history3->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg);
}
 
#$url = $config->getURL($rep, $path, "get");
$url = $config->getURL($rep, $path, "file");
$vars["getfile"] = "<a href=\"${url}getfile&amp;rev=$passrev&amp;sc=$showchanged\">${lang["GETFILE"]}</a>";
unset($vars['error']);
 
$listing = array ();
$vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
 
$vars["version"] = $version;
$vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
if (!$rep->hasReadAccess($path, false))
$vars["noaccess"] = true;
$vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
$vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
 
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."file.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
?>
if ($history == null || count($history->entries) > 1)
{
$vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString;
$vars['difflink'] = '<a href="'.$vars['diffurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
if ($rep->isDownloadAllowed($path))
{
$vars['downloadlurl'] = $config->getURL($rep, $path, 'dl').$passRevString;
$vars['downloadlink'] = '<a href="'.$vars['downloadlurl'].'">'.$lang['DOWNLOAD'].'</a>';
}
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
$mimeType = $useMime; // Restore preserved value to use for 'mimelink' variable.
// If there was a MIME type, create a link to display file with that type.
if ($mimeType && !isset($vars['warning']))
{
$vars['mimeurl'] = $config->getURL($rep, $path, 'file').'usemime=1&amp;'.$passRevString;
$vars['mimelink'] = '<a href="'.$vars['mimeurl'].'">'.$lang['VIEWAS'].' "'.$mimeType.'"</a>';
}
 
$vars['rev'] = $rev;
$vars['peg'] = $peg;
 
if (!$rep->hasReadAccess($path))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
else if (!$svnrep->isFile($path, $rev, $peg))
{
renderTemplate404('file','NOPATH');
}
 
// $listing is populated with file data when file.tmpl calls [websvn-getlisting]
renderTemplate('file');
/WebSVN/include/auth.inc
File deleted
/WebSVN/include/command.inc
File deleted
/WebSVN/include/svnlook.inc
File deleted
/WebSVN/include/feedcreator.class.php
File deleted
/WebSVN/include/distconfig.inc
File deleted
/WebSVN/include/configclass.inc
File deleted
/WebSVN/include/PHP/Compat/Function/image_type_to_mime_type.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/get_include_path.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/str_rot13.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_uintersect_uassoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/clone.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ob_get_clean.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ob_flush.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/restore_include_path.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ini_get_all.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/fprintf.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/set_include_path.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/str_ireplace.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/pg_unescape_bytea.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/mime_content_type.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_udiff_assoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_walk_recursive.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/scandir.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/md5_file.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/php_strip_whitespace.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_change_key_case.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/vprintf.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/constant.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/version_compare.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/inet_pton.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/mhash.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/time_sleep_until.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ob_clean.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/floatval.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_combine.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/bcpowmod.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_uintersect_assoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/is_a.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/str_shuffle.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/strripos.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/idate.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_intersect_assoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/strpbrk.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_udiff.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_intersect_ukey.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/convert_uudecode.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_diff_assoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/pg_affected_rows.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_diff_ukey.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/stripos.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_intersect_key.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_chunk.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/pg_escape_bytea.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/get_headers.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/str_word_count.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/bcinvert.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_product.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_diff_key.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/http_build_query.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/str_split.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_uintersect.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/file_put_contents.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_key_exists.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/substr_compare.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/htmlspecialchars_decode.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/fputcsv.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/file_get_contents.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/inet_ntop.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ob_get_flush.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/debug_print_backtrace.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_search.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/html_entity_decode.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/convert_uuencode.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_udiff_uassoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/ibase_timefmt.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_intersect_uassoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/vsprintf.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/call_user_func_array.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/array_diff_uassoc.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Function/var_export.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/FILE.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/T.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/DIRECTORY_SEPARATOR.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/PHP_EOL.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/STD.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/E_STRICT.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/PATH_SEPARATOR.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Constant/UPLOAD_ERR.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat/Components.php
File deleted
\ No newline at end of file
/WebSVN/include/PHP/Compat.php
File deleted
\ No newline at end of file
/WebSVN/include/version.inc
File deleted
/WebSVN/include/php5compat.inc
File deleted
/WebSVN/include/config.inc
File deleted
/WebSVN/include/accessfile.inc
File deleted
/WebSVN/include/utils.inc
File deleted
/WebSVN/include/setup.inc
File deleted
/WebSVN/include/template.inc
File deleted
/WebSVN/include/bugtraq.inc
File deleted
/WebSVN/include/.gitignore
0,0 → 1,0
/config.php
/WebSVN/include/authz.php
0,0 → 1,132
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// authz.php
//
// Handle SVN access file
 
class Authorization {
var $accessCache = array();
var $accessFile = null;
var $user = null;
 
// {{{ __construct
 
function __construct() {
$this->setUsername();
}
 
// }}}
 
function hasUsername() {
return $this->user !== null;
}
 
function addAccessFile($accessFile) {
$this->accessFile = $accessFile;
}
 
// {{{ setUsername()
//
// Set the username from the current http session
 
function setUsername() {
if (isset($_SERVER['REMOTE_USER'])) {
$this->user = $_SERVER['REMOTE_USER'];
} else if (isset($_SERVER['REDIRECT_REMOTE_USER'])) {
$this->user = $_SERVER['REDIRECT_REMOTE_USER'];
} else if (isset($_SERVER['PHP_AUTH_USER'])) {
$this->user = $_SERVER['PHP_AUTH_USER'];
}
}
 
// }}}
 
// Private function to simplify creation of common SVN authz command string text.
function svnAuthzCommandString($repo, $path, $checkSubDirs = false) {
global $config;
 
$cmd = $config->getSvnAuthzCommand();
$repoAndPath = '--repository ' . quote($repo) . ' --path ' . quote($path);
$username = !$this->hasUsername() ? '' : '--username ' . quote($this->user);
$subDirs = !$checkSubDirs ? '' : '-R';
$authzFile = quote($this->accessFile);
$retVal = "{$cmd} {$repoAndPath} {$username} {$subDirs} {$authzFile}";
 
return $retVal;
}
 
// {{{ hasReadAccess
//
// Returns true if the user has read access to the given path
 
function hasReadAccess($repos, $path, $checkSubDirs = false) {
if ($this->accessFile == null)
return false;
 
if ($path == '' || $path[0] != '/') {
$path = '/'.$path;
}
 
$cmd = $this->svnAuthzCommandString($repos, $path, $checkSubDirs);
$result = 'no';
 
// Access checks might be issued multiple times for the same repos and paths within one and
// the same request, introducing a lot of overhead because of "svnauthz" especially with
// many repos under Windows. The easiest way to somewhat optimize it for different scenarios
// is using a cache.
//
// https://github.com/websvnphp/websvn/issues/78#issuecomment-489306169
$cache =& $this->accessCache;
$cached = isset($cache[$cmd]) ? $cache[$cmd] : null;
$cachedWhen = isset($cached) ? $cached['when'] : 0;
$cachedExpired = (time() - 60) > $cachedWhen;
 
if ($cachedExpired) {
// Sorting by "when" should be established somehow to only remove the oldest element
// instead of an arbitrary first one, which might be the newest added last time.
if (count($cache) >= 1000) {
array_shift($cache);
}
 
$result = runCommand($cmd)[0];
$cache[$cmd] = array('when' => time(),
'result' => $result);
} else {
$result = $cached['result'];
}
 
return $result != 'no';
}
 
// }}}
 
// {{{ hasUnrestrictedReadAccess
//
// Returns true if the user has read access to the given path and too
// all subdirectories
 
function hasUnrestrictedReadAccess($repos, $path) {
return $this->hasReadAccess($repos, $path, true);
}
 
// }}}
 
}
/WebSVN/include/bugtraq.php
0,0 → 1,371
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// bugtraq.php
//
// Functions for accessing the bugtraq properties and replacing issue IDs
// with URLs.
//
// For more information about bugtraq, see
// http://svn.collab.net/repos/tortoisesvn/trunk/doc/issuetrackers.txt
 
class Bugtraq {
// {{{ Properties
 
var $msgstring;
var $urlstring;
var $logregex;
var $append;
 
var $firstPart;
var $firstPartLen;
var $lastPart;
var $lastPartLen;
 
var $propsfound = false;
 
// }}}
 
// {{{ __construct($rep, $svnrep, $path)
 
function __construct($rep, $svnrep, $path) {
global $config;
 
if ($rep->isBugtraqEnabled()) {
$enoughdata = false;
if (($properties = $rep->getBugtraqProperties()) !== null) {
$this->msgstring = $properties['bugtraq:message'];
$this->logregex = $properties['bugtraq:logregex'];
$this->urlstring = $properties['bugtraq:url'];
$this->append = $properties['bugtraq:append'];
$enoughdata = true;
} else {
$pos = strrpos($path, '/');
$parent = substr($path, 0, $pos + 1);
$this->append = true;
 
while (!$enoughdata && (strpos($parent, '/') !== false)) {
$properties = $svnrep->getProperties($parent);
if (empty($this->msgstring) && in_array('bugtraq:message', $properties)) $this->msgstring = $svnrep->getProperty($parent, 'bugtraq:message');
if (empty($this->logregex) && in_array('bugtraq:logregex', $properties)) $this->logregex = $svnrep->getProperty($parent, 'bugtraq:logregex');
if (empty($this->urlstring) && in_array('bugtraq:url', $properties)) $this->urlstring = $svnrep->getProperty($parent, 'bugtraq:url');
if (in_array('bugtraq:append', $properties) && $svnrep->getProperty($parent, 'bugtraq:append') == 'false') $this->append = false;
 
$parent = substr($parent, 0, -1); // Remove the trailing slash
$pos = strrpos($parent, '/'); // Find the last trailing slash
$parent = substr($parent, 0, $pos + 1); // Find the previous parent directory
$enoughdata = ((!empty($this->msgstring) || !empty($this->logregex)) && !empty($this->urlstring));
}
}
 
$this->msgstring = trim(@$this->msgstring);
$this->urlstring = trim(@$this->urlstring);
 
if ($enoughdata && !empty($this->msgstring)) {
$this->initPartInfo();
}
 
if ($enoughdata) {
$this->propsfound = true;
}
}
}
 
// }}}
 
// {{{ initPartInfo()
 
function initPartInfo() {
if (($bugidpos = strpos($this->msgstring, '%BUGID%')) !== false && strpos($this->urlstring, '%BUGID%') !== false) {
// Get the textual parts of the message string for comparison purposes
$this->firstPart = substr($this->msgstring, 0, $bugidpos);
$this->firstPartLen = strlen($this->firstPart);
$this->lastPart = substr($this->msgstring, $bugidpos + 7);
$this->lastPartLen = strlen($this->lastPart);
}
}
 
// }}}
 
// {{{ replaceIDs($message)
 
function replaceIDs($message) {
if (!$this->propsfound) return $message;
 
// First we search for the message string
$logmsg = '';
$message = rtrim($message);
 
if ($this->append) {
// Just compare the last line
if (($offset = strrpos($message, "\n")) !== false) {
$logmsg = substr($message, 0, $offset + 1);
$bugLine = substr($message, $offset + 1);
} else {
$bugLine = $message;
}
} else {
if (($offset = strpos($message, "\n")) !== false) {
$bugLine = substr($message, 0, $offset);
$logmsg = substr($message, $offset);
} else {
$bugLine = $message;
}
}
 
// Make sure that our line really is an issue tracker message
if (isset($this->firstPart) && isset($this->lastPart) && ((strncmp($bugLine, $this->firstPart, $this->firstPartLen) == 0)) && strcmp(substr($bugLine, -$this->lastPartLen, $this->lastPartLen), $this->lastPart) == 0) {
// Get the issues list
if ($this->lastPartLen > 0) {
$issues = substr($bugLine, $this->firstPartLen, -$this->lastPartLen);
} else {
$issues = substr($bugLine, $this->firstPartLen);
}
 
// Add each reference to the first part of the line
$line = $this->firstPart;
while ($pos = strpos($issues, ',')) {
$issue = trim(substr($issues, 0, $pos));
$issues = substr($issues, $pos + 1);
 
$line .= '<a href="'.str_replace('%BUGID%', $issue, $this->urlstring).'">'.$issue.'</a>, ';
}
$line .= '<a href="'.str_replace('%BUGID%', trim($issues), $this->urlstring).'">'.trim($issues).'</a>'.$this->lastPart;
 
if ($this->append) {
$message = $logmsg.$line;
} else {
$message = $line.$logmsg;
}
}
 
// Now replace all other instances of bug IDs that match the regex
if ($this->logregex) {
$message = rtrim($message);
$line = '';
$allissues = '';
 
$lines = explode("\n", $this->logregex);
$regex_all = '~'.$lines[0].'~';
$regex_single = @$lines[1];
 
if (empty($regex_single)) {
// If the property only contains one line, then the pattern is only designed
// to find one issue number at a time. e.g. [Ii]ssue #?(\d+). In this case
// we need to replace the matched issue ID with the link.
 
if ($numMatches = preg_match_all($regex_all, $message, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
$addedOffset = 0;
for ($match = 0; $match < $numMatches; $match++) {
$issue = $matches[$match][1][0];
$issueOffset = $matches[$match][1][1];
 
$issueLink = '<a href="'.str_replace('%BUGID%', $issue, $this->urlstring).'">'.$issue.'</a>';
$message = substr_replace($message, $issueLink, $issueOffset + $addedOffset, strlen($issue));
$addedOffset += strlen($issueLink) - strlen($issue);
}
}
} else {
// It the property contains two lines, then the first is a pattern for extracting
// multiple issue numbers, and the second is a pattern extracting each issue
// number from the multiple match. e.g. [Ii]ssue #?(\d+)(,? ?#?(\d+))+ and (\d+)
 
while (preg_match($regex_all, $message, $matches, PREG_OFFSET_CAPTURE)) {
$completeMatch = $matches[0][0];
$completeMatchOffset = $matches[0][1];
 
$replacement = $completeMatch;
 
if ($numMatches = preg_match_all('~'.$regex_single.'~', $replacement, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
$addedOffset = 0;
for ($match = 0; $match < $numMatches; $match++) {
$issue = $matches[$match][1][0];
$issueOffset = $matches[$match][1][1];
 
$issueLink = '<a href="'.str_replace('%BUGID%', $issue, $this->urlstring).'">'.$issue.'</a>';
$replacement = substr_replace($replacement, $issueLink, $issueOffset + $addedOffset, strlen($issue));
$addedOffset += strlen($issueLink) - strlen($issue);
}
}
 
$message = substr_replace($message, $replacement, $completeMatchOffset, strlen($completeMatch));
}
}
}
 
return $message;
}
 
// }}}
 
}
 
// The BugtraqTestable class is a derived class that is used to test the matching
// abilities of the Bugtraq class. In particular, it allows for the initialisation of the
// class without the need for a repository.
 
class BugtraqTestable extends Bugtraq {
// {{{ __construct()
 
function __construct() {
// This constructor serves to assure that the parent constructor is not
// called.
}
 
// }}}
 
// {{{ setUpVars($message, $url, $regex, $append)
 
function setUpVars($message, $url, $regex, $append) {
$this->msgstring = $message;
$this->urlstring = $url;
$this->logregex = $regex;
$this->append = $append;
$this->propsfound = true;
 
$this->initPartInfo();
}
 
// }}}
 
// {{{ setMessage($message)
 
function setMessage($message) {
$this->msgstring = $message;
}
 
// }}}
 
// {{{ setUrl($url)
 
function setUrl($url) {
$this->urlstring = $url;
}
 
// }}}
 
// {{{ setRegex($regex)
 
function setRegEx($regex) {
$this->logregex = $regex;
}
 
// }}}
 
// {{{ setAppend($append)
 
function setAppend($append) {
$this->append = $append;
}
 
// }}}
 
// {{{ printVars()
 
function printVars() {
echo 'msgstring = '.$this->msgstring."\n";
echo 'urlstring = '.$this->urlstring."\n";
echo 'logregex = '.$this->logregex."\n";
echo 'append = '.$this->append."\n";
 
echo 'firstPart = '.$this->firstPart."\n";
echo 'firstPartLen = '.$this->firstPartLen."\n";
echo 'lastPart = '.$this->lastPart."\n";
echo 'lastPartLen = '.$this->lastPartLen."\n";
}
 
// }}}
}
 
// {{{ test_bugtraq()
 
function test_bugtraq() {
$tester = new BugtraqTestable;
 
$tester->setUpVars('BugID: %BUGID%',
'http://bugtracker/?id=%BUGID%',
'[Ii]ssue #?(\d+)',
true
);
 
//$tester->printVars();
 
$res = $tester->replaceIDs('BugID: 789'."\n".
'This is a test message that refers to issue #123 and'."\n".
'issue #456.'."\n".
'BugID: 789'
);
 
echo nl2br($res).'<p>';
 
$res = $tester->replaceIDs('BugID: 789, 101112'."\n".
'This is a test message that refers to issue #123 and'."\n".
'issue #456.'."\n".
'BugID: 789, 101112'
);
 
echo nl2br($res).'<p>';
 
$tester->setAppend(false);
 
$res = $tester->replaceIDs('BugID: 789'."\n".
'This is a test message that refers to issue #123 and'."\n".
'issue #456.'."\n".
'BugID: 789'
);
 
echo nl2br($res).'<p>';
 
$res = $tester->replaceIDs('BugID: 789, 101112'."\n".
'This is a test message that refers to issue #123 and'."\n".
'issue #456.'."\n".
'BugID: 789, 101112'
);
 
echo nl2br($res).'<p>';
 
$tester->setUpVars('BugID: %BUGID%',
'http://bugtracker/?id=%BUGID%',
'[Ii]ssues?:?(\s*(,|and)?\s*#\d+)+\n(\d+)',
true
);
 
$res = $tester->replaceIDs('BugID: 789, 101112'."\n".
'This is a test message that refers to issue #123 and'."\n".
'issues #456, #654 and #321.'."\n".
'BugID: 789, 101112'
);
 
echo nl2br($res).'<p>';
 
$tester->setUpVars('Test: %BUGID%',
'http://bugtracker/?id=%BUGID%',
'\s*[Cc]ases*\s*[IDs]*\s*[#: ]+((\d+[ ,:;#]*)+)\n(\d+)',
true
);
 
$res = $tester->replaceIDs('Cosmetic change'."\n".
'CaseIDs: 48'
);
 
echo nl2br($res).'<p>';
}
 
// }}}
/WebSVN/include/command.php
0,0 → 1,209
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// command.php
//
// External command handling
 
function detectCharacterEncoding($str) {
$list = array('UTF-8', 'ISO-8859-1', 'windows-1252');
if (function_exists('mb_detect_encoding')) {
foreach ($list as $item) {
if (mb_check_encoding($str, $item)) return $item;
}
 
} else if (function_exists('iconv')) {
foreach ($list as $item) {
$encstr = iconv($item, $item.'//TRANSLIT//IGNORE', $str);
if (md5($encstr) == md5($str)) return $item;
}
}
 
return null;
}
 
// {{{ toOutputEncoding
 
function toOutputEncoding($str) {
$enc = detectCharacterEncoding($str);
 
if ($enc !== null && function_exists('mb_convert_encoding')) {
$str = mb_convert_encoding($str, 'UTF-8', $enc);
 
} else if ($enc !== null && function_exists('iconv')) {
$str = iconv($enc, 'UTF-8//TRANSLIT//IGNORE', $str);
 
} else {
// @see http://w3.org/International/questions/qa-forms-utf-8.html
$isUtf8 = preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $str
);
if (!$isUtf8) $str = utf8_encode($str);
}
 
return $str;
}
 
// }}}
 
// {{{ escape
//
// Escape a string to output
 
function escape($str) {
$entities = array();
$entities['&'] = '&amp;';
$entities['<'] = '&lt;';
$entities['>'] = '&gt;';
$entities['"'] = '&quot;';
$entities['\''] = '&apos;';
return str_replace(array_keys($entities), array_values($entities), $str ?? '');
}
 
// }}}
 
// {{{ execCommand
 
function execCommand($cmd, &$retcode) {
return @exec($cmd, $tmp, $retcode);
}
 
// }}}
 
// {{{ popenCommand
 
function popenCommand($cmd, $mode) {
return popen($cmd, $mode);
}
 
// }}}
 
// {{{ passthruCommand
 
function passthruCommand($cmd) {
return passthru($cmd);
}
 
// }}}
 
// {{{ runCommand
 
function runCommand($cmd, $mayReturnNothing = false, &$errorIf = 'NOT_USED') {
global $config, $lang;
 
$output = array();
$error = '';
$opts = null;
 
// https://github.com/websvnphp/websvn/issues/75
// https://github.com/websvnphp/websvn/issues/78
if ($config->serverIsWindows) {
if (!strpos($cmd, '>') && !strpos($cmd, '|')) {
$opts = array('bypass_shell' => true);
} else {
$cmd = '"'.$cmd.'"';
}
}
 
$descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
$resource = proc_open($cmd, $descriptorspec, $pipes, null, null, $opts);
 
if (!is_resource($resource)) {
echo '<p>'.$lang['BADCMD'].': <code>'.stripCredentialsFromCommand($cmd).'</code></p>';
exit;
}
 
$handle = $pipes[1];
$firstline = true;
 
while (!feof($handle)) {
$line = rtrim(fgets($handle), "\n\r");
if ($firstline && empty($line) && !$mayReturnNothing) {
$error = 'No output on STDOUT.';
break;
}
 
$firstline = false;
$output[] = toOutputEncoding($line);
}
 
while (!feof($pipes[2])) {
$error .= fgets($pipes[2]);
}
$error = toOutputEncoding(trim($error));
 
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
 
proc_close($resource);
 
# Some commands are expected to return no output, but warnings on STDERR.
if ((count($output) > 0) || $mayReturnNothing) {
return $output;
}
 
if ($errorIf != 'NOT_USED') {
$errorIf = $error;
return $output;
}
 
echo '<p>'.$lang['BADCMD'].': <code>'.stripCredentialsFromCommand($cmd).'</code></p>';
echo '<p>'.nl2br($error).'</p>';
exit;
}
 
// }}}
 
function stripCredentialsFromCommand($cmd) {
global $config;
 
$quotingChar = ($config->serverIsWindows ? '"' : "'");
$quotedString = $quotingChar.'([^'.$quotingChar.'\\\\]*(\\\\.[^'.$quotingChar.'\\\\]*)*)'.$quotingChar;
$patterns = array('|--username '.$quotedString.' |U', '|--password '.$quotedString.' |U');
$replacements = array('--username '.quote('***').' ', '--password '.quote('***').' ');
$cmd = preg_replace($patterns, $replacements, $cmd, 1);
 
return $cmd;
}
 
// {{{ quote
//
// Quote a string to send to the command line
 
function quote($str) {
global $config;
 
if ($config->serverIsWindows) {
return '"'.$str.'"';
} else {
return escapeshellarg($str);
}
}
 
// }}}
/WebSVN/include/configclass.php
0,0 → 1,1702
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// configclass.php
//
// General class for handling configuration options
 
require_once 'include/command.php';
require_once 'include/authz.php';
require_once 'include/version.php';
 
// Auxillary functions used to sort repositories by name/group
 
// {{{ cmpReps($a, $b)
 
function cmpReps($a, $b) {
// First, sort by group
$g = strcasecmp((string) $a->group, (string) $b->group);
if ($g) return $g;
 
// Same group? Sort by name
return strcasecmp($a->name, $b->name);
}
 
// }}}
 
// {{{ cmpGroups($a, $b)
 
function cmpGroups($a, $b) {
$g = strcasecmp((string) $a->group, (string) $b->group);
if ($g) return $g;
 
return 0;
}
 
// }}}
 
// {{{ mergesort(&$array, [$cmp_function])
 
function mergesort(&$array, $cmp_function = 'strcmp') {
// Arrays of size < 2 require no action
 
if (count($array) < 2) return;
 
// Split the array in half
$halfway = count($array) / 2;
$array1 = array_slice($array, 0, $halfway);
$array2 = array_slice($array, $halfway);
 
// Recurse to sort the two halves
mergesort($array1, $cmp_function);
mergesort($array2, $cmp_function);
 
// If all of $array1 is <= all of $array2, just append them.
if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
$array = array_merge($array1, $array2);
return;
}
 
// Merge the two sorted arrays into a single sorted array
$array = array();
$array1count = count($array1);
$array2count = count($array2);
$ptr1 = 0;
$ptr2 = 0;
while ($ptr1 < $array1count && $ptr2 < $array2count) {
if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
$array[] = $array1[$ptr1++];
} else {
$array[] = $array2[$ptr2++];
}
}
 
// Merge the remainder
while ($ptr1 < $array1count) $array[] = $array1[$ptr1++];
while ($ptr2 < $array2count) $array[] = $array2[$ptr2++];
 
return;
}
 
// }}}
 
// A Repository parent path configuration class
 
class ParentPath {
// {{{ Properties
 
var $path;
var $group;
var $pattern;
var $skipAlreadyAdded;
var $clientRootURL;
 
// }}}
 
// {{{ __construct($path [, $group [, $pattern [, $skipAlreadyAdded [, $clientRootURL]]]])
function __construct($path, $group = null, $pattern = false, $skipAlreadyAdded = true, $clientRootURL = '') {
$this->path = $path;
$this->group = $group;
$this->pattern = $pattern;
$this->skipAlreadyAdded = $skipAlreadyAdded;
$this->clientRootURL = rtrim($clientRootURL, '/');
}
// }}}
 
// {{{ findRepository($name)
// look for a repository with $name
function &findRepository($name) {
global $config;
if ($this->group != null) {
$prefix = $this->group.'.';
if (substr($name, 0, strlen($prefix)) == $prefix) {
$name = substr($name, strlen($prefix));
} else {
$null = null;
return $null;
}
}
// is there a directory named $name?
$fullpath = $this->path.DIRECTORY_SEPARATOR.$name;
if (is_dir($fullpath) && is_readable($fullpath)) {
// And that contains a db directory (in an attempt to not include non svn repositories.
$dbfullpath = $fullpath.DIRECTORY_SEPARATOR.'db';
if (is_dir($dbfullpath) && is_readable($dbfullpath)) {
// And matches the pattern if specified
if ($this->pattern === false || preg_match($this->pattern, $name)) {
$url = $config->fileUrlPrefix.$fullpath;
$url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
if ($url[ strlen($url) - 1 ] == '/') {
$url = substr($url, 0, -1);
}
 
if (!in_array($url, $config->_excluded, true)) {
$clientRootURL = ($this->clientRootURL) ? $this->clientRootURL.'/'.$name : '';
$rep = new Repository($name, $name, $url, $this->group, null, null, null, $clientRootURL);
return $rep;
}
}
}
}
$null = null;
return $null;
}
// }}}
 
// {{{ getRepositories()
// return all repositories in the parent path matching pattern
function &getRepositories() {
global $config;
$repos = array();
$handle = @opendir($this->path);
 
if (!$handle) return $repos;
 
// For each file...
while (false !== ($name = readdir($handle))) {
$fullpath = $this->path.DIRECTORY_SEPARATOR.$name;
if ($name[0] != '.' && is_dir($fullpath) && is_readable($fullpath)) {
// And that contains a db directory (in an attempt to not include non svn repositories.
$dbfullpath = $fullpath.DIRECTORY_SEPARATOR.'db';
if (is_dir($dbfullpath) && is_readable($dbfullpath)) {
// And matches the pattern if specified
if ($this->pattern === false || preg_match($this->pattern, $name)) {
$url = $config->fileUrlPrefix.$fullpath;
$url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
if ($url[strlen($url) - 1] == '/') {
$url = substr($url, 0, -1);
}
$clientRootURL = ($this->clientRootURL) ? $this->clientRootURL.'/'.$name : '';
$repos[] = new Repository($name, $name, $url, $this->group, null, null, null, $clientRootURL);
}
}
}
}
closedir($handle);
 
// Sort the repositories into alphabetical order
if (!empty($repos)) {
usort($repos, 'cmpReps');
}
 
return $repos;
}
// }}}
 
// {{{ getSkipAlreadyAdded()
// Return if we should skip already added repos for this parent path.
function getSkipAlreadyAdded() {
return $this->skipAlreadyAdded;
}
// }}}
}
 
// A Repository configuration class
 
class Repository {
// {{{ Properties
 
var $name;
var $svnName;
var $path;
var $subpath;
var $group;
var $username = null;
var $password = null;
var $clientRootURL;
 
// Local configuration options must start off unset
 
var $allowDownload;
var $minDownloadLevel;
var $allowedExceptions = array();
var $disallowedExceptions = array();
var $logsShowChanges;
var $rss;
var $rssCaching;
var $rssMaxEntries;
var $spaces;
var $ignoreSvnMimeTypes;
var $ignoreWebSVNContentTypes;
var $bugtraq;
var $bugtraqProperties;
var $authz = null;
var $templatePath = false;
 
// }}}
 
// {{{ __construct($name, $svnName, $serverRootURL [, $group [, $username [, $password [, $clientRootURL]]]])
 
function __construct($name, $svnName, $serverRootURL, $group = null, $username = null, $password = null, $subpath = null, $clientRootURL = null) {
$this->name = $name;
$this->svnName = $svnName;
$this->path = $serverRootURL;
$this->subpath = $subpath;
$this->group = $group;
$this->username = $username;
$this->password = $password;
$this->clientRootURL = rtrim($clientRootURL, '/');
}
 
// }}}
 
// {{{ getDisplayName()
 
function getDisplayName() {
if (!empty($this->group)) {
return $this->group.'.'.$this->name;
}
 
return $this->name;
}
 
// }}}
 
// {{{ svnCredentials
 
function svnCredentials() {
$params = '';
if ($this->username !== null && $this->username !== '') {
$params .= ' --username '.quote($this->username);
}
if ($this->password !== null) {
$params .= ' --password '.quote($this->password);
}
return $params;
}
 
// }}}
 
// Local configuration accessors
 
function setLogsShowChanges($enabled = true) {
$this->logsShowChanges = $enabled;
}
 
function logsShowChanges() {
global $config;
 
if (isset($this->logsShowChanges))
return $this->logsShowChanges;
else
return $config->logsShowChanges();
}
 
// {{{ RSS Feed
 
function setRssEnabled($enabled) {
$this->rss = $enabled;
}
 
function isRssEnabled() {
global $config;
 
if (isset($this->rss))
return $this->rss;
else
return $config->isRssEnabled();
}
 
function setRssCachingEnabled($enabled = true) {
$this->rssCaching = $enabled;
}
 
function isRssCachingEnabled() {
global $config;
 
if (isset($this->rssCaching))
return $this->rssCaching;
else
return $config->isRssCachingEnabled();
}
 
function setRssMaxEntries($max) {
$this->rssMaxEntries = $max;
}
 
function getRssMaxEntries() {
global $config;
 
if (isset($this->rssMaxEntries))
return $this->rssMaxEntries;
else
return $config->getRssMaxEntries();
}
 
// }}}
 
// {{{ Download
 
function allowDownload() {
$this->allowDownload = true;
}
 
function disallowDownload() {
$this->allowDownload = false;
}
 
function getAllowDownload() {
global $config;
 
if (isset($this->allowDownload)) {
return $this->allowDownload;
}
 
return $config->getAllowDownload();
}
 
function setMinDownloadLevel($level) {
$this->minDownloadLevel = $level;
}
 
function getMinDownloadLevel() {
global $config;
 
if (isset($this->minDownloadLevel)) {
return $this->minDownloadLevel;
}
 
return $config->getMinDownloadLevel();
}
 
function addAllowedDownloadException($path) {
if ($path[strlen($path) - 1] != '/') $path .= '/';
 
$this->allowedExceptions[] = $path;
}
 
function addDisallowedDownloadException($path) {
if ($path[strlen($path) - 1] != '/') $path .= '/';
 
$this->disallowedExceptions[] = $path;
}
 
function isDownloadAllowed($path) {
global $config;
 
// Check global download option
if (!$this->getAllowDownload()) {
return false;
}
 
// Check with access module
if (!$this->hasUnrestrictedReadAccess($path)) {
return false;
}
 
$subs = explode('/', $path);
$level = count($subs) - 2;
if ($level >= $this->getMinDownloadLevel()) {
// Level OK, search for disallowed exceptions
 
if ($config->findException($path, $this->disallowedExceptions)) {
return false;
}
 
if ($config->findException($path, $config->disallowedExceptions)) {
return false;
}
 
return true;
 
} else {
// Level not OK, search for disallowed exceptions
 
if ($config->findException($path, $this->allowedExceptions)) {
return true;
}
 
if ($config->findException($path, $config->allowedExceptions)) {
return true;
}
 
return false;
}
}
 
// }}}
 
// {{{ Templates
 
function setTemplatePath($path) {
$this->templatePath = $path;
}
 
function getTemplatePath() {
global $config;
if (!empty($this->templatePath)) {
return $this->templatePath;
}
 
return $config->getTemplatePath();
}
 
// }}}
 
// {{{ Tab expansion
 
function expandTabsBy($sp) {
$this->spaces = $sp;
}
 
function getExpandTabsBy() {
global $config;
 
if (isset($this->spaces)) {
return $this->spaces;
}
 
return $config->getExpandTabsBy();
}
 
// }}}
 
// {{{ MIME-Type Handing
 
function ignoreSvnMimeTypes() {
$this->ignoreSvnMimeTypes = true;
}
 
function useSvnMimeTypes() {
$this->ignoreSvnMimeTypes = false;
}
 
function getIgnoreSvnMimeTypes() {
global $config;
 
if (isset($this->ignoreSvnMimeTypes)) {
return $this->ignoreSvnMimeTypes;
}
 
return $config->getIgnoreSvnMimeTypes();
}
 
function ignoreWebSVNContentTypes() {
$this->ignoreWebSVNContentTypes = true;
}
 
function useWebSVNContentTypes() {
$this->ignoreWebSVNContentTypes = false;
}
 
function getIgnoreWebSVNContentTypes() {
global $config;
 
if (isset($this->ignoreWebSVNContentTypes)) {
return $this->ignoreWebSVNContentTypes;
}
 
return $config->getIgnoreWebSVNContentTypes();
}
 
// }}}
 
// {{{ Bugtraq issue tracking
 
function setBugtraqEnabled($enabled) {
$this->bugtraq = $enabled;
}
 
function isBugtraqEnabled() {
global $config;
 
if (isset($this->bugtraq))
return $this->bugtraq;
else
return $config->isBugtraqEnabled();
}
 
function setBugtraqProperties($properties) {
$this->bugtraqProperties = $properties;
}
 
function getBugtraqProperties() {
global $config;
 
if (isset($this->bugtraqProperties))
return $this->bugtraqProperties;
else
return $config->getBugtraqProperties();
}
 
// }}}
 
// {{{ Authorization
 
function useAccessFile($file) {
if (is_readable($file)) {
if ($this->authz === null) {
$this->authz = new Authorization();
}
$this->authz->addAccessFile($file);
} else {
die('Unable to read access file "'.$file.'"');
}
}
 
function &getAuthz() {
global $config;
 
$a = null;
if ($this->authz !== null) {
$a =& $this->authz;
} else {
$a =& $config->getAuthz();
}
return $a;
}
 
function _getPathWithSubIf($pathWoSub) {
if (!$this->subpath) {
return $pathWoSub;
}
 
return '/' . $this->subpath . $pathWoSub;
}
 
function hasReadAccess($pathWoSub, $checkSubDirs = false) {
$path = $this->_getPathWithSubIf($pathWoSub);
$a =& $this->getAuthz();
 
if (!empty($a)) {
return $a->hasReadAccess($this->svnName, $path, $checkSubDirs);
}
 
// No access file - free access...
return true;
}
 
function hasLogReadAccess($pathWithSub) {
$path = $pathWithSub;
$a =& $this->getAuthz();
 
if (!empty($a)) {
return $a->hasReadAccess($this->svnName, $path, false);
}
 
// No access file - free access...
return true;
}
 
function hasUnrestrictedReadAccess($pathWoSub) {
$path = $this->_getPathWithSubIf($pathWoSub);
$a =& $this->getAuthz();
 
if (!empty($a)) {
return $a->hasUnrestrictedReadAccess($this->svnName, $path);
}
 
// No access file - free access...
return true;
}
 
// }}}
 
}
 
// The general configuration class
 
class WebSvnConfig {
// {{{ Properties
 
// Tool path locations
 
var $_svnCommandPath = '';
var $_svnConfigDir = '/tmp/websvn';
var $_svnTrustServerCert = false;
var $svn = 'svn --non-interactive --config-dir /tmp/websvn';
var $svnAuthz = 'svnauthz accessof';
var $diff = 'diff';
var $enscript = 'enscript -q';
var $sed = 'sed';
var $gzip = 'gzip';
var $tar = 'tar';
var $zip = 'zip';
var $locale = '';
 
// different modes for file and directory download
 
var $defaultFileDlMode = 'plain';
var $defaultDirectoryDlMode = 'gzip';
 
var $validFileDlModes = array( 'gzip', 'zip', 'plain' );
var $validDirectoryDlModes = array( 'gzip', 'zip' );
 
// Other configuration items
 
var $treeView = true;
var $flatIndex = true;
var $openTree = false;
var $alphabetic = false;
var $showLastModInIndex = true;
var $showLastModInListing = true;
var $showAgeInsteadOfDate = true;
var $_showRepositorySelectionForm = true;
var $_ignoreWhitespacesInDiff = false;
var $serverIsWindows = false;
var $multiViews = false;
var $multiViewsIndex = 'browse';
var $useEnscript = false;
var $useEnscriptBefore_1_6_3 = false;
var $useGeshi = false;
var $geshiScript = 'geshi.php';
var $useParsedown = false;
var $parsedownScript = 'Parsedown.php';
var $inlineMimeTypes = array();
var $allowDownload = false;
var $tempDir = '';
var $minDownloadLevel = 0;
var $allowedExceptions = array();
var $disallowedExceptions = array();
var $logsShowChanges = false;
var $rss = true;
var $rssCaching = false;
var $rssMaxEntries = 40;
var $spaces = 8;
var $bugtraq = false;
var $bugtraqProperties = null;
var $authz = null;
var $blockRobots = false;
 
var $loadAllRepos = false;
 
var $templatePaths = array();
var $userTemplate = false;
 
var $ignoreSvnMimeTypes = false;
var $ignoreWebSVNContentTypes = false;
 
var $subversionVersion = '';
var $subversionMajorVersion = '';
var $subversionMinorVersion = '';
 
var $defaultLanguage = 'en';
var $ignoreAcceptedLanguages = false;
 
var $quote = "'";
var $pathSeparator = ':';
var $fileUrlPrefix = 'file://';
var $breadcrumbRepoRootAsRepo = false;
 
var $_repositories = array();
 
var $_parentPaths = array(); // parent paths to load
 
var $_parentPathsLoaded = false;
 
var $_excluded = array();
 
// }}}
 
// {{{ __construct()
 
function __construct() {
}
 
// }}}
 
// {{{ Repository configuration
 
function addRepository($name, $serverRootURL, $group = null, $username = null, $password = null, $clientRootURL = null) {
$this->addRepositorySubpath($name, $serverRootURL, null, $group, $username, $password, $clientRootURL);
}
 
function addRepositorySubpath($name, $serverRootURL, $subpath, $group = null, $username = null, $password = null, $clientRootURL = null) {
if (DIRECTORY_SEPARATOR != '/') {
$serverRootURL = str_replace(DIRECTORY_SEPARATOR, '/', $serverRootURL);
if ($subpath !== null) {
$subpath = str_replace(DIRECTORY_SEPARATOR, '/', $subpath);
}
}
$serverRootURL = trim($serverRootURL, '/');
$svnName = substr($serverRootURL, strrpos($serverRootURL, '/') + 1);
$this->_repositories[] = new Repository($name, $svnName, $serverRootURL, $group, $username, $password, $subpath, $clientRootURL);
}
 
// Automatically set up the repositories based on a parent path
 
function parentPath($path, $group = null, $pattern = false, $skipAlreadyAdded = true, $clientRootURL = '') {
$this->_parentPaths[] = new ParentPath($path, $group, $pattern, $skipAlreadyAdded, $clientRootURL);
}
 
function addExcludedPath($path) {
$url = $this->fileUrlPrefix.$path;
$url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
if ($url[strlen($url) - 1] == '/') {
$url = substr($url, 0, -1);
}
$this->_excluded[] = $url;
}
 
function getRepositories() {
// lazily load parent paths
if ($this->_parentPathsLoaded) return $this->_repositories;
 
$this->_parentPathsLoaded = true;
 
foreach ($this->_parentPaths as $parentPath) {
$parentRepos = $parentPath->getRepositories();
foreach ($parentRepos as $repo) {
if (!$parentPath->getSkipAlreadyAdded()) {
$this->_repositories[] = $repo;
} else {
// we have to check if we already have a repo with the same svn name
$duplicate = false;
foreach ($this->_repositories as $knownRepos) {
if ($knownRepos->path == $repo->path && $knownRepos->subpath == $repo->subpath) {
$duplicate = true;
break;
}
}
 
if (!$duplicate && !in_array($repo->path, $this->_excluded, true)) {
$this->_repositories[] = $repo;
}
}
}
}
 
return $this->_repositories;
}
 
function &findRepository($name) {
// first look in the "normal repositories"
foreach ($this->_repositories as $index => $rep) {
if (strcmp($rep->getDisplayName(), $name) == 0) {
$repref =& $this->_repositories[$index];
return $repref;
}
}
 
// now if the parent repos have not already been loaded
// check them
if (!$this->_parentPathsLoaded) {
foreach ($this->_parentPaths as $parentPath) {
$repref =& $parentPath->findRepository($name);
if ($repref != null) {
$this->_repositories[] = $repref;
return $repref;
}
}
}
 
// Hack to return a string by reference; value retrieved at setup.php:414
$str = 'Unable to find repository "'.escape($name).'".';
$error =& $str;
return $error;
}
 
// }}}
 
// {{{ setServerIsWindows
//
// The server is running on Windows
 
function setServerIsWindows() {
$this->serverIsWindows = true;
 
// On Windows machines, use double quotes around command line parameters
$this->quote = '"';
 
// On Windows, semicolon separates path entries in a list rather than colon.
$this->pathSeparator = ';';
 
$this->fileUrlPrefix = 'file:///';
}
 
// }}}
 
// {{{ MultiViews
 
// useMultiViews
//
// Use MultiViews to access the repository
 
function useMultiViews($multiViewsIndex = 'browse') {
$this->multiViews = true;
$this->multiViewsIndex = $multiViewsIndex;
}
 
function getUseMultiViews() {
return $this->multiViews;
}
 
function getMultiViewsIndex() {
return $this->multiViewsIndex;
}
 
// }}}
 
// {{{ Enscript
 
// useEnscript
//
// Use Enscript to colourise listings
 
function useEnscript($before_1_6_3 = false) {
$this->useEnscript = true;
$this->useEnscriptBefore_1_6_3 = $before_1_6_3;
}
 
function getUseEnscript() {
return $this->useEnscript;
}
 
function getUseEnscriptBefore_1_6_3() {
return $this->useEnscriptBefore_1_6_3;
}
 
// }}}
 
// {{{ GeSHi
 
function setGeshiPath($path) {
$this->_setPath($this->geshiScript, $path, 'geshi.php');
}
 
function getGeshiScript() {
return $this->geshiScript;
}
 
// useGeshi
//
// Use GeSHi to colourise listings
function useGeshi() {
$this->useGeshi = true;
}
 
function getUseGeshi() {
return $this->useGeshi;
}
 
// }}}
 
// {{{ Parsedown
 
function setParsedownPath($path) {
$this->_setPath($this->parsedownScript, $path, 'Parsedown.php');
}
 
function getParsedownScript() {
return $this->parsedownScript;
}
 
// useParsedown
//
// Use Parsedown to render README.md
function useParsedown() {
$this->useParsedown = true;
}
 
function getUseParsedown() {
return $this->useParsedown;
}
 
// }}}
 
// {{{ Inline MIME Types
 
// inlineMimeTypes
//
// Specify MIME types to display inline in WebSVN pages
function addInlineMimeType($type) {
if (!in_array($type, $this->inlineMimeTypes)) {
$this->inlineMimeTypes[] = $type;
}
}
 
// }}}
 
// {{{ Show changed files by default on log.php
 
function setLogsShowChanges($enabled = true, $myrep = 0) {
if (empty($myrep)) {
$this->logsShowChanges = $enabled;
} else {
$repo =& $this->findRepository($myrep);
$repo->logsShowChanges = $enabled;
}
}
 
function logsShowChanges() {
return $this->logsShowChanges;
}
 
// }}}
 
// {{{ RSS
 
function setRssEnabled($enabled = true, $myrep = 0) {
if (empty($myrep)) {
$this->rss = $enabled;
} else {
$repo =& $this->findRepository($myrep);
$repo->setRssEnabled($enabled);
}
}
 
function isRssEnabled() {
return $this->rss;
}
 
function setRssCachingEnabled($enabled = true, $myrep = 0) {
if (empty($myrep)) {
$this->rssCaching = true;
} else {
$repo =& $this->findRepository($myrep);
$repo->setRssCachingEnabled($enabled);
}
}
 
function isRssCachingEnabled() {
return $this->rssCaching;
}
 
// Maximum number of entries in RSS feed
 
function setRssMaxEntries($max, $myrep = 0) {
if (empty($myrep)) {
$this->rssMaxEntries = $max;
} else {
$repo =& $this->findRepository($myrep);
$repo->setRssMaxEntries($max);
}
}
 
function getRssMaxEntries() {
return $this->rssMaxEntries;
}
 
function getHideRSS() {
return $this->rss;
}
 
// cacheRSS
//
// Enable caching of RSS feeds
 
function enableRSSCaching($myrep = 0) {
if (empty($myrep)) {
$this->rssCaching = true;
} else {
$repo =& $this->findRepository($myrep);
$repo->enableRSSCaching();
}
}
 
function getRSSCaching() {
return $this->rssCaching;
}
 
// }}}
 
// {{{ Downloads
 
// allowDownload
//
// Allow download of tarballs
 
function allowDownload($myrep = 0) {
if (empty($myrep)) {
$this->allowDownload = true;
} else {
$repo =& $this->findRepository($myrep);
$repo->allowDownload();
}
}
 
function disallowDownload($myrep = 0) {
if (empty($myrep)) {
$this->allowDownload = false;
} else {
$repo =& $this->findRepository($myrep);
$repo->disallowDownload();
}
}
 
function getAllowDownload() {
return $this->allowDownload;
}
 
function setTempDir($tempDir) {
$this->tempDir = $tempDir;
}
 
function getTempDir() {
if (empty($this->tempDir)) {
$this->tempDir = sys_get_temp_dir();
}
return $this->tempDir;
}
 
function setMinDownloadLevel($level, $myrep = 0) {
if (empty($myrep)) {
$this->minDownloadLevel = $level;
} else {
$repo =& $this->findRepository($myrep);
$repo->setMinDownloadLevel($level);
}
}
 
function getMinDownloadLevel() {
return $this->minDownloadLevel;
}
 
function addAllowedDownloadException($path, $myrep = 0) {
if ($path[strlen($path) - 1] != '/') {
$path .= '/';
}
 
if (empty($myrep)) {
$this->allowedExceptions[] = $path;
} else {
$repo =& $this->findRepository($myrep);
$repo->addAllowedDownloadException($path);
}
}
 
function addDisallowedDownloadException($path, $myrep = 0) {
if ($path[strlen($path) - 1] != '/') {
$path .= '/';
}
 
if (empty($myrep)) {
$this->disallowedExceptions[] = $path;
} else {
$repo =& $this->findRepository($myrep);
$repo->addDisallowedDownloadException($path);
}
}
 
function findException($path, $exceptions) {
foreach ($exceptions as $key => $exc) {
if (strncmp($exc, $path, strlen($exc)) == 0) {
return true;
}
}
 
return false;
}
 
// }}}
 
// {{{ getURL
//
// Get the URL to a path name based on the current config
 
function getURL($rep, $path, $op) {
list($base, $params) = $this->getUrlParts($rep, $path, $op);
$url = $base.'?';
foreach ($params as $k => $v) {
$url .= $k.'='.rawurlencode($v).'&amp;';
}
return $url;
}
 
// }}}
 
// {{{ getUrlParts
//
// Get the URL and parameters for a path name based on the current config
 
function getUrlParts($rep, $path, $op) {
$params = array();
 
if ($this->multiViews) {
$url = $_SERVER['SCRIPT_NAME'];
if (preg_match('|\.php$|i', $url)) {
// remove the .php extension
$url = substr($url, 0, -4);
}
 
if ($path && $path[0] != '/') {
$path = '/'.$path;
}
 
if (substr($url, -5) == 'index') {
$url = substr($url, 0, -5).$this->multiViewsIndex;
}
 
if ($op == 'index') {
$url .= '/';
} else if (is_object($rep)) {
$url .= '/'.$rep->getDisplayName().str_replace('%2F', '/', rawurlencode($path ?? ''));
 
if ($op && $op != 'dir' && $op != 'file') {
$params['op'] = $op;
}
}
 
} else {
switch ($op) {
case 'index':
$url = '.';
break;
 
case 'dir':
$url = 'listing.php';
break;
 
case 'revision':
$url = 'revision.php';
break;
 
case 'file':
$url = 'filedetails.php';
break;
 
case 'log':
$url = 'log.php';
break;
 
case 'diff':
$url = 'diff.php';
break;
 
case 'blame':
$url = 'blame.php';
break;
 
case 'form':
$url = 'form.php';
break;
 
case 'rss':
$url = 'rss.php';
break;
 
case 'dl':
$url = 'dl.php';
break;
 
case 'comp':
$url = 'comp.php';
break;
 
case 'search':
$url = 'search.php';
break;
}
 
if (is_object($rep) && $op != 'index') {
$params['repname'] = $rep->getDisplayName();
}
if (!empty($path)) {
$params['path'] = $path;
}
}
 
return array($url, $params);
}
 
// }}}
 
// {{{ Paths and Commands
 
// setPath
//
// Set the location of the given path
 
function _setPath(&$var, $path, $name, $params = '') {
if ($path == '') {
// Search in system search path. No check for existence possible
$var = $name;
} else {
$lastchar = substr($path, -1, 1);
$isDir = ($lastchar == DIRECTORY_SEPARATOR || $lastchar == '/' || $lastchar == '\\');
 
if (!$isDir) $path .= DIRECTORY_SEPARATOR;
 
if (($this->serverIsWindows && !file_exists($path.$name.'.exe')) || (!$this->serverIsWindows && !file_exists($path.$name))) {
echo 'Unable to find "'.$name.'" tool at location "'.$path.$name.'"';
exit;
}
 
// On a windows machine we need to put quotes around the
// entire command to allow for spaces in the path
if ($this->serverIsWindows) {
$var = '"'.$path.$name.'"';
} else {
$var = $path.$name;
}
}
 
// Append parameters
if ($params != '') $var .= ' '.$params;
}
 
// Define directory path to use for --config-dir parameter
function setSvnConfigDir($path) {
$this->_svnConfigDir = $path;
$this->_updateSvnCommand();
}
 
// Define flag to use --trust-server-cert parameter
function setTrustServerCert() {
$this->_svnTrustServerCert = true;
$this->_updateSvnCommand();
}
 
// Define the location of the svn command (e.g. '/usr/bin')
function setSvnCommandPath($path) {
$this->_svnCommandPath = $path;
$this->_updateSvnCommand();
}
 
// Define the location of the svnauthz command (e.g. '/usr/bin')
function setSvnAuthzCommandPath($path) {
$this->_setPath($this->svnAuthz, $path, 'svnauthz', 'accessof');
}
 
function _updateSvnCommand() {
$this->_setPath($this->svn, $this->_svnCommandPath, 'svn', '--non-interactive --config-dir '.$this->_svnConfigDir.($this->_svnTrustServerCert ? ' --trust-server-cert' : ''));
}
 
function getSvnCommand() {
return $this->svn;
}
 
function getSvnAuthzCommand() {
return $this->svnAuthz;
}
 
// setDiffPath
//
// Define the location of the diff command
 
function setDiffPath($path) {
$this->_setPath($this->diff, $path, 'diff');
}
 
function getDiffCommand() {
return $this->diff;
}
 
// setEnscriptPath
//
// Define the location of the enscript command
 
function setEnscriptPath($path) {
$this->_setPath($this->enscript, $path, 'enscript', '-q');
}
 
function getEnscriptCommand() {
return $this->enscript;
}
 
// setSedPath
//
// Define the location of the sed command
 
function setSedPath($path) {
$this->_setPath($this->sed, $path, 'sed');
}
 
function getSedCommand() {
return $this->sed;
}
 
// setTarPath
//
// Define the location of the tar command
 
function setTarPath($path) {
$this->_setPath($this->tar, $path, 'tar');
}
 
function getTarCommand() {
return $this->tar;
}
 
// setGzipPath
//
// Define the location of the GZip command
 
function setGzipPath($path) {
$this->_setPath($this->gzip, $path, 'gzip');
}
 
function getGzipCommand() {
return $this->gzip;
}
 
// setZipPath
//
// Define the location of the zip command
function setZipPath($path) {
$this->_setPath($this->zip, $path, 'zip');
}
 
function getZipPath() {
return $this->zip;
}
 
// setLocale
//
// Set the locale for PHP and all spawned processes
 
function setLocale($locale) {
$this->locale = $locale;
}
 
function getLocale() {
return $this->locale;
}
 
// setDefaultFileDlMode
//
// Define the default file download mode - one of [gzip, zip, plain]
function setDefaultFileDlMode($dlmode) {
if (in_array($dlmode, $this->validFileDlModes)) {
$this->defaultFileDlMode = $dlmode;
} else {
echo 'Setting default file download mode to an invalid value "'.$dlmode.'"';
exit;
}
}
 
function getDefaultFileDlMode() {
return $this->defaultFileDlMode;
}
 
// setDefaultDirectoryDlMode
//
// Define the default directory download mode - one of [gzip, zip]
function setDefaultDirectoryDlMode($dlmode) {
if (in_array($dlmode, $this->validDirectoryDlModes)) {
$this->defaultDirectoryDlMode = $dlmode;
} else {
echo 'Setting default directory download mode to an invalid value "'.$dlmode.'"';
exit;
}
}
 
function setDefaultFolderDlMode($dlmode) {
$this->setDefaultDirectoryDlMode($dlmode);
}
 
function getDefaultDirectoryDlMode() {
return $this->defaultDirectoryDlMode;
}
 
function getDefaultFolderDlMode() {
return $this->getDefaultDirectoryDlMode();
}
 
// Templates
 
function addTemplatePath($path) {
$lastchar = substr($path, -1, 1);
if ($lastchar != '/' && $lastchar != '\\') {
$path .= DIRECTORY_SEPARATOR;
}
 
if (!in_array($path, $this->templatePaths)) {
$this->templatePaths[] = $path;
}
}
 
function setTemplatePath($path, $myrep = null) {
$lastchar = substr($path, -1, 1);
if ($lastchar != '/' && $lastchar != '\\') {
$path .= DIRECTORY_SEPARATOR;
}
 
if ($myrep !== null) {
// fixed template for specific repository
$repo =& $this->findRepository($myrep);
$repo->setTemplatePath($path);
} else {
// for backward compatibility
if (in_array($path, $this->templatePaths)) {
array_splice($this->templatePaths, array_search($path, $this->templatePaths), 1);
}
array_unshift($this->templatePaths, $path);
}
}
 
function getTemplatePath() {
if (count($this->templatePaths) == 0) {
echo 'No template path added in config file';
exit;
}
if ($this->userTemplate !== false)
return $this->userTemplate;
else
return $this->templatePaths[0];
}
 
// }}}
 
function setDefaultLanguage($language) {
$this->defaultLanguage = $language;
}
 
function getDefaultLanguage() {
return $this->defaultLanguage;
}
 
function ignoreUserAcceptedLanguages() {
$this->ignoreAcceptedLanguages = true;
}
 
function useAcceptedLanguages() {
return !$this->ignoreAcceptedLanguages;
}
 
// {{{ Tab expansion functions
 
function expandTabsBy($sp, $myrep = 0) {
if (empty($myrep)) {
$this->spaces = $sp;
} else {
$repo =& $this->findRepository($myrep);
$repo->expandTabsBy($sp);
}
}
 
function getExpandTabsBy() {
return $this->spaces;
}
 
// }}}
 
// {{{ Bugtraq issue tracking
 
function setBugtraqEnabled($enabled, $myrep = 0) {
if (empty($myrep)) {
$this->bugtraq = $enabled;
} else {
$repo =& $this->findRepository($myrep);
$repo->setBugtraqEnabled($enabled);
}
}
 
function isBugtraqEnabled() {
return $this->bugtraq;
}
 
function setBugtraqProperties($message, $logregex, $url, $append = true, $myrep = null) {
$properties = array();
$properties['bugtraq:message'] = $message;
$properties['bugtraq:logregex'] = $logregex;
$properties['bugtraq:url'] = $url;
$properties['bugtraq:append'] = (bool)$append;
if ($myrep === null) {
$this->bugtraqProperties = $properties;
} else {
$repo =& $this->findRepository($myrep);
$repo->setBugtraqProperties($properties);
}
}
 
function getBugtraqProperties() {
return $this->bugtraqProperties;
}
 
// }}}
 
// {{{ Misc settings
 
function ignoreSvnMimeTypes() {
$this->ignoreSvnMimeTypes = true;
}
 
function getIgnoreSvnMimeTypes() {
return $this->ignoreSvnMimeTypes;
}
 
function ignoreWebSVNContentTypes() {
$this->ignoreWebSVNContentTypes = true;
}
 
function getIgnoreWebSVNContentTypes() {
return $this->ignoreWebSVNContentTypes;
}
 
function useAccessFile($file, $myrep = 0) {
if (empty($myrep)) {
if (is_readable($file)) {
if ($this->authz === null) {
$this->authz = new Authorization();
}
$this->authz->addAccessFile($file);
} else {
echo 'Unable to read access file "'.$file.'"';
exit;
}
} else {
$repo =& $this->findRepository($myrep);
$repo->useAccessFile($file);
}
}
 
function &getAuthz() {
return $this->authz;
}
 
function areRobotsBlocked() {
return $this->blockRobots;
}
 
function setBlockRobots($value = true) {
$this->blockRobots = $value;
}
 
function useTreeView() {
$this->treeView = true;
}
 
function getUseTreeView() {
return $this->treeView;
}
 
function useFlatView() {
$this->treeView = false;
}
 
function useTreeIndex($open) {
$this->flatIndex = false;
$this->openTree = $open;
}
 
function getUseFlatIndex() {
return $this->flatIndex;
}
 
function getOpenTree() {
return $this->openTree;
}
 
function setLoadAllRepos($flag) {
$this->loadAllRepos = $flag;
}
 
function showLoadAllRepos() {
return $this->loadAllRepos;
}
 
function setAlphabeticOrder($flag) {
$this->alphabetic = $flag;
}
 
function isAlphabeticOrder() {
return $this->alphabetic;
}
 
function showLastModInIndex() {
return $this->showLastModInIndex;
}
 
function setShowLastModInIndex($show) {
$this->showLastModInIndex = $show;
}
 
function showLastModInListing() {
return $this->showLastModInListing;
}
 
function setShowLastModInListing($show) {
$this->showLastModInListing = $show;
}
 
function showAgeInsteadOfDate() {
return $this->showAgeInsteadOfDate;
}
 
function setShowAgeInsteadOfDate($show) {
$this->showAgeInsteadOfDate = $show;
}
 
function showRepositorySelectionForm() {
return $this->_showRepositorySelectionForm;
}
 
function setShowRepositorySelectionForm($show) {
$this->_showRepositorySelectionForm = $show;
}
 
function getIgnoreWhitespacesInDiff() {
return $this->_ignoreWhitespacesInDiff;
}
 
function setIgnoreWhitespacesInDiff($ignore) {
$this->_ignoreWhitespacesInDiff = $ignore;
}
 
// Methods for storing version information for the command-line svn tool
 
function setSubversionVersion($subversionVersion) {
$this->subversionVersion = $subversionVersion;
}
 
function getSubversionVersion() {
return $this->subversionVersion;
}
 
function setSubversionMajorVersion($subversionMajorVersion) {
$this->subversionMajorVersion = $subversionMajorVersion;
}
 
function getSubversionMajorVersion() {
return $this->subversionMajorVersion;
}
 
function setSubversionMinorVersion($subversionMinorVersion) {
$this->subversionMinorVersion = $subversionMinorVersion;
}
 
function getSubversionMinorVersion() {
return $this->subversionMinorVersion;
}
 
// }}}
 
// {{{ Sort the repostories
//
// This function sorts the repositories by group name. The contents of the
// group are left in there original order, which will either be sorted if the
// group was added using the parentPath function, or defined for the order in
// which the repositories were included in the user's config file.
//
// Note that as of PHP 4.0.6 the usort command no longer preserves the order
// of items that are considered equal (in our case, part of the same group).
// The mergesort function preserves this order.
 
function sortByGroup() {
if (!empty($this->_repositories)) {
mergesort($this->_repositories, 'cmpGroups');
}
}
 
// }}}
 
// {{{ Change the name of the breadcrumb root-phrase to that of the current repo?
 
function setBreadcrumbRepoRootAsRepo($newValue) {
$this->breadcrumbRepoRootAsRepo = $newValue;
}
 
function getBreadcrumbRepoRootAsRepo() {
return $this->breadcrumbRepoRootAsRepo;
}
 
// }}}
}
/WebSVN/include/diff_inc.php
0,0 → 1,349
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// diff_inc.php
//
// Diff to files
 
if (!defined('USE_AUTOLOADER')) {
@include_once 'Horde/String.php';
@include_once 'Horde/Text/Diff.php';
@include_once 'Horde/Text/Diff/Mapped.php';
@include_once 'Horde/Text/Diff/Engine/Native.php';
@include_once 'Horde/Text/Diff/Op/Base.php';
@include_once 'Horde/Text/Diff/Op/Copy.php';
@include_once 'Horde/Text/Diff/Op/Delete.php';
@include_once 'Horde/Text/Diff/Op/Add.php';
@include_once 'Horde/Text/Diff/Op/Change.php';
@include_once 'Horde/Text/Diff/Renderer.php';
@include_once 'Horde/Text/Diff/Renderer/Unified.php';
}
include_once 'include/diff_util.php';
 
$arrayBased = false;
$fileBased = false;
 
class ListingHelper {
var $_listing = array();
var $_index = 0;
var $_blockStart = false;
 
function _add($text1, $lineno1, $class1, $text2, $lineno2, $class2) {
$listing = &$this->_listing;
$index = &$this->_index;
 
$listvar = &$listing[$index];
$listvar['rev1diffclass'] = $class1;
$listvar['rev2diffclass'] = $class2;
 
$listvar['rev1line'] = $text1;
$listvar['rev2line'] = $text2;
 
$listvar['rev1lineno'] = $lineno1;
$listvar['rev2lineno'] = $lineno2;
$listvar['startblock'] = $this->_blockStart;
$this->_blockStart = false;
$index++;
}
 
function addDeletedLine($text, $lineno) {
$this->_add($text, $lineno, 'diffdeleted', '&nbsp;', '-', 'diffempty');
}
 
function addAddedLine($text, $lineno) {
$this->_add('&nbsp;', '-', 'diffempty', $text, $lineno, 'diffadded');
}
 
function addChangedLine($text1, $lineno1, $text2, $lineno2) {
$this->_add($text1, $lineno1, 'diffchanged', $text2, $lineno2, 'diffchanged');
}
 
// note that $text1 do not need to be equal $text2 if $ignoreWhitespace is true
function addLine($text1, $lineno1, $text2, $lineno2) {
$this->_add($text1, $lineno1, 'diff', $text2, $lineno2, 'diff');
}
 
function startNewBlock() {
$this->_blockStart = true;
}
 
function getListing() {
return $this->_listing;
}
}
 
function nextLine(&$obj) {
global $arrayBased, $fileBased;
if ($arrayBased) return array_shift($obj);
if ($fileBased) return fgets($obj);
return '';
}
 
function endOfFile(&$obj) {
global $arrayBased, $fileBased;
if ($arrayBased) return count($obj) == 0;
if ($fileBased) return feof($obj);
return true;
}
 
 
function getWrappedLineFromFile($file, $is_highlighted) {
$line = fgets($file);
if ($line === false) return false;
$line = toOutputEncoding($line);
if (!$is_highlighted) {
$line = escape($line);
}
$line = rtrim($line, "\n\r");
if (strip_tags($line) === '') $line = '&nbsp;';
return wrapInCodeTagIfNecessary($line);
}
 
function diff_result($all, $highlighted, $newtname, $oldtname, $obj, $ignoreWhitespace) {
$ofile = fopen($oldtname, 'r');
$nfile = fopen($newtname, 'r');
 
// Get the first real line
$line = nextLine($obj);
 
$index = 0;
$listingHelper = new ListingHelper();
 
$curoline = 1;
$curnline = 1;
 
$sensibleLineChanges = new SensibleLineChanges(new LineDiff($ignoreWhitespace));
 
while (!endOfFile($obj)) {
// Get the first line of this range
$oline = 0;
sscanf($line, '@@ -%d', $oline);
$line = substr($line, strpos($line, '+'));
$nline = 0;
sscanf($line, '+%d', $nline);
 
while ($curoline < $oline || $curnline < $nline) {
if ($curoline < $oline) {
$text1 = getWrappedLineFromFile($ofile, $highlighted);
$tmpoline = $curoline;
$curoline++;
} else {
$tmpoline = '?';
$text1 = '&nbsp';
}
 
if ($curnline < $nline) {
$text2 = getWrappedLineFromFile($nfile, $highlighted);
$tmpnline = $curnline;
$curnline++;
} else {
$tmpnline = '?';
$text2 = '&nbsp;';
}
 
if ($all) {
$listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline);
}
}
 
if (!$all && $line !== false) {
$listingHelper->startNewBlock();
}
 
$fin = false;
while (!endOfFile($obj) && !$fin) {
$line = nextLine($obj);
if ($line === false || $line === '' || strncmp($line, '@@', 2) == 0) {
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted);
$fin = true;
} else {
$mod = $line[0];
$line = substr($line, 1);
 
switch ($mod) {
case '-':
$text = getWrappedLineFromFile($ofile, $highlighted);
$sensibleLineChanges->addDeletedLine($line, $text, $curoline);
$curoline++;
break;
 
case '+':
$text = getWrappedLineFromFile($nfile, $highlighted);
$sensibleLineChanges->addAddedLine($line, $text, $curnline);
$curnline++;
break;
 
default:
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted);
 
$text1 = getWrappedLineFromFile($ofile, $highlighted);
$text2 = getWrappedLineFromFile($nfile, $highlighted);
$listingHelper->addLine($text1, $curoline, $text2, $curnline);
 
$curoline++;
$curnline++;
 
break;
}
}
 
if (!$fin) {
$index++;
}
}
}
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted);
 
// Output the rest of the files
if ($all) {
while (!feof($ofile) || !feof($nfile)) {
$noneof = false;
 
$text1 = getWrappedLineFromFile($ofile, $highlighted);
if ($text1 !== false) {
$tmpoline = $curoline;
$curoline++;
$noneof = true;
} else {
$tmpoline = '-';
$text1 = '&nbsp;';
}
 
 
$text2 = getWrappedLineFromFile($nfile, $highlighted);
if ($text2 !== false) {
$tmpnline = $curnline;
$curnline++;
$noneof = true;
} else {
$tmpnline = '-';
$text2 = '&nbsp;';
}
 
if ($noneof) {
$listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline);
}
 
}
}
 
fclose($ofile);
fclose($nfile);
 
return $listingHelper->getListing();
}
 
function command_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) {
global $config, $lang, $arrayBased, $fileBased;
 
$context = 5;
 
if ($all) {
// Setting the context to 0 makes diff generate the wrong line numbers!
$context = 1;
}
 
if ($ignoreWhitespace) {
$whitespaceFlag = ' -w';
} else {
$whitespaceFlag = '';
}
 
// Open a pipe to the diff command with $context lines of context:
$cmd = $config->diff.$whitespaceFlag.' -U '.$context.' "'.$oldtname.'" "'.$newtname.'"';
$diff = runCommand($cmd, true);
 
// Ignore the 3 header lines:
$line = array_shift($diff);
$line = array_shift($diff);
 
$arrayBased = true;
$fileBased = false;
 
if ($highlighted) {
$listing = diff_result($all, $highlighted, $newhlname, $oldhlname, $diff, $ignoreWhitespace);
} else {
$listing = diff_result($all, $highlighted, $newtname, $oldtname, $diff, $ignoreWhitespace);
}
 
return $listing;
}
 
function inline_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) {
global $arrayBased, $fileBased;
 
$context = 5;
if ($all) {
// Setting the context to 0 makes diff generate the wrong line numbers!
$context = 1;
}
 
// modify error reporting level to suppress deprecated/strict warning "Assigning the return value of new by reference"
$bckLevel = error_reporting();
$removeLevel = E_DEPRECATED;
$modLevel = $bckLevel & (~$removeLevel);
error_reporting($modLevel);
 
// Create the diff class
$fromLines = file($oldtname);
$toLines = file($newtname);
if (!$ignoreWhitespace) {
$diff = new Horde_Text_Diff('Native', array($fromLines, $toLines));
} else {
$whitespaces = array(' ', "\t", "\n", "\r");
$mappedFromLines = array();
foreach ($fromLines as $k => $line) {
$line = rtrim($line, "\n\r");
$fromLines[$k] = $line;
$mappedFromLines[] = str_replace($whitespaces, array(), $line);
}
$mappedToLines = array();
foreach ($toLines as $k => $line) {
$line = rtrim($line, "\n\r");
$toLines[$k] = $line;
$mappedToLines[] = str_replace($whitespaces, array(), $line);
}
$diff = new Horde_Text_Diff_Mapped('Native', array($fromLines, $toLines, $mappedFromLines, $mappedToLines));
}
$renderer = new Horde_Text_Diff_Renderer_Unified(array('leading_context_lines' => $context, 'trailing_context_lines' => $context));
$rendered = explode("\n", $renderer->render($diff));
 
// restore previous error reporting level
error_reporting($bckLevel);
 
$arrayBased = true;
$fileBased = false;
if ($highlighted) {
$listing = diff_result($all, $highlighted, $newhlname, $oldhlname, $rendered, $ignoreWhitespace);
} else {
$listing = diff_result($all, $highlighted, $newtname, $oldtname, $rendered, $ignoreWhitespace);
}
 
return $listing;
}
 
function do_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) {
if ((!$ignoreWhitespace ? class_exists('Horde_Text_Diff') : class_exists('Horde_Text_Diff_Mapped'))
&& class_exists('Horde_Text_Diff_Renderer_Unified')) {
return inline_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname);
} else {
return command_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname);
}
}
/WebSVN/include/diff_util.php
0,0 → 1,364
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// diff_util.php
//
// help diff_inc.php to make sensible changes from added and deleted diff lines
// These lines are automatically paired and also inline diff is performed to show
// insertions/deletions on one line. diff_inc.php must have all Horde_Text_Diff
// requirements met (include_once statements).
 
// Interface for diffing function
class LineDiffInterface {
// similarity 1 means that strings are very close to each other
// 0 means totally different
function lineSimilarity($text1, $text2) {
assert(false);
}
 
// return array($left, $right) annotated with <ins> and <del>
function inlineDiff($text1, $highlighted1, $text2, $highlighted2, $highlighted) {
assert(false);
}
}
 
// Default line diffing function
class LineDiff extends LineDiffInterface {
 
private bool $ignoreWhitespace;
 
function __construct($ignoreWhitespace) {
$this->ignoreWhitespace = $ignoreWhitespace;
}
 
// {{{ levenshtein2
// levenshtein edit distance, on small strings use php function
// on large strings approximate distance using words
// computed by dynamic programming
function levenshtein2($str1, $str2) {
if (strlen($str1) < 255 && strlen($str2) < 255) {
return levenshtein($str1, $str2);
}
 
$l1 = explode(' ', $str1);
$l2 = explode(' ', $str2);
 
$n = count($l1);
$m = count($l2);
$d = array_fill(0, $n + 1, array_fill(0, $m + 1, 0));
 
for ($i = 1; $i < $n + 1; $i++) {
$d[$i][0] = $i;
}
for ($j = 1; $j < $m + 1; $j++) {
$d[0][$j] = $j;
}
 
for ($i = 1; $i < $n + 1; $i++) {
for ($j = 1; $j < $m + 1; $j++) {
$c = ($l1[$i - 1] == $l2[$j - 1]) ? 0 : strlen($l1[$i - 1]) + strlen($l2[$j - 1]);
$d[$i][$j] = min($d[$i - 1][$j] + 1, $d[$i][$j - 1] + 1, $d[$i - 1][$j - 1] + $c);
}
}
 
return $d[$n][$m];
}
// }}}
 
// {{{ lineSimilarity
function lineSimilarity($text1, $text2) {
$distance = $this->levenshtein2($text1, $text2);
return max(0.0, 1.0 - $distance / (strlen($text1) + strlen($text2) + 4));
}
// }}}
 
// {{{ tokenize whole line into words
// note that separators are returned as tokens of length 1
// and if $ignoreWhitespace is true, consecutive whitespaces are returned as one token
function tokenize($string, $highlighted, $ignoreWhitespace) {
$html = array('<' => '>', '&' => ';');
$whitespaces = array("\t","\n","\r",' ');
$separators = array('.','-','+','*','/','<','>','?','(',')','&','/','{','}','[',']',':',';');
$data = array();
$segment = '';
$segmentIsWhitespace = true;
$count = strlen($string);
for ($i = 0; $i < $count; $i++) {
$c = $string[$i];
if ($highlighted && array_key_exists($c, $html)) {
if ($segment != '') {
$data[] = $segment;
}
// consider html tags and entities as a single token
$endchar = $html[$c];
$segment = $c;
do {
$i++;
$c = $string[$i];
$segment .= $c;
} while ($c != $endchar && $i < $count - 1);
$data[] = $segment;
$segment = '';
$segmentIsWhitespace = false;
} else if (in_array($c, $separators) || (!$ignoreWhitespace && in_array($c, $whitespaces))) {
// if it is separator or whitespace and we do not consider consecutive whitespaces
if ($segment != '') {
$data[] = $segment;
}
$data[] = $c;
$segment = '';
$segmentIsWhitespace = true;
} else if (in_array($c, $whitespaces)) {
// if it is whitespace and we consider consecutive whitespaces as one token
if (!$segmentIsWhitespace) {
$data[] = $segment;
$segment = '';
$segmentIsWhitespace = true;
}
$segment .= $c;
} else {
// no separator or whitespace
if ($segmentIsWhitespace && $segment != '') {
$data[] = $segment;
$segment = '';
}
$segment .= $c;
$segmentIsWhitespace = false;
}
}
if ($segment != '') {
$data[] = $segment;
}
return $data;
}
// }}}
 
// {{{ lineDiff
function inlineDiff($text1, $highlighted1, $text2, $highlighted2, $highlighted) {
$whitespaces = array(' ', "\t", "\n", "\r");
 
$do_diff = true;
 
if ($text1 == '' || $text2 == '') {
$do_diff = false;
}
 
if ($this->ignoreWhitespace && (str_replace($whitespaces, array(), $text1) == str_replace($whitespaces, array(), $text2))) {
$do_diff = false;
}
 
// Exit gracefully if loading of Horde_Text_Diff failed
if (!class_exists('Horde_Text_Diff') || !class_exists('Horde_Text_Diff_Mapped')) {
$do_diff = false;
}
 
// Return highlighted lines without doing inline diff
if (!$do_diff) {
return array($highlighted1, $highlighted2);
}
 
$tokens1 = $this->tokenize($highlighted1, $highlighted, $this->ignoreWhitespace);
$tokens2 = $this->tokenize($highlighted2, $highlighted, $this->ignoreWhitespace);
 
if (!$this->ignoreWhitespace) {
$diff = new Horde_Text_Diff('Native', array($tokens1, $tokens2));
} else {
// we need to create mapped parts for MappedDiff
$mapped1 = array();
foreach ($tokens1 as $token) {
$mapped1[] = str_replace($whitespaces, array(), $token);
}
$mapped2 = array();
foreach ($tokens2 as $token) {
$mapped2[] = str_replace($whitespaces, array(), $token);
}
$diff = new Horde_Text_Diff_Mapped('Native', array($tokens1, $tokens2, $mapped1, $mapped2));
}
 
// now, get the diff and annotate text
$edits = $diff->getDiff();
 
$line1 = '';
$line2 = '';
foreach ($edits as $edit) {
if ($edit instanceof Horde_Text_Diff_Op_Copy) {
$line1 .= implode('', $edit->orig);
$line2 .= implode('', $edit->final);
} else if ($edit instanceof Horde_Text_Diff_Op_Delete) {
$line1 .= '<del>'.implode('', $edit->orig).'</del>';
} else if ($edit instanceof Horde_Text_Diff_Op_Add) {
$line2 .= '<ins>'.implode('', $edit->final).'</ins>';
} else if ($edit instanceof Horde_Text_Diff_Op_Change) {
$line1 .= '<del>'.implode('', $edit->orig).'</del>';
$line2 .= '<ins>'.implode('', $edit->final).'</ins>';
} else {
assert(false);
}
}
return array($line1, $line2);
}
// }}}
}
 
// Class for computing sensibly added/deleted block of lines.
class SensibleLineChanges {
var $_added = array();
var $_deleted = array();
var $_lineDiff = null;
 
function __construct($lineDiff) {
$this->_lineDiff = $lineDiff;
}
 
function addDeletedLine($text, $highlighted_text, $lineno) {
$this->_deleted[] = array($text, $highlighted_text, $lineno);
}
 
function addAddedLine($text, $highlighted_text, $lineno) {
$this->_added[] = array($text, $highlighted_text, $lineno);
}
 
// this function computes simple match - first min(deleted,added) lines are marked as changed
// it is intended to be run instead of _computeBestMatching if the diff is too big
function _computeFastMatching($n, $m) {
$result = array();
$q = 0;
while ($q < $n && $q < $m) {
$result[] = array($this->_deleted[$q], $this->_added[$q]);
$q++;
}
while ($q < $n) {
$result[] = array($this->_deleted[$q], null);
$q++;
}
while ($q < $m) {
$result[] = array(null, $this->_added[$q]);
$q++;
}
return $result;
}
 
// {{{ _computeBestMatching
// dynamically compute best matching
// note that this is O(n*m) * O(line similarity)
function _computeBestMatching() {
$n = count($this->_deleted);
$m = count($this->_added);
 
// if the computation will be slow, just run fast algorithm
if ($n * $m > 10000) {
return $this->_computeFastMatching($n, $m);
}
 
// dyn[$i][$j] holds best sum of similarities we can obtain if we match
// first $i deleted lines and first $j added lines
$dyn = array_fill(0, $n + 1, array_fill(0, $m + 1, 0.0));
// backlinks, so we can reconstruct best layout easily
$back = array_fill(0, $n + 1, array_fill(0, $m + 1, -1));
 
// if there is no similarity, prefer adding/deleting lines
$value_del = 0.1;
$value_add = 0.1;
 
// initialize arrays
for ($i = 1; $i <= $n; $i++) {
$back[$i][0] = 0;
$dyn[$i][0] = $value_del * $i;
}
for ($j = 1; $j <= $m; $j++) {
$back[0][$j] = 1;
$dyn[0][$j] = $value_add * $j;
}
 
// main dynamic programming
for ($i = 1; $i <= $n; $i++) {
for ($j = 1; $j <= $m; $j++) {
$best = - 1.0;
$b = -1;
if ($dyn[$i - 1][$j] + $value_del >= $best) {
$b = 0;
$best = $dyn[$i - 1][$j] + $value_del;
}
if ($dyn[$i][$j - 1] + $value_add >= $best) {
$b = 1;
$best = $dyn[$i][$j - 1] + $value_add;
}
$sim = $this->_lineDiff->lineSimilarity($this->_deleted[$i - 1][0], $this->_added[$j - 1][0]);
if ($dyn[$i - 1][$j - 1] + $sim >= $best) {
$b = 2;
$best = $dyn[$i - 1][$j - 1] + $sim;
}
$back[$i][$j] = $b;
$dyn[$i][$j] = $best;
}
}
 
// compute layout for best result
$i = $n;
$j = $m;
$result = array();
 
while ($i + $j >= 1) {
switch($back[$i][$j]) {
case 2: array_push($result, array($this->_deleted[$i - 1], $this->_added[$j - 1]));
$i--;
$j--;
break;
case 1: array_push($result, array(null, $this->_added[$j - 1]));
$j--;
break;
case 0: array_push($result, array($this->_deleted[$i - 1], null));
$i--;
break;
default:
assert(false);
}
}
return array_reverse($result);
}
// }}}
 
// {{{ addChangesToListing
// add computed changes to the listing
function addChangesToListing(&$listingHelper, $highlighted) {
$matching = $this->_computeBestMatching();
foreach ($matching as $change) {
if ($change[1] == null) {
// deleted -- preserve original highlighted text
$listingHelper->addDeletedLine($change[0][1], $change[0][2]);
} else if ($change[0] == null) {
// added -- preserve original highlighted text
$listingHelper->addAddedLine($change[1][1], $change[1][2]);
} else {
// this is fully changed line, make inline diff
$diff = $this->_lineDiff->inlineDiff($change[0][0], $change[0][1], $change[1][0], $change[1][1], $highlighted);
$listingHelper->addChangedLine($diff[0], $change[0][2], $diff[1], $change[1][2]);
}
}
$this->clear();
}
// }}}
 
function clear() {
$this->_added = array();
$this->_deleted = array();
}
}
 
/WebSVN/include/distconfig.php
0,0 → 1,528
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// config.php
//
// Configuration parameters
 
// --- FOLLOW THE INSTRUCTIONS BELOW TO CONFIGURE YOUR SETUP ---
 
// {{{ PLATFORM CONFIGURATION ---
 
// Configure a UTF-8 aware locale to properly convert bytes to characters.
// Otherwise files and directories with non-ASCII encoding are deemed to fail
// with native commands.
// $config->setLocale('C.UTF-8');
 
// Configure the path for Subversion to use for --config-dir
// (e.g. if accepting certificates is required when using repositories via https)
// $config->setSvnConfigDir('/tmp/websvn');
 
// Configure these lines if your commands aren't on your path.
//
// $config->setSvnCommandPath('/path/to/svn/command/'); // e.g. c:\\program files\\subversion\\bin
// $config->setSvnAuthzCommandPath('/path/to/svnauthz/command/'); // e.g. c:\\program files\\subversion\\bin\tools
// $config->setDiffPath('/path/to/diff/command/');
 
// For syntax colouring, if option enabled...
// $config->setEnscriptPath('/path/to/enscript/command/');
// $config->setSedPath('/path/to/sed/command/');
 
// For delivered tarballs, if option enabled...
// $config->setTarPath('/path/to/tar/command/');
 
// For delivered GZIP'd files and tarballs, if option enabled...
// $config->setGZipPath('/path/to/gzip/command/');
 
// download directory/file zipped ...
// $config->setZipPath('/path/to/zip/command/');
 
// Uncomment this line to trust server certificates
// This may useful if you use self-signed certificates and have no chance to accept the certificate once via cli
// $config->setTrustServerCert();
 
// }}}
 
// {{{ REPOSITORY SETUP ---
 
// There are 2 methods for defining the repositiories available on the system.
// Either you list them by hand, in which case you can give each one the name of
// your choice, or you use the parent path function, in which case the name of
// the directory is used as the repository name.
//
// In all cases, you may optionally supply a group name to the repositories.
// This is useful in the case that you need to separate your projects. Grouped
// repositories are referred to using the convention GroupName.RepositoryName
//
// You may also optionally specify the URL that clients should use to check out
// a working copy. If used, it must be specified after the group, username, and
// password; if these arguments are not needed, then pass null instead. Consult
// the WebSvnConfig class in include/configclass.php for function details.
//
// Performance is much better on local repositories (e.g. accessed by file://).
// However, you can also provide an interface onto a remote repository. In this
// case you should supply the username and password needed to access it.
//
// To configure the repositories by hand, copy the appropriate line below,
// uncomment it and replace the name and URL of your repository.
 
// Local repositories (without and with optional group):
// Note that the local URL to the repository depends on your platform:
// Unix-like: file:///path/to/rep
// Windows: file:///c:/svn/proj
//
// $config->addRepository('NameToDisplay', 'local URL');
// $config->addRepository('NameToDisplay', 'local URL', 'group');
//
// Remote repositories (without and with optional group):
// A remote URL looks like http://domain.tld/path/to/rep
//
// $config->addRepository('NameToDisplay', 'remote URL', null, 'username', 'password');
// $config->addRepository('NameToDisplay', 'remote URL', 'group', 'username', 'password');
//
// Display Part of a repository as if it was a repository.
//
// Local repositories (without and with optional group):
//
// $config->addRepositorySubpath('NameToDisplay', 'local URL', 'subpath');
// $config->addRepositorySubpath('NameToDisplay', 'local URL', 'subpath', 'group');
//
// Remote repositories (without and with optional group):
//
// $config->addRepositorySubpath('NameToDisplay', 'remote URL', 'subpath', null, 'username', 'password');
// $config->addRepositorySubpath('NameToDisplay', 'remote URL', 'subpath', 'group', 'username', 'password');
//
// To use the parent path method (without and with optional group), uncomment the next line
// and replace the path with your one. You can call the function several times if you have several parent paths.
// Note that in this case the path is a filesystem path and depends on your platform:
// Unix-like: /path/to/parent
// Windows: c:\\svn
//
// $config->parentPath('filesystem path');
// $config->parentPath('filesystem path', 'group');
//
// To exclude a repository from being added by the parentPath method uncomment the next line
// and replace the path with your one. You can call the function several times if you have several paths to exclude.
//
// $config->addExcludedPath('filesystem path of excluded rep');
//
// To add only a subset of repositories specified by the parent path you can call the function with a pattern.
//
// $config->parentPath('filesystem path', 'group', '/^beginwith/');
 
// }}}
 
// {{{ LOOK AND FEEL ---
//
// Add custom template paths or comment out templates to modify the list of user selectable templates.
// The first added template serves as a default.
 
$config->addTemplatePath($locwebsvnreal.'/templates/calm/');
$config->addTemplatePath($locwebsvnreal.'/templates/BlueGrey/');
$config->addTemplatePath($locwebsvnreal.'/templates/Elegant/');
 
// You may also specify a default template by uncommenting and changing the following line as necessary.
// If no default template is set the first added template is used.
 
// $config->setTemplatePath($locwebsvnreal.'/templates/Elegant/');
 
// You may also specify a per repository fixed template by uncommenting and changing the following
// line as necessary. Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setTemplatePath($locwebsvnreal.'/templates/Elegant/', 'myrep');
 
// The index page containing the projects may either be displayed as a flat view (the default),
// where grouped repositories are displayed as 'GroupName.RepName' or as a tree view.
// In the case of a tree view, you may choose whether the entire tree is open by default.
 
// $config->useTreeIndex(false); // Tree index, closed by default
// $config->useTreeIndex(true); // Tree index, open by default
 
// By default, WebSVN displays a tree view onto the current directory. You can however
// choose to display a flat view of the current directory only, which may make the display
// load faster. Uncomment this line if you want that.
 
// $config->useFlatView();
 
// By default, WebSVN displays subdirectories first and than the files of a directory,
// both alphabetically sorted.
// To use alphabetic order independent of directories and files uncomment this line.
 
// $config->setAlphabeticOrder(true);
 
// By default, WebSVN loads parent path directories and then on user click other,
// This options loads the entire directory in one go and allows to browse without delay.
// By default all will be collapsed to root directory and can be expanded.
// The performance will be impacted as it takes time to load up all the things in the
// repository. Once loaded directory exapansion is instantaneous.
// The alphabetical order is applied to all directory and files.
// This means that grouping of all dirs together and all files together is NOT supported currently!
// The files and directories are shown as is with a mixture of files and folders.
 
// $config->setLoadAllRepos(true);
 
// By default, WebSVN displays the information of the last modification
// (revision, age and author) for each repository in an extra column.
// To disable that uncomment this line.
 
// $config->setShowLastModInIndex(false);
 
// By default, WebSVN displays the information of the last modification
// (revision, age and author) for each file and directory in an extra column.
// To disable that uncomment this line.
 
// $config->setShowLastModInListing(false);
 
// By default, WebSVN displays the age of the last modification.
// Alternativly the date of the last modification can be shown.
// To show dates instead of ages uncomment this line.
 
// $config->setShowAgeInsteadOfDate(false);
 
// By default, WebSVN displays the a form to select an other repository.
// If you have a lot of repositories this slows done the script considerably.
// To disable that uncomment this line.
 
// $config->setShowRepositorySelectionForm(false);
 
// By default, WebSVN does not ignore whitespaces when showing diffs.
// To enable ignoring whitespaces in diffs per default uncomment this line.
 
// $config->setIgnoreWhitespacesInDiff(true);
 
// }}}
 
// {{{ LANGUAGE SETUP ---
 
// Set the default language. If you want English then don't do anything here.
//
// $config->setDefaultLanguage('en');
 
// Ignore the user supplied accepted languages to choose reasonable default language.
// If you want to force the default language - regardless of the client - uncomment the following line.
//
// $config->ignoreUserAcceptedLanguages();
 
// }}}
 
// {{{ MULTIVIEWS ---
 
// Uncomment this line if you want to use MultiView to access the repository by, for example:
//
// http://servername/browse/repname/path/in/repository
//
// Note: The websvn directory will need to have Multiviews turned on in Apache, and you'll need to configure browse.php
 
// $config->useMultiViews();
 
// }}}
 
// {{{ ACCESS RIGHTS ---
 
// Uncomment this line if you want to use your Subversion access file to control access
// rights via WebSVN. For this to work, you'll need to set up the same Apache based authentication
// to the WebSVN (or browse) directory as you have for Subversion itself. More information can be
// found in install.txt
 
// $config->useAccessFile('/path/to/accessfile'); // Global access file
 
// You may also specify a per repository access file by uncommenting and copying the following
// line as necessary. Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->useAccessFile('/path/to/accessfile', 'myrep'); // Access file for myrep
 
// Uncomment this line if you want to prevent search bots to index the WebSVN pages.
 
// $config->setBlockRobots();
 
// }}}
 
// {{{ FILE CONTENT ---
//
// You may wish certain file types to be GZIP'd and delieved to the user when clicked apon.
// This is useful for binary files and the like that don't display well in a browser window!
// Copy, uncomment and modify this line for each extension to which this rule should apply.
// (Don't forget the . before the extension. You don't need an index between the []'s).
// If you'd rather that the files were delivered uncompressed with the associated MIME type,
// then read below.
//
// $zipped[] = '.dll';
 
// Subversion controlled files have an svn:mime-type property that can
// be set on a file indicating its mime type. By default binary files
// are set to the generic appcliation/octet-stream, and other files
// don't have it set at all. WebSVN also has a built-in list of
// associations from file extension to MIME content type. (You can
// view this list in setup.php).
//
// Determining the content-type: By default, if the svn:mime-type
// property exists and is different from application/octet-stream, it
// is used. Otherwise, if the built-in list has a contentType entry
// for the extension of the file, that is used. Otherwise, if the
// svn:mime-type property exists has the generic binary value of
// application/octet-stream, the file will be served as a binary
// file. Otherwise, the file will be brought up as ASCII text in the
// browser window (although this text may optionally be colourised.
// See below).
//
// Uncomment this if you want to ignore any svn:mime-type property on your
// files.
//
// $config->ignoreSvnMimeTypes();
//
// Uncomment this if you want skip WebSVN's custom mime-type handling
//
// $config->ignoreWebSVNContentTypes();
//
// Following the examples below, you can add new associations, modify
// the default ones or even delete them entirely (to show them in
// ASCII via WebSVN).
 
// $contentType['.c'] = 'text/plain'; // Create a new association
// $contentType['.doc'] = 'text/plain'; // Modify an existing one
// unset($contentType['.m']); // Remove a default association
 
// If you want to selectively override one or more MIME types to display inline
// (e.g., the svn:mime-type property is something like text/plain or text/xml, or
// the file extension matches an entry in $contentType), you can choose to ignore
// one or more specific MIME types. This approach is finer-grained than ignoring
// all svn:mime-type properties, and displaying matching files inline such that
// they are highlighted correctly. (Regular expression matching is used.)
 
$config->addInlineMimeType('text/plain');
// $config->addInlineMimeType('text/*');
 
// }}}
 
// {{{ TARBALLS ---
 
// You need tar and gzip installed on your system. Set the paths above if necessary
//
// Uncomment the line below to offer a tarball download option across all your
// repositories.
//
// $config->allowDownload();
//
// Set download modes
// $config->setDefaultFileDlMode('plain');
// $config->setDefaultDirectoryDlMode('gzip');
//
// To change the global option for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->allowDownload('myrep'); // Specifically allow downloading for 'myrep'
// $config->disallowDownload('myrep'); // Specifically disallow downloading for 'myrep'
 
// You can also choose the minimum directory level from which you'll allow downloading.
// A value of zero will allow downloading from the root. 1 will allow downloding of directories
// in the root, etc.
//
// If your project is arranged with trunk, tags and branches at the root level, then a value of 2
// would allow the downloading of directories within branches/tags while disallowing the download
// of the entire branches or tags directories. This would also stop downloading of the trunk, but
// see after for path exceptions.
//
// Change the line below to set the download level across all your repositories.
 
$config->setMinDownloadLevel(2);
 
// To change the level for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setMinDownloadLevel(2, 'myrep');
 
// Finally, you may add or remove certain directories (and their contents) either globally
// or on a per repository basis. Uncomment and copy the following lines as necessary. Note
// that the these are searched in the order than you give them until a match is made (with the
// exception that all the per repository exceptions are tested before the global ones). This means
// that you must disallow /a/b/c/ before you allow /a/b/ otherwise the allowed match on /a/b/ will
// stop any further searching, thereby allowing downloads on /a/b/c/.
 
// Global exceptions possibilties:
//
// $config->addAllowedDownloadException('/path/to/allowed/directory/');
// $config->addDisAllowedDownloadException('/path/to/disallowed/directory/');
//
// Per repository exception possibilties:
// Use the convention 'groupname.myrep' if your repository is in a group.
//
// $config->addAllowedDownloadException('/path/to/allowed/directory/', 'myrep');
// $config->addDisAllowedDownloadException('/path/to/disallowed/directory/', 'myrep');
 
// }}}
 
// {{{ COLOURISATION ---
 
// Uncomment this line if you want to use Enscript to colourise your file listings
//
// You'll need Enscript version 1.6 or higher AND Sed installed to use this feature.
// Set the path above.
//
// If you have version 1.6.3 or newer use the following line.
//
// $config->useEnscript();
//
// If you have version 1.6.2 or older use the following line.
//
// $config->useEnscript(true);
 
// Enscript need to be told what the contents of a file are so that it can be colourised
// correctly. WebSVN includes a predefined list of mappings from file extension to Enscript
// file type (viewable in setup.php).
//
// Here you should add and other extensions not already listed or redefine the default ones. eg:
//
// $extEnscript['.pas'] = 'pascal';
//
// Note that extensions are case sensitive.
 
// Uncomment this line if you want to use GeSHi to colourise your file listings
//
// $config->useGeshi();
// $config->setGeshiPath('/usr/share/php-geshi'); // optional. Use if you have Geshi installed without PEAR/Composer
 
// GeSHi need to be told what the contents of a file are so that it can be colourised
// correctly. WebSVN includes a predefined list of mappings from file extension to GeSHi
// languages (viewable in setup.php).
//
// Here you should add and other extensions not already listed or redefine the default ones. eg:
//
// $extGeshi['pascal'] = array('p', 'pas');
//
// Note that extensions are case sensitive.
 
// }}}
 
// {{{ Markdown Render
 
// Uncomment this line if you want to enable Markdown Rendering of README.md file in the path.
// You will need the Parsedown.php (https://github.com/erusev/parsedown) library for this to work.
// This will look for README.md file on the path and render it.
// The name of "README.md" isn't configurable for now to simply follow GitHub's conventions.
 
// $config->useParsedown();
// $config->setParsedownPath('/usr/share/php/Parsedown/'); // optional. Use if you have Parsedown installed without PEAR/Composer
 
// }}}
 
// {{{ RSSFEED ---
 
// Uncomment this line to hide the RSS feed links across all repositories
 
// $config->setRssEnabled(false);
 
// To override the global setting for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setRssEnabled(false, 'myrep');
// $config->setRssEnabled(true, 'myrep');
 
// Uncomment this line to enable caching RSS feeds across all repositories
// This may create a large number of cache files which are currently not garbaged automatically
 
// $config->setRssCachingEnabled(true);
 
// To override the global setting for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setRssCachingEnabled(true, 'myrep');
// $config->setRssCachingEnabled(false, 'myrep');
 
// Uncomment this line to change the maximum number of RSS entries to display across all repositories
 
// $config->setRssMaxEntries(50);
 
// To override the global setting for individual repositories, uncomment and replicate
// the line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setRssMaxEntries(50, 'myrep');
 
// }}}
 
// {{{ SHOW CHANGED FILES IN LOG ---
 
// Uncomment this line to show changed files on log.php by default. The normal
// behavior is to do this only if the "Show changed files" link is clicked. This
// setting reverses the default action but still allows hiding changed files.
 
// $config->setLogsShowChanges(true);
 
// To override the global setting for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setLogsShowChanges(true, 'myrep');
// $config->setLogsShowChanges(false, 'myrep');
 
// }}}
 
// {{{ BUGTRAQ ---
 
// Uncomment this line to use bugtraq: properties to show links to your BugTracker
// from log messages.
 
// $config->setBugtraqEnabled(true);
 
// To override the global setting for individual repositories, uncomment and replicate
// the appropriate line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->setBugtraqEnabled(true, 'myrep');
// $config->setBugtraqEnabled(false, 'myrep');
 
// Usually the information to extract the bugtraq information and generate links are
// stored in SVN properties starting with 'bugtraq:':
// namely 'bugtraq:message', 'bugtraq:logregex', 'bugtraq:url' and 'bugtraq:append'.
// To override the SVN properties globally or for individual repositories, uncomment
// the appropriate line below (replacing 'myrep' with the name of the repository).
 
// $config->setBugtraqProperties('bug #%BUGID%', 'issues? (\d+)([, ] *(\d+))*'."\n".'(\d+)', 'http://www.example.com/issues/show_bug.cgi?id=%BUGID%', false);
// $config->setBugtraqProperties('bug #%BUGID%', 'issues? (\d+)([, ] *(\d+))*'."\n".'(\d+)', 'http://www.example.com/issues/show_bug.cgi?id=%BUGID%', false, 'myrep');
 
// }}}
 
// {{{ MISCELLANEOUS ---
 
// Comment out this if you don't have the right to use it. Be warned that you may need it however!
set_time_limit(0);
 
// Change the line below to specify a temporary directory other than the one PHP uses.
 
// $config->setTempDir('temp');
 
// Number of spaces to expand tabs to in diff/listing view across all repositories
 
$config->expandTabsBy(8);
 
// To override the global setting for individual repositories, uncomment and replicate
// the line below (replacing 'myrep' with the name of the repository).
// Use the convention 'groupname.myrep' if your repository is in a group.
 
// $config->expandTabsBy(3, 'myrep'); // Expand Tabs by 3 for repository 'myrep'
 
// Change the name of the breadcrumb root-phrase to that of the current repo?
// $config->setBreadcrumbRepoRootAsRepo(true);
 
// }}}
/WebSVN/include/header
1,7 → 1,5
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
10,12 → 8,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
/WebSVN/include/setup.php
0,0 → 1,620
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// setup.php
//
// Global setup
 
// --- DON'T CHANGE THIS FILE ---
//
// User changes should be done in config.php
 
// Include the configuration class
require_once 'include/configclass.php';
 
// Register Composer autoloader if available
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
define('USE_AUTOLOADER', true);
}
 
// Create the config
$config = new WebSvnConfig();
 
if (DIRECTORY_SEPARATOR == '\\') {
$config->setServerIsWindows();
}
 
// Set up locwebsvnhttp
// Note: we will use nothing in MultiViews mode so that the URLs use the root
// directory by default.
if (empty($locwebsvnhttp)) {
$locwebsvnhttp = defined('WSVN_MULTIVIEWS') ? '' : '.';
}
if (empty($locwebsvnreal)) {
$locwebsvnreal = '.';
}
 
$vars['locwebsvnhttp'] = $locwebsvnhttp;
 
// {{{ Content Types
// Set up the default content-type extension handling
 
$contentType = array(
'.dwg' => 'application/acad', // AutoCAD Drawing files
'.arj' => 'application/arj',
'.ccad' => 'application/clariscad', // ClarisCAD files
'.drw' => 'application/drafting', // MATRA Prelude drafting
'.dxf' => 'application/dxf', // DXF (AutoCAD)
'.xls' => 'application/excel', // Microsoft Excel
'.unv' => 'application/i-deas', //SDRC I-DEAS files
'.igs' => 'application/iges', // IGES graphics format
'.iges' => 'application/iges', // IGES graphics format
'.hqx' => 'application/mac-binhex40', // Macintosh BinHex format
'.word' => 'application/msword', // Microsoft Word
'.w6w' => 'application/msword', // Microsoft Word
'.doc' => 'application/msword', // Microsoft Word
'.wri' => 'application/mswrite', // Microsoft Write
'.bin' => 'application/octet-stream', // Uninterpreted binary
'.exe' => 'application/x-msdownload', // Windows EXE
'.oda' => 'application/oda',
'.pdf' => 'application/pdf', // PDF (Adobe Acrobat)
'.ai' => 'application/postscript', // PostScript
'.ps' => 'application/postscript', // PostScript
'.eps' => 'application/postscript', // PostScript
'.prt' => 'application/pro_eng', // PTC Pro/ENGINEER
'.part' => 'application/pro_eng', // PTC Pro/ENGINEER
'.rtf' => 'application/rtf', // Rich Text Format
'.set' => 'application/set', // SET (French CAD standard)
'.stl' => 'application/sla', // Stereolithography
'.sol' => 'application/solids', // MATRA Prelude Solids
'.stp' => 'application/STEP', // ISO-10303 STEP data files
'.step' => 'application/STEP', // ISO-10303 STEP data files
'.vda' => 'application/vda', // VDA-FS Surface data
'.dir' => 'application/x-director', // Macromedia Director
'.dcr' => 'application/x-director', // Macromedia Director
'.dxr' => 'application/x-director', // Macromedia Director
'.mif' => 'application/x-mif', // FrameMaker MIF Format
'.csh' => 'application/x-csh', // C-shell script
'.dvi' => 'application/x-dvi', // TeX DVI
'.gz' => 'application/gzip', // GNU Zip
'.gzip' => 'application/gzip', // GNU Zip
'.hdf' => 'application/x-hdf', // ncSA HDF Data File
'.latex' => 'application/x-latex', // LaTeX source
'.nc' => 'application/x-netcdf', // Unidata netCDF
'.cdf' => 'application/x-netcdf', // Unidata netCDF
'.sit' => 'application/x-stuffit', // Stiffut Archive
'.tcl' => 'application/x-tcl', // TCL script
'.texinfo' => 'application/x-texinfo', // Texinfo (Emacs)
'.texi' => 'application/x-texinfo', // Texinfo (Emacs)
'.t' => 'application/x-troff', // Troff
'.tr' => 'application/x-troff', // Troff
'.roff' => 'application/x-troff', // Troff
'.man' => 'application/x-troff-man', // Troff with MAN macros
'.me' => 'application/x-troff-me', // Troff with ME macros
'.ms' => 'application/x-troff-ms', // Troff with MS macros
'.src' => 'application/x-wais-source', // WAIS source
'.bcpio' => 'application/x-bcpio', // Old binary CPIO
'.cpio' => 'application/x-cpio', // POSIX CPIO
'.gtar' => 'application/x-gtar', // GNU tar
'.shar' => 'application/x-shar', // Shell archive
'.sv4cpio' => 'application/x-sv4cpio', // SVR4 CPIO
'.sv4crc' => 'application/x-sv4crc', // SVR4 CPIO with CRC
'.tar' => 'application/x-tar', // 4.3BSD tar format
'.ustar' => 'application/x-ustar', // POSIX tar format
'.hlp' => 'application/x-winhelp', // Windows Help
'.zip' => 'application/zip', // ZIP archive
 
'.au' => 'audio/basic', // Basic audio (usually m-law)
'.snd' => 'audio/basic', // Basic audio (usually m-law)
'.aif' => 'audio/x-aiff', // AIFF audio
'.aiff' => 'audio/x-aiff', // AIFF audio
'.aifc' => 'audio/x-aiff', // AIFF audio
'.ra' => 'audio/x-pn-realaudio', // RealAudio
'.ram' => 'audio/x-pn-realaudio', // RealAudio
'.rpm' => 'audio/x-pn-realaudio-plugin', // RealAudio (plug-in)
'.wav' => 'audio/x-wav', // Windows WAVE audio
'.mp3' => 'audio/x-mp3', // MP3 files
 
'.gif' => 'image/gif', // gif image
'.ief' => 'image/ief', // Image Exchange Format
'.jpg' => 'image/jpeg', // JPEG image
'.jpe' => 'image/jpeg', // JPEG image
'.jpeg' => 'image/jpeg', // JPEG image
'.pict' => 'image/pict', // Macintosh PICT
'.png' => 'image/png', // PNG image
'.svg' => 'image/svg+xml', // Scalable vector graphics
'.tiff' => 'image/tiff', // TIFF image
'.tif' => 'image/tiff', // TIFF image
'.ras' => 'image/x-cmu-raster', // CMU raster
'.pnm' => 'image/x-portable-anymap', // PBM Anymap format
'.pbm' => 'image/x-portable-bitmap', // PBM Bitmap format
'.pgm' => 'image/x-portable-graymap', // PBM Graymap format
'.ppm' => 'image/x-portable-pixmap', // PBM Pixmap format
'.rgb' => 'image/x-rgb', // RGB Image
'.xbm' => 'image/x-xbitmap', // X Bitmap
'.xpm' => 'image/x-xpixmap', // X Pixmap
'.xwd' => 'image/x-xwindowdump', // X Windows dump (xwd) format
 
'.mpeg' => 'video/mpeg', // MPEG video
'.mpg' => 'video/mpeg', // MPEG video
'.mpe' => 'video/mpeg', // MPEG video
'.mpeg' => 'video/mpeg', // MPEG video
'.qt' => 'video/quicktime', // QuickTime Video
'.mov' => 'video/quicktime', // QuickTime Video
'.avi' => 'video/msvideo', // Microsoft Windows Video
'.movie' => 'video/x-sgi-movie', // SGI Movieplayer format
'.wrl' => 'x-world/x-vrml', // VRML Worlds
 
'.ods' => 'application/vnd.oasis.opendocument.spreadsheet', // OpenDocument Spreadsheet
'.ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', // OpenDocument Spreadsheet Template
'.odp' => 'application/vnd.oasis.opendocument.presentation', // OpenDocument Presentation
'.otp' => 'application/vnd.oasis.opendocument.presentation-template', // OpenDocument Presentation Template
'.odg' => 'application/vnd.oasis.opendocument.graphics', // OpenDocument Drawing
'.otg' => 'application/vnd.oasis.opendocument.graphics-template', // OpenDocument Drawing Template
'.odc' => 'application/vnd.oasis.opendocument.chart', // OpenDocument Chart
'.otc' => 'application/vnd.oasis.opendocument.chart-template', // OpenDocument Chart Template
'.odf' => 'application/vnd.oasis.opendocument.formula', // OpenDocument Formula
'.otf' => 'application/vnd.oasis.opendocument.formula-template', // OpenDocument Formula Template
'.odi' => 'application/vnd.oasis.opendocument.image', // OpenDocument Image
'.oti' => 'application/vnd.oasis.opendocument.image-template', // OpenDocument Image Template
'.odb' => 'application/vnd.oasis.opendocument.database', // OpenDocument Database
'.odt' => 'application/vnd.oasis.opendocument.text', // OpenDocument Text
'.ott' => 'application/vnd.oasis.opendocument.text-template', // OpenDocument Text Template
'.odm' => 'application/vnd.oasis.opendocument.text-master', // OpenDocument Master Document
'.oth' => 'application/vnd.oasis.opendocument.text-web', // OpenDocument HTML Template
);
 
// }}}
 
// {{{ Enscript file extensions
 
// List of extensions recognised by enscript.
 
$extEnscript = array(
'.ada' => 'ada',
'.adb' => 'ada',
'.ads' => 'ada',
'.awk' => 'awk',
'.c' => 'c',
'.c++' => 'cpp',
'.cc' => 'cpp',
'.cmake' => 'cmake',
'CMakeLists.txt' => 'cmake',
'.cpp' => 'cpp',
'.csh' => 'csh',
'.cxx' => 'cpp',
'.diff' => 'diffu',
'.dpr' => 'delphi',
'.e' => 'eiffel',
'.el' => 'elisp',
'.eps' => 'postscript',
'.f' => 'fortran',
'.for' => 'fortran',
'.gs' => 'haskell',
'.h' => 'c',
'.hpp' => 'cpp',
'.hs' => 'haskell',
'.htm' => 'html',
'.html' => 'html',
'.idl' => 'idl',
'.java' => 'java',
'.js' => 'javascript',
'.json' => 'javascript',
'.lgs' => 'haskell',
'.lhs' => 'haskell',
'.m' => 'objc',
'.m4' => 'm4',
'.man' => 'nroff',
'.nr' => 'nroff',
'.p' => 'pascal',
'.pas' => 'delphi',
'.patch' => 'diffu',
'.pkg' => 'sql',
'.pl' => 'perl',
'.pm' => 'perl',
'.pp' => 'pascal',
'.ps' => 'postscript',
'.s' => 'asm',
'.scheme' => 'scheme',
'.scm' => 'scheme',
'.scr' => 'synopsys',
'.sh' => 'sh',
'.shtml' => 'html',
'.sql' => 'sql',
'.st' => 'states',
'.syn' => 'synopsys',
'.synth' => 'synopsys',
'.tcl' => 'tcl',
'.tex' => 'tex',
'.texi' => 'tex',
'.texinfo' => 'tex',
'.v' => 'verilog',
'.vba' => 'vba',
'.vh' => 'verilog',
'.vhd' => 'vhdl',
'.vhdl' => 'vhdl',
'.py' => 'python',
);
 
// }}}
 
// {{{ GeSHi file extensions
 
// List of extensions recognised by GeSHi.
 
$extGeshi = array(
'actionscript3' => array('as'),
'ada' => array('ada', 'adb', 'ads'),
'asm' => array('ash', 'asi', 'asm'),
'asp' => array('asp'),
'bash' => array('sh'),
'bibtex' => array('bib'),
'c' => array('c'),
'cfm' => array('cfm', 'cfml'),
'cmake' => array('cmake', 'CMakeLists.txt'),
'cobol' => array('cbl'),
'cpp' => array('cc', 'cpp', 'cxx', 'c++', 'h', 'hpp'),
'csharp' => array('cs'),
'css' => array('css'),
'd' => array('d'),
'delphi' => array('dpk', 'dpr', 'pas'),
'diff' => array('diff', 'patch'),
'dos' => array('bat', 'cmd'),
'eiffel' => array('e'),
'erlang' => array('erl'),
'email' => array('eml'),
'fortran' => array('f', 'for', 'f90'),
'gettext' => array('po', 'pot'),
'gml' => array('gml'),
'gnuplot' => array('plt'),
'groovy' => array('groovy'),
'haskell' => array('gs', 'hs', 'lgs', 'lhs'),
'html4strict' => array('html', 'htm'),
'idl' => array('idl'),
'ini' => array('desktop', 'ini'),
'java5' => array('java'),
'javascript' => array('js', 'json'),
'latex' => array('tex'),
'lisp' => array('lisp'),
'lua' => array('lua'),
'make' => array('make'),
'matlab' => array('m'),
'perl' => array('pl', 'pm'),
'php' => array('php', 'php3', 'php4', 'php5', 'phps', 'phtml'),
'povray' => array('pov'),
'properties' => array('properties'),
'providex' => array('pvc', 'pvx'),
'python' => array('py'),
'reg' => array('reg'),
'ruby' => array('rb'),
'scala' => array('scala'),
'scheme' => array('scm', 'scheme'),
'scilab' => array('sci'),
'smalltalk' => array('st'),
'sql' => array('sql'),
'tcl' => array('tcl'),
'vb' => array('bas'),
'vbnet' => array('vb'),
'vh' => array('v', 'verilog'),
'vhdl' => array('vhd', 'vhdl'),
'vim' => array('vim'),
'whitespace' => array('ws'),
'xml' => array('xml', 'xsl', 'xsd', 'xib', 'wsdl', 'svg', 'plist', 'jmx'),
'z80' => array('z80'),
);
 
// }}}
 
// Loads English localized strings by default (must go before config.php)
require 'languages/english.php';
 
// Support one WebSVN installation hosting multiple different SVNParentPaths, distinguished by their
// location. Per location, the web server needs to set some environment variable providing the path
// to the config to either exclusively or additionally include, implementing a simple layered config
// this way. That allows, e.g., changing paths to repos per location only and share everything else.
//
// The following implementation deals with multiple most likely problems in such an environment, like
// HTTP redirects influencing the name of the environment variable set and "preg_grep" indexing its
// results depending on the input, so optionally changing between requests.
//
// https://stackoverflow.com/q/3050444/696632
// https://bz.apache.org/bugzilla/show_bug.cgi?id=58739
$confSuccess = 0;
$envPathConf = preg_grep('/^(?:REDIRECT_)*WEBSVN_PATH_CONF$/', array_keys($_SERVER));
$envPathConf = array_values($envPathConf);
$envPathConf = array_key_exists(0, $envPathConf)
? $_SERVER[$envPathConf[0]]
: '';
 
// Get the user's personalised config (requires the locwebsvnhttp stuff above).
if (file_exists('include/config.php')) {
require_once 'include/config.php';
$confSuccess = 1;
}
if (!empty($envPathConf)) {
require_once $envPathConf;
$confSuccess = 1;
}
if (!$confSuccess) {
die('No config applied, either create "include/config.php" or use environment variable ' .
'"WEBSVN_PATH_CONF". The example file "include/distconfig.php" should be copied and ' .
'modified as needed.');
}
 
// Make sure that the input locale is set up correctly
putenv("LANG=".setlocale(LC_ALL, $config->getLocale()));
 
$vars['showageinsteadofdate'] = $config->showAgeInsteadOfDate();
 
// Initialize the version of SVN that is being used by WebSVN internally.
require_once 'include/svnlook.php';
$vars['svnversion'] = $config->getSubversionVersion();
 
// Initialize an array with all query parameters except language and template.
$queryParams = $_GET + $_POST;
unset($queryParams['language']);
unset($queryParams['template']);
$hidden = '';
foreach ($queryParams as $key => $value) {
if (is_array($value)) {
for ($i = 0; $i < count($value); $i++) {
$hidden .= '<input type="hidden" name="'.escape($key).'[]" value="'.escape($value[$i]).'"/>';
}
} else {
$hidden .= '<input type="hidden" name="'.escape($key).'" value="'.escape($value).'"/>';
}
}
 
// If the request specifies a language, store in a cookie. Otherwise, check for cookies specifying a
// particular language already.
$language = ''; // RFC 4646 language tag for representing the selected language.
if (!empty($_REQUEST['language'])) {
$language = $_REQUEST['language'];
setcookie('storedlang', $language, time() + (60 * 60 * 24 * 356 * 10));
setcookie('storedsesslang', $language);
} else if (isset($_COOKIE['storedlang'])) {
$language = $_COOKIE['storedlang'];
} else if (isset($_COOKIE['storedsesslang'])) {
$language = $_COOKIE['storedsesslang'];
}
 
// Load available languages (populates $languages array)
require 'languages/languages.php';
// Get the default language as defined by config.php
$defaultLanguage = $config->getDefaultLanguage();
if (!isset($languages[$defaultLanguage]))
$defaultLanguage = 'en';
// Determine which language to actually use
$language = getUserLanguage($languages, $defaultLanguage, $language);
$vars['language_code'] = $language;
// For languages other than English, load translated strings over existing ones.
if ($language != 'en')
require 'languages/'.$languages[$language][0].'.php';
// Generate the HTML form for selecting a different language
$vars['language_form'] = '<form method="get" action="" id="language">'.$hidden;
$vars['language_select'] = '<select name="language" onchange="javascript:this.form.submit();">';
foreach ($languages as $code => $names) {
$sel = ($code == $language) ? '" selected="selected' : '';
$vars['language_select'] .= '<option value="'.$code.$sel.'">'.$names[2].' &ndash; '.$names[1].'</option>';
}
$vars['language_select'] .= '</select>';
$vars['language_submit'] = '<noscript><input type="submit" value="'.$lang['GO'].'" /></noscript>';
$vars['language_endform'] = '</form>';
 
// Load repository if possible
if ($config->multiViews) {
$rep = null; // MultiViews has custom code to load a repository
} else {
// Load repository matching 'repname' parameter (if set) or the default.
$repname = @$_REQUEST['repname'];
if (isset($repname)) {
$rep = $config->findRepository($repname);
} else {
$reps = $config->getRepositories();
$rep = (isset($reps[0]) ? $reps[0] : null);
}
// Make sure that the user has set up a repository
if ($rep == null) {
$vars['error'] = $lang['SUPPLYREP'];
} else if (is_string($rep)) {
$vars['error'] = $rep;
$rep = null;
} else {
$vars['repurl'] = $config->getURL($rep, '', 'dir');
$vars['clientrooturl'] = $rep->clientRootURL;
$vars['repname'] = escape($rep->getDisplayName());
$vars['allowdownload'] = $rep->getAllowDownload();
}
}
 
// If the request specifies a template, store in a cookie. Otherwise, check for cookies specifying a
// particular template already.
$template = '';
if (!empty($_REQUEST['template'])) {
$template = $_REQUEST['template'];
setcookie('storedtemplate', $template, time() + (60 * 60 * 24 * 365 * 10));
setcookie('storedsesstemplate', $template);
} else if (isset($_COOKIE['storedtemplate'])) {
$template = $_COOKIE['storedtemplate'];
} else if (isset($_COOKIE['storedsesstemplate'])) {
$template = $_COOKIE['storedsesstemplate'];
}
 
$templates = array();
// Skip creating template list when selected repository has specific template.
if ($rep == null || $rep->templatePath === false) {
// Get all templates defined in config.php; use last path component as name.
foreach ($config->templatePaths as $path) {
$templates[$path] = basename($path);
}
$selectedTemplatePath = $config->getTemplatePath();
if ($template != '' && in_array($template, $templates)) {
$selectedTemplatePath = array_search($template, $templates);
$config->userTemplate = $selectedTemplatePath;
}
}
 
// Generate the HTML form for selecting a different template
if (count($templates) > 1) {
$vars['template_form'] = '<form method="get" action="" id="template">'.$hidden;
$vars['template_select'] = '<select name="template" onchange="javascript:this.form.submit();">';
natcasesort($templates);
foreach ($templates as $path => $name) {
$sel = ($path == $selectedTemplatePath) ? ' selected="selected"' : '';
$vars['template_select'] .= '<option value="'.$name.'"'.$sel.'>'.$name.'</option>';
}
$vars['template_select'] .= '</select>';
$vars['template_submit'] = '<noscript><input type="submit" value="'.$lang['GO'].'" /></noscript>';
$vars['template_endform'] = '</form>';
} else {
$vars['template_form'] = '';
$vars['template_select'] = '';
$vars['template_submit'] = '';
$vars['template_endform'] = '';
}
 
$vars['indexurl'] = $config->getURL('', '', 'index');
$vars['validationurl'] = getFullURL($_SERVER['SCRIPT_NAME']).'?'.buildQuery($queryParams + array('template' => $template, 'language' => $language), '%26');
 
$path = !empty($_REQUEST['path']) ? $_REQUEST['path'] : null;
if ($path === null || $path === '')
$path = '/';
$vars['path'] = str_replace('%2F', '/', rawurlencode($path));
$vars['safepath'] = escape($path);
// Set operative and peg revisions (if specified) and save passed-in revision
$rev = (int)@$_REQUEST['rev'];
$peg = (int)@$_REQUEST['peg'];
$search = (string)@$_REQUEST['search'];
if ($peg === 0)
$peg = '';
$passrev = $rev;
 
if (!$config->multiViews) {
// With MultiViews, browse creates the form once the current project is found.
createProjectSelectionForm();
createRevisionSelectionForm();
createSearchSelectionForm();
}
 
// set flag if robots should be blocked
$vars['blockrobots'] = $config->areRobotsBlocked();
 
$listing = array();
 
// Set up response headers
header('Content-Type: text/html; charset=UTF-8');
header('Content-Language: '.$language);
 
// Function to create the project selection HTML form
function createProjectSelectionForm() {
global $config, $vars, $rep, $lang;
 
$vars['projects_form'] = '';
$vars['projects_select'] = '';
$vars['projects_submit'] = '';
$vars['projects_endform'] = '';
 
if (!$config->showRepositorySelectionForm() || count($config->getRepositories()) < 2)
return;
 
if ($rep) {
$currentRepoName = $rep->getDisplayName();
$options = '';
} else {
$currentRepoName = '';
$options = '<option value="" selected="selected"></option>';
}
foreach ($config->getRepositories() as $repository) {
if ($repository->hasReadAccess('/')) {
$repoName = $repository->getDisplayName();
$sel = ($repoName == $currentRepoName) ? ' selected="selected"' : '';
$options .= '<option value="'.escape($repoName).'"'.$sel.'>'.escape($repoName).'</option>';
}
}
if (strlen($options) === 0)
return;
 
$vars['projects_form'] = '<form method="get" action="" id="project">';
if ($config->multiViews)
$vars['projects_form'] .= '<input type="hidden" name="op" value="rep" />';
$vars['projects_select'] = '<select name="repname" onchange="javascript:this.form.submit();">'.$options.'</select>';
$vars['projects_submit'] = '<noscript><input type="submit" value="'.$lang['GO'].'" /></noscript>';
$vars['projects_endform'] = '</form>';
}
 
// Function to create the revision selection HTML form
function createRevisionSelectionForm() {
global $config, $lang, $vars, $rep, $path, $rev, $peg;
 
if ($rep == null)
return;
 
$params = array();
if (!$config->multiViews) {
$params['repname'] = $rep->getDisplayName();
if ($path === null)
$path = !empty($_REQUEST['path']) ? $_REQUEST['path'] : null;
if ($path && $path != '/')
$params['path'] = $path;
}
if ($peg || $rev)
$params['peg'] = ($peg ? $peg : $rev);
$hidden = '';
foreach ($params as $key => $value) {
$hidden .= '<input type="hidden" name="'.$key.'" value="'.escape($value).'" />';
}
// The blank "action" attribute makes form link back to the containing page.
$vars['revision_form'] = '<form method="get" action="" id="revision">'.$hidden;
if ($rev === null)
$rev = (int)@$_REQUEST['rev'];
$vars['revision_input'] = '<input type="text" size="5" name="rev" placeholder="'.($rev ? $rev : 'HEAD').'" />';
$vars['revision_submit'] = '<input type="submit" value="'.$lang['GO'].'" />';
$vars['revision_endform'] = '</form>';
}
 
function createSearchSelectionForm() {
global $config, $lang, $vars, $rep, $path, $rev, $peg, $search;
if ($rep === null)
return;
$params = array();
if (!$config->multiViews) {
$params['repname'] = $rep->getDisplayName();
if ($path === null)
$path = !empty($_REQUEST['path']) ? $_REQUEST['path'] : null;
if ($path && $path != '/')
$params['path'] = $path;
}
if ($peg || $rev)
$params['rev'] = ($peg ? $peg : $rev);
$hidden = '';
foreach ($params as $key => $value) {
$hidden .= '<input type="hidden" name="'.$key.'" value="'.escape($value).'" />';
}
$vars['search'] = true;
$vars['search_form'] = '<form method="get" action="'.$config->getURL($rep, '', 'search').'" id="search">'.$hidden;
$search = $search? $search : $lang['SEARCH_PLACEHOLDER'];
$vars['search_input'] = '<input type="text" size="20" name="search" placeholder="'.$search.'" />';
$vars['search_submit'] = '<input type="submit" value="'.$lang['SEARCH'].'" />';
$vars['search_endform'] = '</form>';
}
function sendHeaderForbidden() {
http_response_code(403);
}
/WebSVN/include/svnlook.php
0,0 → 1,1270
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// svn-look.php
//
// Svn bindings
//
// These binding currently use the svn command line to achieve their goal. Once a proper
// SWIG binding has been produced for PHP, there'll be an option to use that instead.
 
require_once 'include/utils.php';
 
// {{{ Classes for retaining log information ---
 
$debugxml = false;
 
class SVNInfoEntry {
var $rev = 1;
var $path = '';
var $isdir = null;
}
 
class SVNMod {
var $action = '';
var $copyfrom = '';
var $copyrev = '';
var $path = '';
var $isdir = null;
}
 
class SVNListEntry {
var $rev = 1;
var $author = '';
var $date = '';
var $committime;
var $age = '';
var $file = '';
var $isdir = null;
}
 
class SVNList {
var $entries; // Array of entries
var $curEntry; // Current entry
 
var $path = ''; // The path of the list
}
 
class SVNLogEntry {
var $rev = 1;
var $author = '';
var $date = '';
var $committime;
var $age = '';
var $msg = '';
var $path = '';
var $precisePath = '';
 
var $mods;
var $curMod;
}
 
function SVNLogEntry_compare($a, $b) {
return strnatcasecmp($a->path, $b->path);
}
 
class SVNLog {
var $entries; // Array of entries
var $curEntry; // Current entry
 
var $path = ''; // Temporary variable used to trace path history
 
// findEntry
//
// Return the entry for a given revision
 
function findEntry($rev) {
foreach ($this->entries as $index => $entry) {
if ($entry->rev == $rev) {
return $index;
}
}
}
}
 
// }}}
 
// {{{ XML parsing functions---
 
$curTag = '';
 
$curInfo = 0;
 
// {{{ infoStartElement
 
function infoStartElement($parser, $name, $attrs) {
global $curInfo, $curTag, $debugxml;
 
switch ($name) {
case 'INFO':
if ($debugxml) print 'Starting info'."\n";
break;
 
case 'ENTRY':
if ($debugxml) print 'Creating info entry'."\n";
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'KIND':
if ($debugxml) print 'Kind '.$v."\n";
$curInfo->isdir = ($v == 'dir');
break;
case 'REVISION':
if ($debugxml) print 'Revision '.$v."\n";
$curInfo->rev = $v;
break;
}
}
}
break;
 
default:
$curTag = $name;
break;
}
}
 
// }}}
 
// {{{ infoEndElement
 
function infoEndElement($parser, $name) {
global $curInfo, $debugxml, $curTag;
 
switch ($name) {
case 'ENTRY':
if ($debugxml) print 'Ending info entry'."\n";
if ($curInfo->isdir) {
$curInfo->path .= '/';
}
break;
}
 
$curTag = '';
}
 
// }}}
 
// {{{ infoCharacterData
 
function infoCharacterData($parser, $data) {
global $curInfo, $curTag, $debugxml;
 
switch ($curTag) {
case 'URL':
if ($debugxml) print 'URL: '.$data."\n";
$curInfo->path = $data;
break;
 
case 'ROOT':
if ($debugxml) print 'Root: '.$data."\n";
$curInfo->path = urldecode(substr($curInfo->path, strlen($data)));
break;
}
}
 
// }}}
 
$curList = 0;
 
// {{{ listStartElement
 
function listStartElement($parser, $name, $attrs) {
global $curList, $curTag, $debugxml;
 
switch ($name) {
case 'LIST':
if ($debugxml) print 'Starting list'."\n";
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'PATH':
if ($debugxml) print 'Path '.$v."\n";
$curList->path = $v;
break;
}
}
}
break;
 
case 'ENTRY':
if ($debugxml) print 'Creating new entry'."\n";
$curList->curEntry = new SVNListEntry;
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'KIND':
if ($debugxml) print 'Kind '.$v."\n";
$curList->curEntry->isdir = ($v == 'dir');
break;
}
}
}
break;
 
case 'COMMIT':
if ($debugxml) print 'Commit'."\n";
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'REVISION':
if ($debugxml) print 'Revision '.$v."\n";
$curList->curEntry->rev = $v;
break;
}
}
}
break;
 
default:
$curTag = $name;
break;
}
}
 
// }}}
 
// {{{ listEndElement
 
function listEndElement($parser, $name) {
global $curList, $debugxml, $curTag;
 
switch ($name) {
case 'ENTRY':
if ($debugxml) print 'Ending new list entry'."\n";
if ($curList->curEntry->isdir) {
$curList->curEntry->file .= '/';
}
$curList->entries[] = $curList->curEntry;
$curList->curEntry = null;
break;
}
 
$curTag = '';
}
 
// }}}
 
// {{{ listCharacterData
 
function listCharacterData($parser, $data) {
global $curList, $curTag, $debugxml;
 
switch ($curTag) {
case 'NAME':
if ($debugxml) print 'Name: '.$data."\n";
if ($data === false || $data === '') return;
$curList->curEntry->file .= $data;
break;
 
case 'AUTHOR':
if ($debugxml) print 'Author: '.$data."\n";
if ($data === false || $data === '') return;
if (function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding'))
$data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
$curList->curEntry->author .= $data;
break;
 
case 'DATE':
if ($debugxml) print 'Date: '.$data."\n";
if ($data === false || $data === '') return;
$committime = parseSvnTimestamp($data);
$curList->curEntry->committime = $committime;
$curList->curEntry->date = date('Y-m-d H:i:s', $committime);
$curList->curEntry->age = datetimeFormatDuration(max(time() - $committime, 0), true, true);
break;
}
}
 
// }}}
 
$curLog = 0;
 
// {{{ logStartElement
 
function logStartElement($parser, $name, $attrs) {
global $curLog, $curTag, $debugxml;
 
switch ($name) {
case 'LOGENTRY':
if ($debugxml) print 'Creating new log entry'."\n";
$curLog->curEntry = new SVNLogEntry;
$curLog->curEntry->mods = array();
 
$curLog->curEntry->path = $curLog->path;
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'REVISION':
if ($debugxml) print 'Revision '.$v."\n";
$curLog->curEntry->rev = $v;
break;
}
}
}
break;
 
case 'PATH':
if ($debugxml) print 'Creating new path'."\n";
$curLog->curEntry->curMod = new SVNMod;
 
if (count($attrs)) {
foreach ($attrs as $k => $v) {
switch ($k) {
case 'ACTION':
if ($debugxml) print 'Action '.$v."\n";
$curLog->curEntry->curMod->action = $v;
break;
 
case 'COPYFROM-PATH':
if ($debugxml) print 'Copy from: '.$v."\n";
$curLog->curEntry->curMod->copyfrom = $v;
break;
 
case 'COPYFROM-REV':
$curLog->curEntry->curMod->copyrev = $v;
break;
 
case 'KIND':
if ($debugxml) print 'Kind '.$v."\n";
$curLog->curEntry->curMod->isdir = ($v == 'dir');
break;
}
}
}
 
$curTag = $name;
break;
 
default:
$curTag = $name;
break;
}
}
 
// }}}
 
// {{{ logEndElement
 
function logEndElement($parser, $name) {
global $curLog, $debugxml, $curTag;
 
switch ($name) {
case 'LOGENTRY':
if ($debugxml) print 'Ending new log entry'."\n";
$curLog->entries[] = $curLog->curEntry;
break;
 
case 'PATH':
// The XML returned when a file is renamed/branched in inconsistent.
// In the case of a branch, the path doesn't include the leafname.
// In the case of a rename, it does. Ludicrous.
 
if (!empty($curLog->path)) {
$pos = strrpos($curLog->path, '/');
$curpath = substr($curLog->path, 0, $pos);
$leafname = substr($curLog->path, $pos + 1);
} else {
$curpath = '';
$leafname = '';
}
 
$curMod = $curLog->curEntry->curMod;
if ($curMod->action == 'A') {
if ($debugxml) print 'Examining added path "'.$curMod->copyfrom.'" - Current path = "'.$curpath.'", leafname = "'.$leafname.'"'."\n";
if ($curMod->path == $curLog->path) {
// For directories and renames
$curLog->path = $curMod->copyfrom;
} else if ($curMod->path == $curpath || $curMod->path == $curpath.'/') {
// Logs of files that have moved due to branching
$curLog->path = $curMod->copyfrom.'/'.$leafname;
} else {
$curLog->path = str_replace($curMod->path, $curMod->copyfrom, $curLog->path);
}
if ($debugxml) print 'New path for comparison: "'.$curLog->path.'"'."\n";
}
 
if ($debugxml) print 'Ending path'."\n";
$curLog->curEntry->mods[] = $curLog->curEntry->curMod;
break;
 
case 'MSG':
$curLog->curEntry->msg = trim($curLog->curEntry->msg);
if ($debugxml) print 'Completed msg = "'.$curLog->curEntry->msg.'"'."\n";
break;
}
 
$curTag = '';
}
 
// }}}
 
// {{{ logCharacterData
 
function logCharacterData($parser, $data) {
global $curLog, $curTag, $debugxml;
 
switch ($curTag) {
case 'AUTHOR':
if ($debugxml) print 'Author: '.$data."\n";
if ($data === false || $data === '') return;
if (function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding'))
$data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
$curLog->curEntry->author .= $data;
break;
 
case 'DATE':
if ($debugxml) print 'Date: '.$data."\n";
if ($data === false || $data === '') return;
$committime = parseSvnTimestamp($data);
$curLog->curEntry->committime = $committime;
$curLog->curEntry->date = date('Y-m-d H:i:s', $committime);
$curLog->curEntry->age = datetimeFormatDuration(max(time() - $committime, 0), true, true);
break;
 
case 'MSG':
if ($debugxml) print 'Msg: '.$data."\n";
if (function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding'))
$data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
$curLog->curEntry->msg .= $data;
break;
 
case 'PATH':
if ($debugxml) print 'Path name: '.$data."\n";
if ($data === false || $data === '') return;
$curLog->curEntry->curMod->path .= $data;
break;
}
}
 
// }}}
 
// }}}
 
// {{{ internal functions (_topLevel and _listSort)
 
// Function returns true if the give entry in a directory tree is at the top level
 
function _topLevel($entry) {
// To be at top level, there must be one space before the entry
return (strlen($entry) > 1 && $entry[0] == ' ' && $entry[ 1 ] != ' ');
}
 
// Function to sort two given directory entries.
// Directories go at the top if config option alphabetic is not set
 
function _listSort($e1, $e2) {
global $config;
 
$file1 = $e1->file;
$file2 = $e2->file;
$isDir1 = ($file1[strlen($file1) - 1] == '/');
$isDir2 = ($file2[strlen($file2) - 1] == '/');
 
if (!$config->isAlphabeticOrder()) {
if ($isDir1 && !$isDir2) return -1;
if ($isDir2 && !$isDir1) return 1;
}
 
if ($isDir1) $file1 = substr($file1, 0, -1);
if ($isDir2) $file2 = substr($file2, 0, -1);
 
return strnatcasecmp($file1, $file2);
}
 
// }}}
 
// {{{ encodePath
 
// Function to encode a URL without encoding the /'s
 
function encodePath($uri) {
global $config;
 
$uri = str_replace(DIRECTORY_SEPARATOR, '/', $uri);
if (function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) {
$uri = mb_convert_encoding($uri, 'UTF-8', mb_detect_encoding($uri));
}
 
$parts = explode('/', $uri);
$partscount = count($parts);
for ($i = 0; $i < $partscount; $i++) {
// do not rawurlencode the 'svn+ssh://' part!
if ($i != 0 || $parts[$i] != 'svn+ssh:') {
$parts[$i] = rawurlencode($parts[$i]);
}
}
 
$uri = implode('/', $parts);
 
// Quick hack. Subversion seems to have a bug surrounding the use of %3A instead of :
 
$uri = str_replace('%3A', ':', $uri);
 
// Correct for Window share names
if ($config->serverIsWindows) {
if (substr($uri, 0, 2) == '//') {
$uri = '\\'.substr($uri, 2, strlen($uri));
}
 
if (substr($uri, 0, 10) == 'file://///' ) {
$uri = 'file:///\\'.substr($uri, 10, strlen($uri));
}
}
 
return $uri;
}
 
// }}}
 
function _equalPart($str1, $str2) {
$len1 = strlen($str1);
$len2 = strlen($str2);
$i = 0;
while ($i < $len1 && $i < $len2) {
if (strcmp($str1[$i], $str2[$i]) != 0) {
break;
}
$i++;
}
if ($i == 0) {
return '';
}
return substr($str1, 0, $i);
}
 
function _logError($string) {
$string = preg_replace("/--password '.*'/", "--password '[...]'", $string);
error_log($string);
}
 
// The SVNRepository class
 
class SVNRepository {
var $repConfig;
var $geshi = null;
 
function __construct($repConfig) {
$this->repConfig = $repConfig;
}
 
// {{{ highlightLine
//
// Distill line-spanning syntax highlighting so that each line can stand alone
// (when invoking on the first line, $attributes should be an empty array)
// Invoked to make sure all open syntax highlighting tags (<font>, <i>, <b>, etc.)
// are closed at the end of each line and re-opened on the next line
 
function highlightLine($line, &$attributes) {
$hline = '';
 
// Apply any highlighting in effect from the previous line
foreach ($attributes as $attr) {
$hline .= $attr['text'];
}
 
// append the new line
$hline .= $line;
 
// update attributes
for ($line = strstr($line, '<'); $line; $line = strstr(substr($line, 1), '<')) {
if (substr($line, 1, 1) == '/') {
// if this closes a tag, remove most recent corresponding opener
$tagNamLen = strcspn($line, '> '."\t", 2);
$tagNam = substr($line, 2, $tagNamLen);
foreach (array_reverse(array_keys($attributes)) as $k) {
if ($attributes[$k]['tag'] == $tagNam) {
unset($attributes[$k]);
break;
}
}
} else {
// if this opens a tag, add it to the list
$tagNamLen = strcspn($line, '> '."\t", 1);
$tagNam = substr($line, 1, $tagNamLen);
$tagLen = strcspn($line, '>') + 1;
$attributes[] = array('tag' => $tagNam, 'text' => substr($line, 0, $tagLen));
}
}
 
// close any still-open tags
foreach (array_reverse($attributes) as $attr) {
$hline .= '</'.$attr['tag'].'>';
}
 
// XXX: this just simply replaces [ and ] with their entities to prevent
// it from being parsed by the template parser; maybe something more
// elegant is in order?
$hline = str_replace('[', '&#91;', str_replace(']', '&#93;', $hline) );
return $hline;
}
 
// }}}
 
// Private function to simplify creation of common SVN command string text.
function svnCommandString($command, $path, $rev, $peg) {
global $config;
return $config->getSvnCommand().$this->repConfig->svnCredentials().' '.$command.' '.($rev ? '-r '.$rev.' ' : '').quote(encodePath($this->getSvnPath($path)).'@'.($peg ? $peg : ''));
}
 
// Private function to simplify creation of enscript command string text.
function enscriptCommandString($path) {
global $config, $extEnscript;
 
$filename = basename($path);
$ext = strrchr($path, '.');
 
$lang = false;
if (array_key_exists($filename, $extEnscript)) {
$lang = $extEnscript[$filename];
} else if ($ext && array_key_exists(strtolower($ext), $extEnscript)) {
$lang = $extEnscript[strtolower($ext)];
}
 
$cmd = $config->enscript.' --language=html';
if ($lang !== false) {
$cmd .= ' --color --'.(!$config->getUseEnscriptBefore_1_6_3() ? 'highlight' : 'pretty-print').'='.$lang;
}
$cmd .= ' -o -';
return $cmd;
}
 
// {{{ getFileContents
//
// Dump the content of a file to the given filename
 
function getFileContents($path, $filename, $rev = 0, $peg = '', $pipe = '', $highlight = 'file') {
global $config;
assert ($highlight == 'file' || $highlight == 'no' || $highlight == 'line');
 
$highlighted = false;
 
// If there's no filename, just deliver the contents as-is to the user
if ($filename == '') {
$cmd = $this->svnCommandString('cat', $path, $rev, $peg);
passthruCommand($cmd.' '.$pipe);
return $highlighted;
}
 
// Get the file contents info
 
$tempname = $filename;
if ($highlight == 'line') {
$tempname = tempnamWithCheck($config->getTempDir(), '');
}
$highlighted = true;
$shouldTrimOutput = false;
$explodeStr = "\n";
if ($highlight != 'no' && $config->useGeshi && $geshiLang = $this->highlightLanguageUsingGeshi($path)) {
$this->applyGeshi($path, $tempname, $geshiLang, $rev, $peg, false, $highlight);
// Geshi outputs in HTML format, enscript does not
$shouldTrimOutput = true;
$explodeStr = "<br />";
} else if ($highlight != 'no' && $config->useEnscript) {
// Get the files, feed it through enscript, then remove the enscript headers using sed
// Note that the sed command returns only the part of the file between <PRE> and </PRE>.
// It's complicated because it's designed not to return those lines themselves.
$cmd = $this->svnCommandString('cat', $path, $rev, $peg);
$cmd = $cmd.' | '.$this->enscriptCommandString($path).' | '.
$config->sed.' -n '.$config->quote.'1,/^<PRE.$/!{/^<\\/PRE.$/,/^<PRE.$/!p;}'.$config->quote.' > '.$tempname;
} else {
$highlighted = false;
$cmd = $this->svnCommandString('cat', $path, $rev, $peg);
$cmd = $cmd.' > '.quote($filename);
}
 
if (isset($cmd)) {
$error = '';
$output = runCommand($cmd, true, $error);
 
if (!empty($error)) {
global $lang;
_logError($lang['BADCMD'].': '.$cmd);
_logError($error);
 
global $vars;
$vars['warning'] = nl2br(escape(toOutputEncoding($error)));
}
}
 
if ($highlighted && $highlight == 'line') {
// If we need each line independently highlighted (e.g. for diff or blame)
// then we'll need to filter the output of the highlighter
// to make sure tags like <font>, <i> or <b> don't span lines
 
$dst = fopen($filename, 'w');
if ($dst) {
$content = file_get_contents($tempname);
$content = explode($explodeStr, $content);
 
// $attributes is used to remember what highlighting attributes
// are in effect from one line to the next
$attributes = array(); // start with no attributes in effect
 
foreach ($content as $line) {
if ($shouldTrimOutput) {
$line = trim($line);
}
fputs($dst, $this->highlightLine($line, $attributes)."\n");
}
fclose($dst);
}
}
if ($tempname != $filename) {
@unlink($tempname);
}
return $highlighted;
}
 
// }}}
 
// {{{ highlightLanguageUsingGeshi
//
// check if geshi can highlight the given extension and return the language
 
function highlightLanguageUsingGeshi($path) {
global $config;
global $extGeshi;
 
$filename = basename($path);
$ext = strrchr($path, '.');
if (substr($ext, 0, 1) == '.') $ext = substr($ext, 1);
 
foreach ($extGeshi as $language => $extensions) {
if (in_array($filename, $extensions) || in_array(strtolower($ext), $extensions)) {
if ($this->geshi === null) {
if (!defined('USE_AUTOLOADER')) {
require_once $config->getGeshiScript();
}
$this->geshi = new GeSHi();
}
$this->geshi->set_language($language);
if ($this->geshi->error() === false) {
return $language;
}
}
}
return '';
}
 
// }}}
 
// {{{ applyGeshi
//
// perform syntax highlighting using geshi
 
function applyGeshi($path, $filename, $language, $rev, $peg = '', $return = false, $highlight = 'file') {
global $config;
 
// Output the file to the filename
$error = '';
$cmd = $this->svnCommandString('cat', $path, $rev, $peg).' > '.quote($filename);
$output = runCommand($cmd, true, $error);
 
if (!empty($error)) {
global $lang;
_logError($lang['BADCMD'].': '.$cmd);
_logError($error);
 
global $vars;
$vars['warning'] = 'Unable to cat file: '.nl2br(escape(toOutputEncoding($error)));
return;
}
 
$source = file_get_contents($filename);
 
if ($this->geshi === null) {
if (!defined('USE_AUTOLOADER')) {
require_once $config->getGeshiScript();
}
$this->geshi = new GeSHi();
}
 
$this->geshi->set_source($source);
$this->geshi->set_language($language);
$this->geshi->set_header_type(GESHI_HEADER_NONE);
$this->geshi->set_overall_class('geshi');
$this->geshi->set_tab_width($this->repConfig->getExpandTabsBy());
 
if ($highlight == 'file') {
$this->geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
$this->geshi->set_overall_id('geshi');
$this->geshi->enable_ids(true);
}
 
if ($return) {
return $this->geshi->parse_code();
} else {
$f = @fopen($filename, 'w');
fwrite($f, $this->geshi->parse_code());
fclose($f);
}
}
 
// }}}
 
// {{{ listFileContents
//
// Print the contents of a file without filling up Apache's memory
 
function listFileContents($path, $rev = 0, $peg = '') {
global $config;
 
if ($config->useGeshi && $geshiLang = $this->highlightLanguageUsingGeshi($path)) {
$tempname = tempnamWithCheck($config->getTempDir(), 'websvn');
if ($tempname !== false) {
print toOutputEncoding($this->applyGeshi($path, $tempname, $geshiLang, $rev, $peg, true));
@unlink($tempname);
}
} else {
$pre = false;
$cmd = $this->svnCommandString('cat', $path, $rev, $peg);
if ($config->useEnscript) {
$cmd .= ' | '.$this->enscriptCommandString($path).' | '.
$config->sed.' -n '.$config->quote.'/^<PRE.$/,/^<\\/PRE.$/p'.$config->quote;
} else {
$pre = true;
}
 
if ($result = popenCommand($cmd, 'r')) {
if ($pre)
echo '<pre>';
while (!feof($result)) {
$line = fgets($result, 1024);
$line = toOutputEncoding($line);
if ($pre) {
$line = escape($line);
}
print hardspace($line);
}
if ($pre)
echo '</pre>';
pclose($result);
}
}
}
 
// }}}
 
// {{{ listReadmeContents
//
// Parse the README.md file
function listReadmeContents($path, $rev = 0, $peg = '') {
global $config;
 
$file = "README.md";
 
if ($this->isFile($path.$file) != True)
{
return;
}
 
if (!$config->getUseParsedown())
{
return;
}
 
// Autoloader handles most of the time
if (!defined('USE_AUTOLOADER')) {
require_once $config->getParsedownScript();
}
 
$mdParser = new Parsedown();
$cmd = $this->svnCommandString('cat', $path.$file, $rev, $peg);
 
if (!($result = popenCommand($cmd, 'r')))
{
return;
}
 
echo('<div id="wrap">');
while (!feof($result))
{
$line = fgets($result, 1024);
echo $mdParser->text($line);
}
echo('</div>');
pclose($result);
 
}
 
// }}}
 
// {{{ getBlameDetails
//
// Dump the blame content of a file to the given filename
 
function getBlameDetails($path, $filename, $rev = 0, $peg = '') {
$error = '';
$cmd = $this->svnCommandString('blame', $path, $rev, $peg).' > '.quote($filename);
$output = runCommand($cmd, true, $error);
 
if (!empty($error)) {
global $lang;
_logError($lang['BADCMD'].': '.$cmd);
_logError($error);
 
global $vars;
$vars['warning'] = 'No blame info: '.nl2br(escape(toOutputEncoding($error)));
}
}
 
// }}}
 
function getProperties($path, $rev = 0, $peg = '') {
$cmd = $this->svnCommandString('proplist', $path, $rev, $peg);
$ret = runCommand($cmd, true);
$properties = array();
if (is_array($ret)) {
foreach ($ret as $line) {
if (substr($line, 0, 1) == ' ') {
$properties[] = ltrim($line);
}
}
}
return $properties;
}
 
// {{{ getProperty
 
function getProperty($path, $property, $rev = 0, $peg = '') {
$cmd = $this->svnCommandString('propget '.$property, $path, $rev, $peg);
$ret = runCommand($cmd, true);
// Remove the surplus newline
if (count($ret)) {
unset($ret[count($ret) - 1]);
}
return implode("\n", $ret);
}
 
// }}}
 
// {{{ exportDirectory
//
// Exports the directory to the given location
 
function exportRepositoryPath($path, $filename, $rev = 0, $peg = '') {
$cmd = $this->svnCommandString('export', $path, $rev, $peg).' '.quote($filename.'@');
$retcode = 0;
execCommand($cmd, $retcode);
if ($retcode != 0) {
global $lang;
_logError($lang['BADCMD'].': '.$cmd);
}
return $retcode;
}
 
// }}}
 
// {{{ _xmlParseCmdOutput
 
function _xmlParseCmdOutput($cmd, $startElem, $endElem, $charData) {
$error = '';
$lines = runCommand($cmd, false, $error);
$linesCnt = count($lines);
$xml_parser = xml_parser_create('UTF-8');
 
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, $startElem, $endElem);
xml_set_character_data_handler($xml_parser, $charData);
 
for ($i = 0; $i < $linesCnt; ++$i) {
$line = $lines[$i] . "\n";
$isLast = $i == ($linesCnt - 1);
 
if (xml_parse($xml_parser, $line, $isLast)) {
continue;
}
 
$errorMsg = sprintf('XML error: %s (%d) at line %d column %d byte %d'."\n".'cmd: %s',
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_error_code($xml_parser),
xml_get_current_line_number($xml_parser),
xml_get_current_column_number($xml_parser),
xml_get_current_byte_index($xml_parser),
$cmd);
 
if (xml_get_error_code($xml_parser) == 5) {
break;
}
 
// errors can contain sensitive info! don't echo this ~J
_logError($errorMsg);
exit;
}
 
xml_parser_free($xml_parser);
if (empty($error)) {
return;
}
 
$error = toOutputEncoding(nl2br(str_replace('svn: ', '', $error)));
global $lang;
_logError($lang['BADCMD'].': '.$cmd);
_logError($error);
 
global $vars;
if (strstr($error, 'found format')) {
$vars['error'] = 'Repository uses a newer format than Subversion '.$config->getSubversionVersion().' can read. ("'.nl2br(escape(toOutputEncoding(substr($error, strrpos($error, 'Expected'))))).'.")';
} else if (strstr($error, 'No such revision')) {
$vars['warning'] = 'Revision '.$rev.' of this resource does not exist.';
} else {
$vars['error'] = $lang['BADCMD'].': <code>'.escape(stripCredentialsFromCommand($cmd)).'</code><br />'.nl2br(escape(toOutputEncoding($error)));
}
}
 
// }}}
 
// {{{ getInfo
 
function getInfo($path, $rev = 0, $peg = '') {
global $config, $curInfo;
 
// Since directories returned by svn log don't have trailing slashes (:-(), we need to remove
// the trailing slash from the path for comparison purposes
 
if ($path[strlen($path) - 1] == '/' && $path != '/') {
$path = substr($path, 0, -1);
}
 
$curInfo = new SVNInfoEntry;
 
// Get the svn info
 
if ($rev == 0) {
$headlog = $this->getLog('/', '', '', true, 1);
if ($headlog && isset($headlog->entries[0]))
$rev = $headlog->entries[0]->rev;
}
 
$cmd = $this->svnCommandString('info --xml', $path, $rev, $peg);
$this->_xmlParseCmdOutput($cmd, 'infoStartElement', 'infoEndElement', 'infoCharacterData');
 
if ($this->repConfig->subpath !== null) {
if (substr($curInfo->path, 0, strlen($this->repConfig->subpath) + 1) === '/'. $this->repConfig->subpath) {
$curInfo->path = substr($curInfo->path, strlen($this->repConfig->subpath) + 1);
} else {
// hide entry when file is outside of subpath
return null;
}
}
 
return $curInfo;
}
 
// }}}
 
// {{{ getList
 
function getList($path, $rev = 0, $peg = '') {
global $config, $curList;
 
// Since directories returned by svn log don't have trailing slashes (:-(), we need to remove
// the trailing slash from the path for comparison purposes
 
if ($path[strlen($path) - 1] == '/' && $path != '/') {
$path = substr($path, 0, -1);
}
 
$curList = new SVNList;
$curList->entries = array();
$curList->path = $path;
 
// Get the list info
 
if ($rev == 0) {
$headlog = $this->getLog('/', '', '', true, 1);
if ($headlog && isset($headlog->entries[0]))
$rev = $headlog->entries[0]->rev;
}
 
if ($config->showLoadAllRepos()) {
$cmd = $this->svnCommandString('list -R --xml', $path, $rev, $peg);
$this->_xmlParseCmdOutput($cmd, 'listStartElement', 'listEndElement', 'listCharacterData');
}
else {
$cmd = $this->svnCommandString('list --xml', $path, $rev, $peg);
$this->_xmlParseCmdOutput($cmd, 'listStartElement', 'listEndElement', 'listCharacterData');
usort($curList->entries, '_listSort');
}
 
return $curList;
}
 
// }}}
 
// {{{ getListSearch
 
function getListSearch($path, $term = '', $rev = 0, $peg = '') {
global $config, $curList;
 
// Since directories returned by "svn log" don't have trailing slashes (:-(), we need to
// remove the trailing slash from the path for comparison purposes.
if (($path[strlen($path) - 1] == '/') && ($path != '/')) {
$path = substr($path, 0, -1);
}
 
$curList = new SVNList;
$curList->entries = array();
$curList->path = $path;
 
// Get the list info
 
if ($rev == 0) {
$headlog = $this->getLog('/', '', '', true, 1);
if ($headlog && isset($headlog->entries[0]))
$rev = $headlog->entries[0]->rev;
}
 
$term = escapeshellarg($term);
$cmd = 'list -R --search ' . $term . ' --xml';
$cmd = $this->svnCommandString($cmd, $path, $rev, $peg);
$this->_xmlParseCmdOutput($cmd, 'listStartElement', 'listEndElement', 'listCharacterData');
 
return $curList;
}
 
// }}}
 
 
// {{{ getLog
 
function getLog($path, $brev = '', $erev = 1, $quiet = false, $limit = 2, $peg = '', $verbose = false) {
global $config, $curLog;
 
// Since directories returned by svn log don't have trailing slashes (:-(),
// we must remove the trailing slash from the path for comparison purposes.
if (!empty($path) && $path != '/' && $path[strlen($path) - 1] == '/') {
$path = substr($path, 0, -1);
}
 
$curLog = new SVNLog;
$curLog->entries = array();
$curLog->path = $path;
 
// Get the log info
$effectiveRev = ($brev && $erev ? $brev.':'.$erev : ($brev ? $brev.':1' : ''));
$effectivePeg = ($peg ? $peg : ($brev ? $brev : ''));
$cmd = $this->svnCommandString('log --xml '.($verbose ? '--verbose' : ($quiet ? '--quiet' : '')).($limit != 0 ? ' --limit '.$limit : ''), $path, $effectiveRev, $effectivePeg);
 
$this->_xmlParseCmdOutput($cmd, 'logStartElement', 'logEndElement', 'logCharacterData');
 
foreach ($curLog->entries as $entryKey => $entry) {
$fullModAccess = true;
$anyModAccess = (count($entry->mods) == 0);
$precisePath = null;
foreach ($entry->mods as $modKey => $mod) {
$access = $this->repConfig->hasLogReadAccess($mod->path);
if ($access) {
$anyModAccess = true;
 
// find path which is parent of all modification but more precise than $curLogEntry->path
$modpath = $mod->path;
if (!$mod->isdir || $mod->action == 'D') {
$pos = strrpos($modpath, '/');
$modpath = substr($modpath, 0, $pos + 1);
}
if (strlen($modpath) == 0 || substr($modpath, -1) !== '/') {
$modpath .= '/';
}
//compare with current precise path
if ($precisePath === null) {
$precisePath = $modpath;
} else {
$equalPart = _equalPart($precisePath, $modpath);
if (substr($equalPart, -1) !== '/') {
$pos = strrpos($equalPart, '/');
$equalPart = substr($equalPart, 0, $pos + 1);
}
$precisePath = $equalPart;
}
 
// fix paths if command was for a subpath repository
if ($this->repConfig->subpath !== null) {
if (substr($mod->path, 0, strlen($this->repConfig->subpath) + 1) === '/'. $this->repConfig->subpath) {
$curLog->entries[$entryKey]->mods[$modKey]->path = substr($mod->path, strlen($this->repConfig->subpath) + 1);
} else {
// hide modified entry when file is outside of subpath
unset($curLog->entries[$entryKey]->mods[$modKey]);
}
}
} else {
// hide modified entry when access is prohibited
unset($curLog->entries[$entryKey]->mods[$modKey]);
$fullModAccess = false;
}
}
if (!$fullModAccess) {
// hide commit message when access to any of the entries is prohibited
$curLog->entries[$entryKey]->msg = '';
}
if (!$anyModAccess) {
// hide author and date when access to all of the entries is prohibited
$curLog->entries[$entryKey]->author = '';
$curLog->entries[$entryKey]->date = '';
$curLog->entries[$entryKey]->committime = '';
$curLog->entries[$entryKey]->age = '';
}
 
if ($precisePath !== null) {
$curLog->entries[$entryKey]->precisePath = $precisePath;
} else {
$curLog->entries[$entryKey]->precisePath = $curLog->entries[$entryKey]->path;
}
}
return $curLog;
}
 
// }}}
 
function isFile($path, $rev = 0, $peg = '') {
$cmd = $this->svnCommandString('info --xml', $path, $rev, $peg);
return strpos(implode(' ', runCommand($cmd, true)), 'kind="file"') !== false;
}
 
// {{{ getSvnPath
 
function getSvnPath($path) {
if ($this->repConfig->subpath === null) {
return $this->repConfig->path.$path;
} else {
return $this->repConfig->path.'/'.$this->repConfig->subpath.$path;
}
}
 
// }}}
 
}
 
// Initialize SVN version information by parsing from command-line output.
$cmd = $config->getSvnCommand();
$cmd = str_replace(array('--non-interactive', '--trust-server-cert'), array('', ''), $cmd);
$cmd .= ' --version -q';
$ret = runCommand($cmd, false);
if (preg_match('~([0-9]+)\.([0-9]+)\.([0-9]+)~', $ret[0], $matches)) {
$config->setSubversionVersion($matches[0]);
$config->setSubversionMajorVersion($matches[1]);
$config->setSubversionMinorVersion($matches[2]);
}
/WebSVN/include/template.php
0,0 → 1,321
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// templates.php
//
// Templating system to allow advanced page customisation
 
$vars['version'] = $version; // Set WebSVN version for all template files
$vars['currentyear'] = date('Y');
 
$ignore = false;
 
// Stack of previous test results
$ignorestack = array();
 
// Number of test levels currently ignored
$ignorelevel = 0;
 
// parseCommand
//
// Parse a special command
 
function parseCommand($line, $vars, $handle) {
global $ignore, $ignorestack, $ignorelevel, $config, $listing, $vars;
 
// process content of included file
if (strncmp(trim($line), '[websvn-include:', 16) == 0) {
if (!$ignore) {
$line = trim($line);
$file = substr($line, 16, -1);
parseTemplate($file);
}
return true;
}
 
 
// Check for test conditions
if (strncmp(trim($line), '[websvn-test:', 13) == 0) {
if (!$ignore) {
$line = trim($line);
$var = substr($line, 13, -1);
$neg = ($var[0] == '!');
if ($neg) $var = substr($var, 1);
if (empty($vars[$var]) ^ $neg) {
array_push($ignorestack, $ignore);
$ignore = true;
}
} else {
$ignorelevel++;
}
return true;
}
 
if (strncmp(trim($line), '[websvn-else]', 13) == 0) {
if ($ignorelevel == 0) {
$ignore = !$ignore;
}
return true;
}
 
if (strncmp(trim($line), '[websvn-endtest]', 16) == 0) {
if ($ignorelevel > 0) {
$ignorelevel--;
} else {
$ignore = array_pop($ignorestack);
}
return true;
}
 
if (strncmp(trim($line), '[websvn-getlisting]', 19) == 0) {
global $svnrep, $path, $rev, $peg;
 
if (!$ignore) {
$svnrep->listFileContents($path, $rev, $peg);
}
return true;
}
 
if (strncmp(trim($line), '[websvn-defineicons]', 19) == 0) {
global $icons;
 
if (!isset($icons)) {
$icons = array();
}
 
// Read all the lines until we reach the end of the definition, storing
// each one...
 
if (!$ignore) {
while (!feof($handle)) {
$line = trim(fgets($handle));
if (strncmp($line, '[websvn-enddefineicons]', 22) == 0) {
return true;
}
$eqsign = strpos($line, '=');
$match = substr($line, 0, $eqsign);
$def = substr($line, $eqsign + 1);
$icons[$match] = $def;
}
}
return true;
}
 
if (strncmp(trim($line), '[websvn-icon]', 13) == 0) {
global $icons, $vars;
 
if (!$ignore) {
// The current filetype should be defined my $vars['filetype']
if (!empty($icons[$vars['filetype']])) {
echo parseTags($icons[$vars['filetype']], $vars);
} else if (!empty($icons['*'])) {
echo parseTags($icons['*'], $vars);
}
}
 
return true;
}
 
if (strncmp(trim($line), '[websvn-treenode]', 17) == 0) {
global $icons, $vars;
 
if (!$ignore) {
if ((!empty($icons['i-node'])) && (!empty($icons['t-node'])) && (!empty($icons['l-node']))) {
for ($n = 1; $n < $vars['level']; $n++) {
if ($vars['last_i_node'][$n]) {
echo parseTags($icons['e-node'], $vars);
} else {
echo parseTags($icons['i-node'], $vars);
}
}
 
if ($vars['level'] != 0) {
if ($vars['node'] == 0) {
echo parseTags($icons['t-node'], $vars);
} else {
echo parseTags($icons['l-node'], $vars);
$vars['last_i_node'][$vars['level']] = true;
}
}
}
}
return true;
}
return false;
}
 
// parseTemplate
//
// Parse the given template, replacing the variables with the values passed
 
function parseTemplate($file) {
global $ignore, $rep, $config, $vars, $listing;
 
$template = (($rep) ? $rep->getTemplatePath() : $config->getTemplatePath()).$file;
if (!is_file($template)) {
print 'No template file found ('.$template.')';
exit;
}
 
$handle = fopen($template, 'r');
$inListing = false;
$ignore = false;
$listLines = array();
 
while (!feof($handle)) {
$line = fgets($handle);
// Check for the end of the file list
if ($inListing) {
if (strcmp(trim($line), '[websvn-endlisting]') == 0) {
$inListing = false;
 
// For each item in the list
foreach ($listing as $listvars) {
// Copy the value for this list item into the $vars array
foreach ($listvars as $id => $value) {
$vars[$id] = $value;
}
// Output the list item
foreach ($listLines as $line) {
if (!parseCommand($line, $vars, $handle) && !$ignore) {
print parseTags($line, $vars);
}
}
}
} else if ($ignore == false) {
$listLines[] = $line;
}
} else if (parseCommand($line, $vars, $handle)) {
continue;
} else {
// Check for the start of the file list
if (strncmp(trim($line), '[websvn-startlisting]', 21) == 0) {
$inListing = true;
} else {
if ($ignore == false) {
print parseTags($line, $vars);
}
}
}
}
fclose($handle);
}
 
// parseTags
//
// Replace all occurences of [websvn:varname] with the give variable
 
function parseTags($line, $vars) {
global $lang;
 
// Replace the language strings
while (preg_match('|\[lang:([a-zA-Z0-9_]+)\]|', $line, $matches)) {
// Make sure that the variable exists
if (!isset($lang[$matches[1]])) {
$lang[$matches[1]] = '?${matches[1]}?';
}
$line = str_replace($matches[0], $lang[$matches[1]], $line);
}
 
$l = '';
// Replace the websvn variables
while (preg_match('|\[websvn:([a-zA-Z0-9_]+)\]|', $line, $matches)) {
// Find beginning
$p = strpos($line, $matches[0]);
 
// add everything up to beginning
if ($p > 0) {
$l .= substr($line, 0, $p);
}
 
// Replace variable (special token, if not exists)
$l .= isset($vars[$matches[1]]) ? $vars[$matches[1]]: ('?'.$matches[1].'?');
 
// Remove allready processed part of line
$line = substr($line, $p + strlen($matches[0]));
}
 
// Rebuild line, add remaining part of line
$line = $l.$line;
 
return $line;
}
 
 
// renderTemplate
//
// Renders the templates for the given view
 
function renderTemplate($view, $readmePath = null)
{
 
global $config, $rep, $vars, $listing, $lang, $locwebsvnhttp;
 
// Set the view in the templates variables
$vars['template'] = $view;
 
// Check if we are using a PHP powered template or the standard one
$path = !empty($rep) ? $rep->getTemplatePath() : $config->getTemplatePath();
$path = $path . 'template.php';
 
if (is_readable($path))
{
$vars['templateentrypoint'] = $path;
executePlainPhpTemplate($vars);
}
else
{
parseTemplate('header.tmpl');
flush(); // http://developer.yahoo.com/performance/rules.html#flush
parseTemplate($view . '.tmpl');
 
if (($view === 'directory') || ($view === 'log'))
{
print '<script type="text/javascript" src="'.$locwebsvnhttp.'/javascript/compare-checkboxes.js"></script>';
}
 
if ($readmePath == null)
{
parseTemplate('footer.tmpl');
return;
}
 
$svnrep = new SVNRepository($rep);
$svnrep->listReadmeContents($readmePath);
parseTemplate('footer.tmpl');
}
}
 
function executePlainPhpTemplate($vars) {
require_once $vars['templateentrypoint'];
}
 
// {{{ renderTemplate404
 
function renderTemplate404($view, $errorDetail="")
{
global $vars, $lang;
http_response_code(404);
$vars['error'] = "WebSVN 404 ".$lang[$errorDetail];
renderTemplate($view);
exit(0);
}
 
// }}}
/WebSVN/include/utils.php
0,0 → 1,477
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// utils.php
//
// General utility commands
 
// {{{ createDirLinks
//
// Create a list of links to the current path that'll be available from the template
 
function createPathLinks($rep, $path, $rev, $peg = '') {
global $config, $lang, $vars;
 
$pathComponents = explode('/', $path);
$count = count($pathComponents);
 
// The number of links depends on the last item. It's empty if we're looking
// at a directory, and non-empty if we're looking at a file.
if (empty($pathComponents[$count - 1])) {
$limit = $count - 2;
$dir = true;
} else {
$limit = $count - 1;
$dir = false;
}
 
$passRevString = createRevAndPegString($rev, $peg);
$pathSoFar = '/';
$pathSoFarURL = $config->getURL($rep, $pathSoFar, 'dir').$passRevString;
 
$repoName = $rep->getDisplayName();
$rootName = $lang['BREADCRUMB_REPO_ROOT'];
 
$vars['path_links'] = '';
$vars['path_links_root_root'] = "<a href=\"{$pathSoFarURL}\" class=\"root\"><span>{$rootName}</span></a>";
$vars['path_links_root_repo'] = "<a href=\"{$pathSoFarURL}\" class=\"root\"><span>{$repoName}</span></a>";
$vars['path_links_root_config'] = $config->getBreadcrumbRepoRootAsRepo()
? $vars['path_links_root_repo']
: $vars['path_links_root_root'];
 
for ($n = 1; $n < $limit; $n++) {
$pathSoFar .= $pathComponents[$n].'/';
$pathSoFarURL = $config->getURL($rep, $pathSoFar, 'dir').$passRevString;
$vars['path_links'] .= '<a href="'.$pathSoFarURL.'#'.anchorForPath($pathSoFar).'">'.escape($pathComponents[$n]).'</a>/';
}
 
if (!empty($pathComponents[$n])) {
$pegrev = ($peg && $peg != $rev) ? ' <a class="peg" href="'.'?'.escape(str_replace('&peg='.$peg, '', $_SERVER['QUERY_STRING'])).'">@ '.$peg.'</a>' : '';
if ($dir) {
$vars['path_links'] .= '<span class="dir">'.escape($pathComponents[$n]).'/'.$pegrev.'</span>';
} else {
$vars['path_links'] .= '<span class="file">'.escape($pathComponents[$n]).$pegrev.'</span>';
}
}
}
 
// }}}
 
function createRevAndPegString($rev, $peg) {
$params = array();
if ($rev) $params[] = 'rev='.$rev;
if ($peg) $params[] = 'peg='.$peg;
return implode('&amp;', $params);
}
 
function createDifferentRevAndPegString($rev, $peg) {
$params = array();
if ($rev && (!$peg || $rev != $peg)) $params[] = 'rev='.$rev;
if ($peg) $params[] = 'peg='.$peg;
return implode('&amp;', $params);
}
 
function anchorForPath($path) {
global $config;
 
// (X)HMTL id/name attribute must be this format: [A-Za-z][A-Za-z0-9-_.:]*
// MD5 hashes are 32 characters, deterministic, quite collision-resistant,
// and work for any string, regardless of encoding or special characters.
if ($config->treeView)
return 'a'.md5($path);
else
return '';
}
 
// {{{ create_anchors
//
// Create links out of http:// and mailto: tags
 
// TODO: the target="_blank" nonsense should be optional (or specified by the template)
function create_anchors($text) {
$ret = $text;
 
// Match correctly formed URLs that aren't already links
$ret = preg_replace('#\b(?<!href=")([a-z]+?)://(\S*)([\w/]+)#i',
'<a href="\\1://\\2\\3" target="_blank">\\1://\\2\\3</a>',
$ret);
 
// Now match anything beginning with www, as long as it's not //www since they were matched above
$ret = preg_replace('#\b(?<!//)www\.(\S*)([\w/]+)#i',
'<a href="http://www.\\1\\2" target="_blank">www.\\1\\2</a>',
$ret);
 
// Match email addresses
$ret = preg_replace('#\b([\w\-_.]+)@([\w\-.]+)\.(\w{2,})\b#i',
'<a href="mailto:\\1@\\2.\\3">\\1@\\2.\\3</a>',
$ret);
 
return $ret;
}
 
// }}}
 
// {{{ getFullURL
 
function getFullURL($loc) {
$protocol = 'http';
 
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$protocol = $_SERVER['HTTP_X_FORWARDED_PROTO'];
} else if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) {
$protocol = 'https';
}
 
$port = ':'.$_SERVER['SERVER_PORT'];
if ((':80' == $port && 'http' == $protocol) || (':443' == $port && 'https' == $protocol)) {
$port = '';
}
 
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$host = $_SERVER['HTTP_X_FORWARDED_HOST'];
} else if (isset($_SERVER['HTTP_HOST'])) {
$host = $_SERVER['HTTP_HOST'];
} else if (isset($_SERVER['SERVER_NAME'])) {
$host = $_SERVER['SERVER_NAME'].$port;
} else if (isset($_SERVER['SERVER_ADDR'])) {
$host = $_SERVER['SERVER_ADDR'].$port;
} else {
print 'Unable to redirect';
exit;
}
 
// make sure we have a directory to go to
if (empty($loc)) {
$loc = '/';
} else if ($loc[0] != '/') {
$loc = '/'.$loc;
}
 
$url = $protocol . '://' . $host . $loc;
 
return $url;
}
 
// }}}
 
function xml_entities($str) {
$entities = array();
$entities['&'] = '&amp;';
$entities['<'] = '&lt;';
$entities['>'] = '&gt;';
$entities['"'] = '&quot;';
$entities['\''] = '&apos;';
return str_replace(array_keys($entities), array_values($entities), $str);
}
 
// {{{ hardspace
//
// Replace the spaces at the front of a line with hard spaces
 
// XXX: this is an unnecessary function; you can prevent whitespace from being
// trimmed via CSS (use the "white-space: pre;" properties). ~J
// in the meantime, here's an improved function (does nothing)
 
function hardspace($s) {
return '<code>' . expandTabs($s) . '</code>';
}
 
// }}}
 
function wrapInCodeTagIfNecessary($string) {
global $config;
return ($config->getUseGeshi()) ? $string : '<code>'.$string.'</code>';
}
 
// {{{ expandTabs
 
/**
* Expands the tabs in a line that may or may not include HTML.
*
* Enscript generates code with HTML, so we need to take that into account.
*
* @param string $s Line of possibly HTML-encoded text to expand
* @param int $tabwidth Tab width, -1 to use repository's default, 0 to collapse
* all tabs.
* @return string The expanded line.
* @since 2.1
*/
 
function expandTabs($s, $tabwidth = - 1) {
global $rep;
 
if ($tabwidth == -1) {
$tabwidth = $rep->getExpandTabsBy();
}
$pos = 0;
 
// Parse the string into chunks that are either 1 of: HTML tag, tab char, run of any other stuff
$chunks = preg_split('/((?:<.+?>)|(?:&.+?;)|(?:\t))/', $s, -1, PREG_SPLIT_DELIM_CAPTURE);
 
// Count the sizes of the chunks and replace tabs as we go
$chunkscount = count($chunks);
for ($i = 0; $i < $chunkscount; $i++) {
// make sure we're not dealing with an empty string
if (empty($chunks[$i])) continue;
switch ($chunks[$i][0]) {
case '<': // HTML tag: ignore its width by doing nothing
break;
 
case '&': // HTML entity: count its width as 1 char
$pos++;
break;
 
case "\t": // Tab char: replace it with a run of spaces between length tabwidth and 1
$tabsize = $tabwidth - ($pos % $tabwidth);
$chunks[$i] = str_repeat(' ', $tabsize);
$pos += $tabsize;
break;
 
default: // Anything else: just keep track of its width
$pos += strlen($chunks[$i]);
break;
}
}
 
// Put the chunks back together and we've got the original line, detabbed.
return join('', $chunks);
}
 
// }}}
 
// {{{ datetimeFormatDuration
//
// Formats a duration of seconds for display.
//
// $seconds the number of seconds until something
// $nbsp true if spaces should be replaced by nbsp
// $skipSeconds true if seconds should be omitted
//
// return the formatted duration (e.g. @c "8h 6m 1s")
 
function datetimeFormatDuration($seconds, $nbsp = false, $skipSeconds = false) {
global $lang;
 
$neg = false;
if ($seconds < 0) {
$seconds = 0 - $seconds;
$neg = true;
}
 
$qty = array();
$names = array($lang['DAYLETTER'], $lang['HOURLETTER'], $lang['MINUTELETTER']);
 
$qty[] = (int)($seconds / (60 * 60 * 24));
$seconds %= 60 * 60 * 24;
 
$qty[] = (int)($seconds / (60 * 60));
$seconds %= 60 * 60;
 
$qty[] = (int)($seconds / 60);
 
if (!$skipSeconds) {
$qty[] = (int)($seconds % 60);
$names[] = $lang['SECONDLETTER'];
}
 
$text = $neg ? '-' : '';
$any = false;
$count = count($names);
$parts = 0;
for ($i = 0; $i < $count; $i++) {
// If a "higher valued" time slot had a value or this time slot
// has a value or this is the very last entry (i.e. all values
// are 0 and we still want to print seconds)
if ($any || $qty[$i] > 0 || $i == $count - 1) {
if ($any) $text .= $nbsp ? '&nbsp;' : ' ';
$text .= $qty[$i].' '.$names[$i];
$any = true;
$parts++;
if ($parts >= 2) break;
}
}
return $text;
}
 
// }}}
 
function parseSvnTimestamp($dateString) {
// Try the simple approach of a built-in PHP function first.
$date = strtotime($dateString);
// If the resulting timestamp isn't sane, try parsing manually.
if ($date <= 0) {
$y = 0;
$mo = 0;
$d = 0;
$h = 0;
$m = 0;
$s = 0;
sscanf($dateString, '%d-%d-%dT%d:%d:%d.', $y, $mo, $d, $h, $m, $s);
 
$mo = substr('00'.$mo, -2);
$d = substr('00'.$d, -2);
$h = substr('00'.$h, -2);
$m = substr('00'.$m, -2);
$s = substr('00'.$s, -2);
$date = strtotime($y.'-'.$mo.'-'.$d.' '.$h.':'.$m.':'.$s.' GMT');
}
return $date;
}
 
// {{{ buildQuery
//
// Build parameters for url query part
 
function buildQuery($data, $separator = '&amp;', $key = '') {
if (is_object($data))
$data = get_object_vars($data);
$p = array();
foreach ($data as $k => $v) {
$k = rawurlencode($k);
if (!empty($key))
$k = $key.'['.$k.']';
if (is_array($v) || is_object($v)) {
$p[] = buildQuery($v, $separator, $k);
} else {
$p[] = $k.'='.rawurlencode($v);
}
}
return implode($separator, $p);
}
 
// }}}
 
// {{{ getUserLanguage
 
function getUserLanguage($languages, $default, $userchoice) {
global $config;
if (!$config->useAcceptedLanguages()) return $default;
 
$acceptlangs = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : false;
if (!$acceptlangs)
return $default;
 
$langs = array();
$sublangs = array();
 
foreach (explode(',', $acceptlangs) as $str) {
$a = explode(';', $str, 2);
$lang = trim($a[0]);
$pos = strpos($lang, '-');
if ($pos !== false)
$sublangs[] = substr($lang, 0, $pos);
$q = 1.0;
if (count($a) == 2) {
$v = trim($a[1]);
if (substr($v, 0, 2) == 'q=')
$q = doubleval(substr($v, 2));
}
if ($userchoice)
$q *= 0.9;
$langs[$lang] = $q;
}
 
foreach ($sublangs as $l)
if (!isset($langs[$l]))
$langs[$l] = 0.1;
 
if ($userchoice)
$langs[$userchoice] = 1.0;
 
arsort($langs);
foreach ($langs as $code => $q) {
if (isset($languages[$code])) {
return $code;
}
}
 
return $default;
}
 
// }}}
 
// {{{ removeDirectory
 
function removeDirectory($dir)
{
if (!is_dir($dir))
{
return false;
}
 
$dir = rtrim($dir, '/');
$handle = dir($dir);
 
while (($file = $handle->read()) !== false)
{
if (($file == '.') || ($file == '..'))
{
continue;
}
 
$f = $dir.DIRECTORY_SEPARATOR.$file;
if (!is_link($f) && is_dir($f))
{
removeDirectory($f);
}
else
{
@unlink($f);
}
}
 
$handle->close();
@rmdir($dir);
 
return true;
}
 
// }}}
 
// {{{ tempnameWithCheck
 
function tempnamWithCheck($dir, $prefix, $rmOnShutdown = true) {
$tmp = tempnam($dir, $prefix);
 
if ($tmp && !$rmOnShutdown)
{
return $tmp;
}
if ($tmp && $rmOnShutdown)
{
register_shutdown_function('removeDirectory', $tmp);
return $tmp;
}
 
if (!$tmp && !headers_sent())
{
http_response_code(500);
error_log('Unable to create a temporary file. Either make the currently used directory ("' . $dir . '") writable for WebSVN or change the directory in the configuration.');
print 'Unable to create a temporary file. Either make the currently used directory writable for WebSVN or change the directory in the configuration.';
exit(0);
}
 
global $vars;
$vars['warning'] = 'Unable to create a temporary file. Either make the currently used directory writable for WebSVN or change the directory in the configuration.';
 
return $tmp;
}
 
// }}}
/WebSVN/include/version.php
0,0 → 1,25
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// version.php
//
// Version information
 
$version = '2.8.3';
/WebSVN/index.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,102 → 9,111
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// index.php
//
// Main page. Lists all the projects
// Main page which lists all configured repositories (optionally by groups).
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/template.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/template.php';
 
$vars["action"] = $lang["PROJECTS"];
$vars["repname"] = "";
$vars["rev"] = 0;
$vars["path"] = "";
$vars['action'] = $lang['PROJECTS'];
$vars['repname'] = '';
$vars['rev'] = 0;
$vars['path'] = '';
$vars['safepath'] = escape('');
$vars['showlastmod'] = $config->showLastModInIndex();
 
// Sort the repositories by group
$config->sortByGroup();
$projects = $config->getRepositories();
 
if ($config->flatIndex)
{
// Create the flat view
$projects = $config->getRepositories();
$i = 0;
$listing = array ();
foreach ($projects as $project)
{
if ($project->hasReadAccess("/", true))
{
$url = $config->getURL($project, "/", "dir");
$listing[$i]["rowparity"] = $i % 2;
$listing[$i++]["projlink"] = "<a href=\"${url}sc=0\">".$project->getDisplayName()."</a>";
}
}
$vars["flatview"] = true;
$vars["treeview"] = false;
if (count($projects) == 1 && $projects[0]->hasReadAccess('/')) {
header('Location: '.str_replace('&amp;', '', $config->getURL($projects[0], '', 'dir')));
exit;
}
else
{
// Create the tree view
$projects = $config->getRepositories();
reset($projects);
$i = 0;
$listing = array ();
$curgroup = NULL;
$parity = 0;
foreach ($projects as $project)
{
if ($project->hasReadAccess("/", true))
{
$listing[$i]["rowparity"] = $parity % 2;
$url = $config->getURL($project, "/", "dir");
if ($curgroup != $project->group)
{
# TODO: this should be de-soupified
if (!empty($curgroup))
$listing[$i]["listitem"] = "</div>\n"; // Close the switchcontent div
else
$listing[$i]["listitem"] = "";
 
$listing[$i]["isprojlink"] = false;
$listing[$i]["isgrouphead"] = true;
$curgroup = $project->group;
$listing[$i++]["listitem"] .= "<div class=\"groupname\" onclick=\"expandcontent(this, '$curgroup');\" style=\"cursor:hand; cursor:pointer\"><div class=\"a\"><span class=\"showstate\"></span>$curgroup</div></div>\n<div id=\"$curgroup\" class=\"switchcontent\">";
}
$i = 0;
$parity = 0; // Alternates between every entry, whether it is a group or project
$groupparity = 0; // The first project (and first of any group) resets this to 0
$curgroup = null;
$groupcount = 0;
 
$parity++;
$listing[$i]["isgrouphead"] = false;
$listing[$i]["isprojlink"] = true;
$listing[$i++]["listitem"] = "<a href=\"${url}sc=0\">".$project->name."</a>\n";
}
}
// Create listing of all configured projects (includes groups if they are used).
foreach ($projects as $project) {
if (!$project->hasReadAccess('/'))
continue;
 
if (!empty($curgroup))
$listing[$i]["isprojlink"] = false;
$listing[$i]["isgrouphead"] = false;
$listing[$i]["listitem"] = "</div>"; // Close the switchcontent div
$listvar = &$listing[$i];
// If this is the first project in a group, add an entry for the group.
if ($curgroup != $project->group) {
$groupcount++;
$groupparity = 0;
$listvar['notfirstgroup'] = !empty($curgroup);
$curgroup = $project->group;
$listvar['groupname'] = $curgroup; // Applies until next group is set.
$listvar['groupid'] = strtr(base64_encode('grp'.$curgroup), array('+' => '-', '/' => '_', '=' => ''));
 
$vars["flatview"] = false;
$vars["treeview"] = true;
$vars["opentree"] = $config->openTree;
// setting to null because template.php won't unset them
$listvar['projectlink'] = null;
$listvar['projectname'] = null;
$listvar['projecturl'] = null;
$i++; // Causes the subsequent lines to store data in the next array slot.
$listvar = &$listing[$i];
$listvar['groupid'] = null;
}
$listvar['clientrooturl'] = $project->clientRootURL;
 
// Populate variables for latest modification to the current repository
if ($config->showLastModInIndex()) {
$svnrep = new SVNRepository($project);
$log = $svnrep->getLog('/', '', '', true, 1);
 
if (isset($log->entries[0])) {
$head = $log->entries[0];
$listvar['revision'] = $head->rev;
$listvar['date'] = $head->date;
$listvar['age'] = datetimeFormatDuration(time() - strtotime($head->date));
$listvar['author'] = $head->author;
} else {
$listvar['revision'] = 0;
$listvar['date'] = '';
$listvar['age'] = '';
$listvar['author'] = '';
}
}
 
// Create project (repository) listing
$url = str_replace('&amp;', '', $config->getURL($project, '', 'dir'));
$name = ($config->flatIndex) ? $project->getDisplayName() : $project->name;
$listvar['projectlink'] = '<a href="'.$url.'">'.escape($name).'</a>';
$listvar['projectname'] = escape($name);
$listvar['projecturl'] = $url;
$listvar['rowparity'] = $parity % 2;
$parity++;
$listvar['groupparity'] = $groupparity % 2;
$groupparity++;
$listvar['groupname'] = ($curgroup != null) ? $curgroup : '';
$i++;
}
 
$vars["version"] = $version;
parseTemplate($config->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($config->getTemplatePath()."index.tmpl", $vars, $listing);
parseTemplate($config->getTemplatePath()."footer.tmpl", $vars, $listing);
if (empty($listing) && !empty($projects)) {
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
?>
$vars['flatview'] = $config->flatIndex;
$vars['treeview'] = !$config->flatIndex;
$vars['opentree'] = $config->openTree;
$vars['groupcount'] = $groupcount; // Indicates whether any groups were present.
 
renderTemplate('index');
/WebSVN/javascript/blame-popup.js
0,0 → 1,40
// Find all tags that match <a class="blame-revision" ...> and add events.
var a = document.getElementsByTagName('a');
for (var i = 0; i < a.length; i++) {
if (a[i].className == 'blame-revision') {
addEvent(a[i], 'mouseover', function() { mouseover(this) } );
addEvent(a[i], 'mouseout', function() { mouseout(this) } );
}
}
 
function addEvent(obj, type, func) {
if (obj.addEventListener) {
obj.addEventListener(type, func, false);
return true;
} else if (obj.attachEvent) {
return obj.attachEvent('on'+type, func);
} else {
return false;
}
}
 
function mouseover(a) {
// Find the revision number within the hyperlink text
var m = /rev=(\d+)/.exec(a.href);
var r = m[1];
if (rev[r]) {
var div = document.createElement('div');
div.className = 'blame-popup';
div.innerHTML = rev[r];
a.parentNode.appendChild(div);
}
}
 
function mouseout(a) {
var div = a.parentNode.parentNode.getElementsByTagName('div');
for (var i = 0; i < div.length; i++) {
if (div[i].className = 'blame-popup') {
div[i].parentNode.removeChild(div[i]);
}
}
}
/WebSVN/javascript/collapsible.js
0,0 → 1,209
var tableRows = document.getElementsByTagName('tr');
 
function toggleGroup(groupName)
{
for (var i = 0; i < tableRows.length; i++)
{
if (tableRows[i].title == groupName)
{
if (tableRows[i].style.display == 'none')
{
tableRows[i].style.display = 'table-row';
}
else
{
tableRows[i].style.display = 'none';
}
}
}
}
 
function collapseAllGroups()
{
for (var i = 0; i < tableRows.length; i++)
{
if (tableRows[i].title != '')
{
tableRows[i].style.display = 'none';
}
}
}
 
$("table.collapsible thead").find("th").on("click", function()
{
let oldClass = $(this).get(0).className;
let newClass = (oldClass == 'open') ? 'closed' : 'open';
 
$(this).get(0).className = newClass;
$(this).closest("table").find("tbody").toggle();
});
 
/**
* Hide all non-root entries currently visible.
* <p>
* Depending on the config, the site is able to load ALL files and directories of the current repo
* recursively to prevent additional requests. The use case is to hide all of the root-dirs and let
* users simply toggle the next level of interest without additional waiting. This is implemented by
* using the {@code title}-attribute and the {@code /}-character to represent some path and ONLY the
* root-dirs themself to show DON'T contain such. All other entries have some, either because they
* belong to a subdir or file within some parent dir.
* </p>
* <p>
* There's currently no additional config necessary to apply this JS or not, because the rows worked
* on are only generated in case recursive loading is enabled already!
* </p>
*/
$('table#listing > tbody > tr[title*="/"]').each(function()
{
// "visibility: collapse" leaves some space at the bottom of the whole list, resulting in not
// wanted scrollbars being shown by default.
$(this).hide();
});
 
/**
* Select all direct children for the given parent.
* <p>
* The markup doesn't model parent-child relationships currently, but instead all directories,
* files etc. are maintained as individual rows one after each other. In theory not even the order
* of those rows needs to be alphabetically or fit the parent-child-order in the repo or else, all
* can be mixed-up. So this function searches all rows of the given {@code body} for DIRECT children
* of the given parent row, which can be identified by their paths maintained in the {@code title}-
* attribute. Such filtering is non-trivial and one can't use CSS-selectors only, because those
* paths need to fulfill certain conditions.
* </p>
* @param[in] body
* @param[in] rowParent
* @return Array with direct children of the given parent.
*/
function recursiveLoadDirectChildrenSelect(body, rowParent)
{
// The parent title is used in some reg exp, so properly escape/quote it. Sadly "\Q...\E" does
// not work and JS doesn't seem to provide anythign else on its own as well.
// https://stackoverflow.com/a/3561711/2055163
let titleParent = rowParent.attr('title') || '';
titleParent = titleParent.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
let selector = 'tr[title^="' + titleParent + '/"]';
let directChildren = [];
 
// Selectors don't support regular expressions, but direct children not only start with the
// parent, but don't contain additional children in their title as well. One can't select
// that condition easily, so find ALL children and filter later to direct ones only.
body.children(selector).each(function()
{
let rowChild = $(this);
let titleChild = rowChild.attr('title') || '';
 
let ptChildDirs = titleParent + '/$';
let ptChildFiles = titleParent + '/[^/]+$';
let pattern = ptChildDirs + '|' + ptChildFiles;
 
if (titleChild.match(pattern))
{
directChildren.push(rowChild);
}
});
 
return directChildren;
}
 
/**
* Click-handler for some parent directory.
* <p>
* What needs to happen depends on the visibility of the direct children associated with some parent
* and therefore given: If children are NOT visible, simply show them and ONLY those, as showing
* should not be recursive currently. If children are visible OTOH, ALL of those need to be hidden
* or otherwise some lower level children would still be shown. This is because of the currently
* used markup, which doesn't model parent-child-relationships properly, but places everything at
* one level. Someone needs to take care of hiding children of children of children, when hiding
* associated markup itself only hides some of those. To hide recursively, a custom event named
* {@code hide_children} seems the easiest approach currently, which is then simply handled by the
* parent directory again.
* </p>
* @param[in] directChildren
* @return {@code false} to stop propagation of the current event.
*/
function recursiveLoadRowParentOnClick(directChildren)
{
$.each(directChildren, function()
{
let self = $(this);
let isVisible = self.is(':visible');
 
if (!isVisible)
{
self.show();
return true;
}
 
self.trigger('hide_children');
self.hide();
});
 
return false;
}
 
/**
* Handler to hide direct children.
* <p>
* While showing only the next level of children is wanted, when hiding ALL levels need to be hidden
* instead. This can not easily be achieved with the current markup placing ALL directories, files
* etc. regardless of their depth on the same level. So a special event is registered on each dir
* to simply hide ALL of it's own children and that event is triggered on ALL children of some dir
* as necessary.
* </p>
* @param[in] directChildren
* @return {@code false} to stop propagation of the current event.
*/
function recursiveLoadRowParentOnHideChildren(directChildren)
{
$.each(directChildren, function()
{
let self = $(this);
 
self.trigger('hide_children');
self.hide();
});
 
return false;
}
 
/**
* Process one row when loading all directories and files of some repo recursively.
* <p>
* Markup currently doesn't proiperly model parent-child-relationships, so the current approach is
* to iterated all rows of some rendered table to find direct children on our own. Those children
* are the once to show or hide in the end any by iterating all rows and search the whole body for
* children, all of those can be found easily to register necessary event handlers.
* </p>
* @param[in] body
* @param[in] rowParent
*/
function recursiveLoadRowProc(body, rowParent)
{
let directChildren = recursiveLoadDirectChildrenSelect(body, rowParent);
 
rowParent.find('td.path a[href^="listing.php?"]').on('click', function()
{
return recursiveLoadRowParentOnClick(directChildren);
});
 
rowParent.on('hide_children', function()
{
return recursiveLoadRowParentOnHideChildren(directChildren);
});
}
 
/**
* Register event handlers to hide and show children of root-directories.
*/
$('table#listing > tbody').each(function()
{
let body = $(this);
 
// Each row needs to be checked for its direct children, so that only those can be toggled. The
// "tbody" is necessary so that one can find direct children per row as well, because all those
// are maintained on the same level and only distinguished by their textual path. So we either
// need to search the "tbody" per row for all children or implement some other approach mapping
// things by only iterating rows once. The current approach seems easier for now.
body.children('tr').each(function() { recursiveLoadRowProc(body, $(this)); });
});
/WebSVN/javascript/compare-checkboxes.js
0,0 → 1,18
// Enforce only two compare boxes being checked at once.
function enforceOnlyTwoChecked(clickedCheckbox) {
count = 0;
first = null;
form = clickedCheckbox.form;
for (i = 0; i < form.elements.length; i++) {
if (form.elements[i].type == 'checkbox' && form.elements[i].checked) {
if (first == null && form.elements[i] != clickedCheckbox) {
first = form.elements[i];
}
count += 1;
}
}
if (count > 2) {
first.checked = false;
count -= 1;
}
}
/WebSVN/javascript/ie-png-transparency.js
0,0 → 1,39
// correctly handle PNG transparency in Win IE 5.5 or higher.
function correctPNG()
{
for(var i = 0; i < document.images.length; i++)
{
var img = document.images[i]
var imgName = img.src.toUpperCase()
if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
{
var imgID = (img.id) ? "id='" + img.id + "' " : ""
var imgClass = (img.className) ? "class='" + img.className + "' " : ""
var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
var imgStyle = "display:inline-block;" + img.style.cssText
var imgAttribs = img.attributes;
for (var j=0; j<imgAttribs.length; j++)
{
var imgAttrib = imgAttribs[j];
if (imgAttrib.nodeName == "align")
{
if (imgAttrib.nodeValue == "left") imgStyle = "float:left;" + imgStyle
if (imgAttrib.nodeValue == "right") imgStyle = "float:right;" + imgStyle
break
}
}
var strNewHTML = "<span " + imgID + imgClass + imgTitle
strNewHTML += " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
strNewHTML += "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
strNewHTML += "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"
img.outerHTML = strNewHTML
i = i-1
}
}
}
 
var supported = /MSIE (5\.5)|[6789]/.test(navigator.userAgent) && navigator.platform == "Win32";
 
if (supported)
window.attachEvent("onload", correctPNG);
/WebSVN/javascript/jquery.min.1.9.1.js
0,0 → 1,5
/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
//@ sourceMappingURL=jquery.min.map
*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
/WebSVN/languages/NotUsed/russian.inc
File deleted
/WebSVN/languages/NotUsed/japanese.inc
File deleted
/WebSVN/languages/NotUsed/norwegian.inc
File deleted
/WebSVN/languages/NotUsed/turkish.inc
File deleted
/WebSVN/languages/NotUsed/finnish.inc
File deleted
/WebSVN/languages/NotUsed/slovenian.inc
File deleted
/WebSVN/languages/NotUsed/polish.inc
File deleted
/WebSVN/languages/NotUsed/schinese.inc
File deleted
/WebSVN/languages/NotUsed/tchinese.inc
File deleted
/WebSVN/languages/NotUsed/portuguese.inc
File deleted
/WebSVN/languages/NotUsed/catalan.inc
File deleted
/WebSVN/languages/NotUsed/spanish.inc
File deleted
/WebSVN/languages/NotUsed/french.inc
File deleted
/WebSVN/languages/NotUsed/danish.inc
File deleted
/WebSVN/languages/NotUsed/swedish.inc
File deleted
/WebSVN/languages/NotUsed/dutch.inc
File deleted
/WebSVN/languages/NotUsed/german.inc
File deleted
/WebSVN/languages/NotUsed/korean.inc
File deleted
/WebSVN/languages/czech.inc
File deleted
/WebSVN/languages/english.inc
File deleted
/WebSVN/languages/czech.php
0,0 → 1,124
<?php
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// czech.php
//
// Czech language strings
 
$lang["LANGUAGETAG"] = "cs"; // Language tag (RFC 4646) for this translation.
$lang["LANGUAGENAMEENGLISH"] = "Czech";
$lang["LANGUAGENAMENATIVE"] = "Česky";
$lang["LANGUAGENAMEHTML"] = "&#268;esky";
 
$lang['BREADCRUMB_REPO_ROOT'] = '(root)';
 
$lang["LOG"] = "Záznam";
// $lang["DIFF"] = "Diff";
 
$lang["NOREP"] = "Není určen žádný repozitář";
$lang["NOPATH"] = "Cesta nebyla nalezena";
$lang["NOACCESS"] = "Nemáte dostatečná přístupová práva pro čtení adresáře";
$lang["RESTRICTED"] = "Omezený přístup";
$lang["SUPPLYREP"] = "Nastavte prosím cestu k repozitáři v include/config.php pomocí \$config->parentPath nebo \$config->addRepository<p>Podívejte se do insatlační příručky pro podrobnější informace";
 
$lang["DIFFREVS"] = "Rozdíly mezi revizemi";
$lang["AND"] = "a";
$lang["REV"] = "Revize";
// $lang["LINE"] = "Line";
$lang["LINENO"] = "Číslo řádky";
$lang["SHOWENTIREFILE"] = "Zobraz celý soubor";
$lang["SHOWCOMPACT"] = "Zobraz pouze rozdílné části";
// $lang["IGNOREWHITESPACE"] = "Ignore whitespace";
// $lang["REGARDWHITESPACE"] = "Regard whitespace";
 
// $lang["LISTING"] = "Directory listing";
// $lang["FILEDETAIL"] = "Details";
// $lang["VIEWAS"] = "View as";
$lang["DIFFPREV"] = "Porovnej s předchozí";
// $lang["BLAME"] = "Blame";
// $lang["BLAMEFOR"] = "Blame information for rev";
 
$lang["REVINFO"] = "Informace o revizi";
$lang["GOYOUNGEST"] = "Přejdi na současnou revizi";
$lang["LASTMOD"] = "Poslední změna";
$lang["LOGMSG"] = "Záznam";
$lang["CHANGES"] = "Změny";
$lang["SHOWCHANGED"] = "Zobraz změněné soubory";
$lang["HIDECHANGED"] = "Schovej změněné soubory";
$lang["NEWFILES"] = "Nové soubory";
$lang["CHANGEDFILES"] = "Změněné soubory";
$lang["DELETEDFILES"] = "Smazané soubory";
$lang["VIEWLOG"] = "Ukaž";
$lang["PATH"] = "Cesta";
$lang["AUTHOR"] = "Autor";
$lang["AGE"] = "Stáří";
$lang["CURDIR"] = "Aktuální adresář";
// $lang["TARBALL"] = "Tarball";
// $lang["DOWNLOAD"] = "Download";
 
$lang["PREV"] = "Předchozí";
$lang["NEXT"] = "Následující";
$lang["SHOWALL"] = "Ukaž všechny";
 
$lang["BADCMD"] = "Nepodařilo se spustit tento příkaz";
$lang["UNKNOWNREVISION"] = "Revize nebyla nalezena";
 
$lang["POWERED"] = "Poháněno <a href=\"https://websvnphp.github.io/\">WebSVN</a>";
$lang["PROJECTS"] = "Subversion Repozitáře";
$lang["SERVER"] = "Subversion Servery";
 
$lang["FILTER"] = "Nastavení filtrování";
$lang["STARTLOG"] = "Od revize";
$lang["ENDLOG"] = "Do revize";
$lang["MAXLOG"] = "Max revizí";
$lang["SEARCHLOG"] = "Hledat";
$lang["CLEARLOG"] = "Zruš aktuální filtr";
$lang["MORERESULTS"] = "Najdi další...";
$lang["NORESULTS"] = "Nejsou tu žádné zázanmy odpovídající vašim požadavkům";
$lang["NOMORERESULTS"] = "Nejsou tu žádné další záznamy odpovídající vašim požadavkům";
$lang["NOPREVREV"] = "Není předchozí revize.";
 
$lang["RSSFEEDTITLE"] = "WebSVN RSS feed";
$lang["FILESMODIFIED"] = "soubor(y) změněn(y)";
$lang["RSSFEED"] = "RSS";
 
$lang["DAYLETTER"] = "d";
$lang["HOURLETTER"] = "h";
$lang["MINUTELETTER"] = "m";
$lang["SECONDLETTER"] = "s";
 
$lang["GO"] = "Go";
 
$lang["PATHCOMPARISON"] = "Porovnání cest";
$lang["COMPAREPATHS"] = "Porovnej cesty";
$lang["COMPAREREVS"] = "Porovnej revize";
$lang["PROPCHANGES"] = "Změněné vlastnosti:";
$lang["CONVFROM"] = "Toto porovnání ukazuje změny pro převedení";
$lang["TO"] = "na";
$lang["REVCOMP"] = "Reverzní porovnání";
$lang["COMPPATH"] = "Porovnej cestu:";
$lang["WITHPATH"] = "S umístěním:";
$lang["FILEDELETED"] = "Soubor smazán";
$lang["FILEADDED"] = "Nový soubor";
 
$lang['SEARCH'] = "Vyhledávání";
$lang['SEARCH_PLACEHOLDER'] = "Vyhledejte položky zde";
$lang['NOITEMSFOUND'] = "Žádné předměty nenalezeny";
/WebSVN/languages/english.php
0,0 → 1,125
<?php
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// english.php
//
// English language strings
 
$lang["LANGUAGETAG"] = "en"; // Language tag (RFC 4646) for this translation.
$lang["LANGUAGENAMEENGLISH"] = "English";
$lang["LANGUAGENAMENATIVE"] = "English";
$lang["LANGUAGENAMEHTML"] = "English";
 
$lang['BREADCRUMB_REPO_ROOT'] = '(root)';
 
$lang["LOG"] = "Log";
$lang["DIFF"] = "Diff";
 
$lang["NOREP"] = "No repository given.";
$lang["NOPATH"] = "Path not found.";
$lang["NOACCESS"] = "You do not have the necessary permissions to view this content.";
$lang["RESTRICTED"] = "Restricted access.";
$lang["SUPPLYREP"] = "Please set up a repository in include/config.php using <code>\$config->parentPath</code> or <code>\$config->addRepository</code>. See the installation guide for more details.";
 
$lang["DIFFREVS"] = "Diff between revs";
$lang["AND"] = "and";
$lang["REV"] = "Rev";
$lang["LINE"] = "Line";
$lang["LINENO"] = "Line No.";
$lang["SHOWENTIREFILE"] = "Show entire file";
$lang["SHOWCOMPACT"] = "Only display areas with differences";
$lang["IGNOREWHITESPACE"] = "Ignore whitespace";
$lang["REGARDWHITESPACE"] = "Regard whitespace";
 
$lang["LISTING"] = "Directory listing";
$lang["FILEDETAIL"] = "Details";
$lang["VIEWAS"] = "View as";
$lang["DIFFPREV"] = "Compare with Previous";
$lang["BLAME"] = "Blame";
$lang["BLAMEFOR"] = "Blame information for rev";
 
$lang["REVINFO"] = "Revision Information";
$lang["GOYOUNGEST"] = "Go to most recent revision";
$lang["LASTMOD"] = "Last modification";
$lang["LOGMSG"] = "Log message";
$lang["CHANGES"] = "Changes";
$lang["SHOWCHANGED"] = "Show changed files";
$lang["HIDECHANGED"] = "Hide changed files";
$lang["NEWFILES"] = "New Files";
$lang["CHANGEDFILES"] = "Modified files";
$lang["DELETEDFILES"] = "Deleted files";
$lang["VIEWLOG"] = "View Log";
$lang["PATH"] = "Path";
$lang["AUTHOR"] = "Author";
$lang["AGE"] = "Age";
$lang["CURDIR"] = "Current Directory";
$lang["TARBALL"] = "Tarball";
$lang["DOWNLOAD"] = "Download";
 
$lang["PREV"] = "Prev";
$lang["NEXT"] = "Next";
$lang["SHOWALL"] = "Show All";
 
$lang["BADCMD"] = "Error running this command";
$lang["UNKNOWNREVISION"] = "Revision not found";
 
$lang["POWERED"] = "Powered by <a href=\"https://websvnphp.github.io/\">WebSVN</a>";
$lang["PROJECTS"] = "Subversion Repositories";
$lang["SERVER"] = "Subversion Server";
 
$lang["FILTER"] = "Filtering Options";
$lang["STARTLOG"] = "From rev";
$lang["ENDLOG"] = "To rev";
$lang["MAXLOG"] = "Max revs";
$lang["SEARCHLOG"] = "Search history for";
$lang["CLEARLOG"] = "Clear current filter";
$lang["MORERESULTS"] = "Find more matches...";
$lang["NORESULTS"] = "There are no logs matching your query";
$lang["NOMORERESULTS"] = "There are no more logs matching your query";
$lang["NOPREVREV"] = "No previous revision";
 
$lang["RSSFEEDTITLE"] = "WebSVN RSS feed";
$lang["FILESMODIFIED"] = "file(s) modified";
$lang["RSSFEED"] = "RSS feed";
 
$lang["DAYLETTER"] = "d";
$lang["HOURLETTER"] = "h";
$lang["MINUTELETTER"] = "m";
$lang["SECONDLETTER"] = "s";
 
$lang["GO"] = "Go";
 
$lang["PATHCOMPARISON"] = "Path Comparison";
$lang["COMPAREPATHS"] = "Compare Paths";
$lang["COMPAREREVS"] = "Compare Revisions";
$lang["PROPCHANGES"] = "Property changes:";
$lang["CONVFROM"] = "This comparison shows the changes necessary to convert path ";
$lang["TO"] = "to";
$lang["REVCOMP"] = "Reverse comparison";
$lang["COMPPATH"] = "Compare Path:";
$lang["WITHPATH"] = "With Path:";
$lang["FILEDELETED"] = "File deleted";
$lang["FILEADDED"] = "New file";
 
$lang['NOSEARCHTERM'] = "No search term provided";
$lang['SEARCH'] = "Search";
$lang['SEARCH_PLACEHOLDER'] = "Search for items here";
$lang['NOITEMSFOUND'] = "No Items Found";
/WebSVN/license.txt
0,0 → 1,280
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
 
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
 
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
 
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
/WebSVN/listing.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
24,446 → 22,621
//
// Show the listing for the given repository/path/revision
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
require_once("include/bugtraq.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
require_once 'include/bugtraq.php';
 
function removeURLSeparator($url)
{
return preg_replace('#(\?|&(amp;)?)$#', '', $url);
return preg_replace('#(\?|&(amp;)?)$#', '', $url);
}
 
function fileLink($path, $file, $returnjoin = false)
function urlForPath($fullpath, $passRevString)
{
global $rep, $passrev, $showchanged, $config;
if ($path == "" || $path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
global $config, $rep;
 
if ($ppath{strlen($ppath)-1} != "/")
$ppath .= "/";
if ($file{0} == "/")
$pfile = substr($file, 1);
else
$pfile = $file;
$isDir = $fullpath[strlen($fullpath) - 1] == '/';
 
if ($returnjoin)
return $ppath.$pfile;
if ($isDir)
{
if ($config->treeView)
{
$url = $config->getURL($rep, $fullpath, 'dir').$passRevString;
$id = anchorForPath($fullpath);
$url .= '#'.$id.'" id="'.$id;
}
else
{
$url = $config->getURL($rep, $fullpath, 'dir').$passRevString;
}
}
else
{
$url = $config->getURL($rep, $fullpath, 'file').$passRevString;
}
return removeURLSeparator($url);
}
 
$isDir = $pfile{strlen($pfile) - 1} == "/";
if ($passrev) $passrevstr = "rev=$passrev&amp;"; else $passrevstr = "";
if ($showchanged) $showchangedstr = "sc=$showchanged"; else $showchangedstr = "";
function showDirFiles($svnrep, $subs, $level, $limit, $rev, $peg, $listing, $index, $treeview = true)
{
global $config, $lang, $rep, $passrev, $peg, $passRevString;
 
if ($isDir)
{
$url = $config->getURL($rep, $ppath.$pfile, "dir");
$path = '';
 
// XHTML doesn't allow slashes in IDs ~J
$id = str_replace('/', '_', $ppath.$pfile);
$url = "<a id='$id' href=\"${url}$passrevstr$showchangedstr";
if (!$treeview)
{
$level = $limit;
}
 
$url = removeURLSeparator($url);
if ($config->treeView) $url .= "#$id";
$url .= "\">$pfile</a>";
}
else
{
$url = $config->getURL($rep, $ppath.$pfile, "file");
$url .= $passrevstr.$showchangedstr;
$url = removeURLSeparator($url);
$url = "<a href=\"${url}\">$pfile</a>";
}
// TODO: Fix node links to use the path and number of peg revision (if exists)
// This applies to file detail, log, and RSS -- leave the download link as-is
for ($n = 0; $n <= $level; $n++)
{
$path .= $subs[$n].'/';
}
 
return $url;
}
// List each file in the current directory
$loop = 0;
$last_index = 0;
$accessToThisDir = $rep->hasReadAccess($path, false);
 
function fileLinkGetFile($path, $file)
{
global $rep, $passrev, $showchanged, $config;
// If using flat view and not at the root, create a '..' entry at the top.
if (!$treeview && count($subs) > 2)
{
$parentPath = $subs;
unset($parentPath[count($parentPath) - 2]);
$parentPath = implode('/', $parentPath);
 
if ($path == "" || $path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
if ($rep->hasReadAccess($parentPath, false))
{
$listvar = &$listing[$index];
$listvar['rowparity'] = $index % 2;
$listvar['path'] = str_replace('%2F', '/', rawurlencode($parentPath));
$listvar['filetype'] = 'dir';
$listvar['filename'] = '..';
$listvar['fileurl'] = urlForPath($parentPath, $passRevString);
$listvar['filelink'] = '<a href="'.$listvar['fileurl'].'">'.$listvar['filename'].'</a>';
$listvar['level'] = 0;
$listvar['node'] = 0; // t-node
$listvar['revision'] = $rev;
$listvar['revurl'] = $config->getURL($rep, $parentPath, 'revision').'rev='.$rev.'&amp;isdir=1';
global $vars;
$listvar['date'] = $vars['date'];
$listvar['age'] = datetimeFormatDuration(time() - strtotime($vars['date']), true, true);
$index++;
}
}
 
if ($ppath{strlen($ppath)-1} != "/")
$ppath .= "/";
$openDir = false;
$logList = $svnrep->getList($path, $rev, $peg);
 
if ($file{0} == "/")
$pfile = substr($file, 1);
else
$pfile = $file;
if (!$logList)
{
return $listing;
}
 
$isDir = $pfile{strlen($pfile) - 1} == "/";
$downloadRevAndPeg = createRevAndPegString($rev, $peg ? $peg : $rev);
foreach ($logList->entries as $entry)
{
$isDir = $entry->isdir;
if (!$isDir && $level != $limit)
{
continue; // Skip any files outside the current directory
}
$file = $entry->file;
$isDirString = ($isDir) ? 'isdir=1&amp;' : '';
 
if (!$isDir)
{
$url = $config->getURL($rep, $ppath.$pfile, "file");
$url = removeURLSeparator($url);
$url = "<a href=\"${url}&getfile\">Get</a>";
}
// Only list files/directories that are not designated as off-limits
$access = ($isDir) ? $rep->hasReadAccess($path.$file, false)
: $accessToThisDir;
 
return $url;
if (!$access)
{
continue;
}
 
$listvar = &$listing[$index];
$listvar['rowparity'] = $index % 2;
 
if ($isDir)
{
$openDir = isset($subs[$level + 1]) && (!strcmp($subs[$level + 1].'/', $file) || !strcmp($subs[$level + 1], $file));
$listvar['filetype'] = ($openDir) ? 'diropen' : 'dir';
}
else
{
$openDir = false;
$listvar['filetype'] = strtolower(strrchr($file, '.'));
}
 
$listvar['isDir'] = $isDir;
$listvar['openDir'] = $openDir;
$listvar['level'] = ($treeview) ? $level : 0;
$listvar['node'] = 0; // t-node
$listvar['path'] = str_replace('%2F', '/', rawurlencode($path.$file));
$listvar['filename'] = escape($file);
 
if ($isDir)
{
$listvar['fileurl'] = urlForPath($path.$file, $passRevString);
}
else
{
$listvar['fileurl'] = urlForPath($path.$file, createDifferentRevAndPegString($passrev, $peg));
}
 
$listvar['filelink'] = '<a href="'.$listvar['fileurl'].'">'.$listvar['filename'].'</a>';
 
if ($isDir)
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.$passRevString;
}
else
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.createDifferentRevAndPegString($passrev, $peg);
}
 
if ($treeview)
{
$listvar['compare_box'] = '<input type="checkbox" name="compare[]" value="'.escape($path.$file).'@'.$passrev.'" onclick="enforceOnlyTwoChecked(this)" />';
}
 
if ($config->showLastModInListing())
{
$listvar['committime'] = $entry->committime;
$listvar['revision'] = $entry->rev;
$listvar['author'] = $entry->author;
$listvar['age'] = $entry->age;
$listvar['date'] = $entry->date;
$listvar['revurl'] = $config->getURL($rep, $path.$file, 'revision').$isDirString.createRevAndPegString($entry->rev, $peg ? $peg : $rev);
}
 
if ($rep->isDownloadAllowed($path.$file))
{
$downloadurl = $config->getURL($rep, $path.$file, 'dl').$isDirString.$downloadRevAndPeg;
 
if ($isDir)
{
$listvar['downloadurl'] = $downloadurl;
$listvar['downloadplainurl'] = '';
}
else
{
$listvar['downloadplainurl'] = $downloadurl;
$listvar['downloadurl'] = '';
}
}
else
{
$listvar['downloadplainurl'] = '';
$listvar['downloadurl'] = '';
}
 
if ($rep->isRssEnabled())
{
// RSS should always point to the latest revision, so don't include rev
$listvar['rssurl'] = $config->getURL($rep, $path.$file, 'rss').$isDirString.createRevAndPegString('', $peg);
}
 
$loop++;
$index++;
$last_index = $index;
 
if ($isDir && ($level != $limit))
{
// @todo remove the alternate check with htmlentities when assured that there are not side effects
if (isset($subs[$level + 1]) && (!strcmp($subs[$level + 1].'/', $file) || !strcmp(htmlentities($subs[$level + 1], ENT_QUOTES).'/', htmlentities($file))))
{
$listing = showDirFiles($svnrep, $subs, $level + 1, $limit, $rev, $peg, $listing, $index);
$index = count($listing);
}
}
}
 
// For an expanded tree, give the last entry an "L" node to close the grouping
if ($treeview && $last_index != 0)
{
$listing[$last_index - 1]['node'] = 1; // l-node
}
 
return $listing;
}
 
function showDirFiles($svnrep, $subs, $level, $limit, $rev, $listing, $index, $treeview = true)
function showAllDirFiles($svnrep, $path, $rev, $peg, $listing, $index, $treeView = true)
{
global $rep, $passrev, $showchanged, $config, $lang;
global $config, $lang, $rep, $passrev, $peg, $passRevString;
 
$path = "";
// List each file in the current directory
$loop = 0;
$last_index = 0;
$accessToThisDir = $rep->hasReadAccess($path, false);
 
// Explicitly requested file as attachment
if (isset($_REQUEST['getfile']))
{
$base = basename($path);
// If using flat view and not at the root, create a '..' entry at the top.
if (!$treeView && count($subs) > 2)
{
$parentPath = $subs;
unset($parentPath[count($parentPath) - 2]);
$parentPath = implode('/', $parentPath);
 
header("Content-Type: application/octet-stream");
header("Content-Length: $size");
header("Content-Disposition: inline; filename=".urlencode($base));
if ($rep->hasReadAccess($parentPath, false))
{
$listvar = &$listing[$index];
$listvar['rowparity'] = $index % 2;
$listvar['path'] = str_replace('%2F', '/', rawurlencode($parentPath));
$listvar['filetype'] = 'dir';
$listvar['filename'] = '..';
$listvar['fileurl'] = urlForPath($parentPath, $passRevString);
$listvar['filelink'] = '<a href="'.$listvar['fileurl'].'">'.$listvar['filename'].'</a>';
$listvar['level'] = 0;
$listvar['node'] = 0; // t-node
$listvar['revision'] = $rev;
$listvar['revurl'] = $config->getURL($rep, $parentPath, 'revision').'rev='.$rev.'&amp;isdir=1';
global $vars;
$listvar['date'] = $vars['date'];
$listvar['age'] = datetimeFormatDuration(time() - strtotime($vars['date']), true, true);
$index++;
}
}
 
$svnrep->getFileContents($path, "", $rev);
$openDir = false;
$logList = $svnrep->getList($path, $rev, $peg);
 
exit;
}
if (!$logList)
{
return $listing;
}
 
if (!$treeview)
$level = $limit;
$downloadRevAndPeg = createRevAndPegString($rev, $peg ? $peg : $rev);
 
for ($n = 0; $n <= $level; $n++)
{
$path .= $subs[$n]."/";
}
foreach ($logList->entries as $entry)
{
$isDir = $entry->isdir;
 
$contents = $svnrep->dirContents($path, $rev);
$file = $entry->file;
$isDirString = ($isDir) ? 'isdir=1&amp;' : '';
 
// List each file in the current directory
$loop = 0;
$last_index = 0;
$openDir = false;
$fullaccess = $rep->hasReadAccess($path, false);
foreach($contents as $file)
{
$isDir = ($file{strlen($file) - 1} == "/"?1:0);
$access = false;
// Only list files/directories that are not designated as off-limits
$access = ($isDir) ? $rep->hasReadAccess($path.$file, false)
: $accessToThisDir;
 
if ($isDir)
{
if ($rep->hasReadAccess($path.$file, true))
{
$access = true;
$openDir = (!strcmp($subs[$level+1]."/", $file) || !strcmp($subs[$level+1], $file));
if (!$access)
{
continue;
}
 
if ($openDir)
$listing[$index]["filetype"] = "diropen";
else
$listing[$index]["filetype"] = "dir";
$listvar = &$listing[$index];
$listvar['rowparity'] = $index % 2;
 
if ($rep->isDownloadAllowed($path.$file))
{
$dlurl = $config->getURL($rep, $path.$file, "dl");
$listing[$index]["fileviewdllink"] = "<a href=\"${dlurl}rev=$passrev&amp;isdir=1\">${lang["TARBALL"]}</a>";
}
else
$listing[$index]["fileviewdllink"] = "&nbsp;";
}
}
else
{
if ($fullaccess)
{
$access = true;
if ($level != $limit)
{
// List directories only, skip all files
continue;
}
$listing[$index]["fileviewdllink"] = "&nbsp;";
$listing[$index]["filetype"] = strrchr($file, ".");
}
}
if ($isDir)
{
$listvar['filetype'] = 'dir';
$openDir = true;
}
else
{
$listvar['filetype'] = strtolower(strrchr($file, '.'));
$openDir = false;
}
 
if ($access)
{
$listing[$index]["rowparity"] = ($index % 2)?"L1":"L0";
if ($treeview)
$listing[$index]["compare_box"] = "<input type=\"checkbox\" name=\"compare[]\" value=\"".fileLink($path, $file, true)."@$passrev\" onclick=\"checkCB(this)\" />";
else
$listing[$index]["compare_box"] = "";
$listvar['isDir'] = $isDir;
$listvar['openDir'] = $openDir;
$listvar['path'] = str_replace('%2F', '/', rawurlencode($path.$file));
$tempelements = explode('/',$file);
 
if ($openDir)
$listing[$index]["filelink"] = "<b>".fileLink($path, $file)."</b>";
else
$listing[$index]["filelink"] = fileLink($path, $file);
if ($tempelements[count($tempelements)-1] === "")
{
$lastindexfile = count($tempelements)-1 - 1;
$listvar['node'] = $lastindexfile; // t-node
$listvar['level'] = ($treeView) ? $lastindexfile : 0;
$listvar['filename'] = escape($tempelements[$lastindexfile]);
$listvar['classname'] = '';
 
if ($isDir)
$listing[$index]["filelinkgetfile"] = "";
else
$listing[$index]["filelinkgetfile"] = fileLinkGetFile($path, $file);
for ($n = 0; $n < $lastindexfile; ++$n)
{
$listvar['last_i_node'][$n] = false;
$listvar['classname'] = $listvar['classname'].$tempelements[$n].'/';
}
 
// The history command doesn't return with a trailing slash. We need to remember here if the
// file is a directory or not!
$listvar['classname'] = $listvar['classname'].$tempelements[$lastindexfile];
$listvar['last_i_node'][$lastindexfile] = true;
}
else
{
$lastindexfile = count($tempelements)-1;
$listvar['node'] = $lastindexfile; // t-node
$listvar['level'] = ($treeView) ? $lastindexfile : 0;
$listvar['filename'] = escape($tempelements[$lastindexfile]);
$listvar['classname'] = '';
 
$listing[$index]["isDir"] = $isDir;
for ($n=0; $n < $lastindexfile; ++$n)
{
$listvar['last_i_node'][$n] = false;
$listvar['classname'] = $listvar['classname'].$tempelements[$n].'/';
}
 
if ($treeview)
$listing[$index]["level"] = $level;
else
$listing[$index]["level"] = 0;
$listvar['last_i_node'][$lastindexfile] = true;
}
 
$listing[$index]["node"] = 0; // t-node
if ($isDir)
{
$listvar['fileurl'] = urlForPath($path.$file, $passRevString);
}
else
{
$listvar['fileurl'] = urlForPath($path.$file, createDifferentRevAndPegString($passrev, $peg));
}
 
$fileurl = $config->getURL($rep, $path.$file, "log");
$listing[$index]["fileviewloglink"] = "<a href=\"${fileurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=$isDir\">${lang["VIEWLOG"]}</a>";
$listvar['filelink'] = '<a href="'.$listvar['fileurl'].'">'.$listvar['filename'].'</a>';
 
$rssurl = $config->getURL($rep, $path.$file, "rss");
if ($rep->getHideRss())
{
$listing[$index]["rsslink"] = "<a href=\"${rssurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=$isDir\">${lang["RSSFEED"]}</a>";
$listing[$index]["rssanchor"] = "<a href=\"${rssurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=$isDir\">";
}
if ($isDir)
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.$passRevString;
}
else
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.createDifferentRevAndPegString($passrev, $peg);
}
 
$index++;
$loop++;
$last_index = $index;
if ($treeView)
{
$listvar['compare_box'] = '<input type="checkbox" name="compare[]" value="'.escape($path.$file).'@'.$passrev.'" onclick="enforceOnlyTwoChecked(this)" />';
}
 
if (($level != $limit) && ($isDir))
{
if (!strcmp($subs[$level + 1]."/", $file))
{
$listing = showDirFiles($svnrep, $subs, $level + 1, $limit, $rev, $listing, $index);
$index = count($listing);
}
}
if ($config->showLastModInListing())
{
$listvar['committime'] = $entry->committime;
$listvar['revision'] = $entry->rev;
$listvar['author'] = $entry->author;
$listvar['age'] = $entry->age;
$listvar['date'] = $entry->date;
$listvar['revurl'] = $config->getURL($rep, $path.$file, 'revision').$isDirString.createRevAndPegString($entry->rev, $peg ? $peg : $rev);
}
 
}
}
if ($rep->isDownloadAllowed($path.$file))
{
$downloadurl = $config->getURL($rep, $path.$file, 'dl').$isDirString.$downloadRevAndPeg;
 
if ($last_index != 0 && $treeview)
{
$listing[$last_index - 1]["node"] = 1; // l-node
}
if ($isDir)
{
$listvar['downloadurl'] = $downloadurl;
$listvar['downloadplainurl'] = '';
}
else
{
$listvar['downloadplainurl'] = $downloadurl;
$listvar['downloadurl'] = '';
}
}
else
{
$listvar['downloadplainurl'] = '';
$listvar['downloadurl'] = '';
}
 
return $listing;
if ($rep->isRssEnabled())
{
// RSS should always point to the latest revision, so don't include rev
$listvar['rssurl'] = $config->getURL($rep, $path.$file, 'rss').$isDirString.createRevAndPegString('', $peg);
}
 
$loop++;
$index++;
$last_index = $index;
}
 
return $listing;
}
 
function showTreeDir($svnrep, $path, $rev, $listing)
function showTreeDir($svnrep, $path, $rev, $peg, $listing)
{
global $vars, $config;
global $vars, $config;
 
$subs = explode("/", $path);
if ($config->showLoadAllRepos())
{
$vars['compare_box'] = ''; // Set blank once in case tree view is not enabled.
return showAllDirFiles($svnrep, $path, $rev, $peg, $listing, 0, $config->treeView);
}
 
// For directory, the last element in the subs is empty.
// For file, the last element in the subs is the file name.
// Therefore, it is always count($subs) - 2
$limit = count($subs) - 2;
$subs = explode('/', $path);
 
for ($n = 0; $n < $limit; $n++)
{
$vars["last_i_node"][$n] = FALSE;
}
// The last element in "$subs" is empty for directories, some file name for files, but ALWAYS
// exists as an additional element. Hence, "-2" is necessary.
//
// Additionally, level and limit are conceptually different things, first to e.g. start access
// checks FROM, latter to process UNTIL. So don't merge those values too easily, especially as
// both values needed to be different in some environments in the past for some unkown reason.
//
// https://github.com/websvnphp/websvn/issues/146#issuecomment-913353366
$limit = count($subs) - 2;
$level = $limit;
$level = $level <= 0 ? 0 : $level;
 
return showDirFiles($svnrep, $subs, 0, $limit, $rev, $listing, 0, $config->treeView);
for ($n = 0; $n < $limit; $n++)
{
$vars['last_i_node'][$n] = false;
}
 
$vars['compare_box'] = ''; // Set blank once in case tree view is not enabled.
return showDirFiles($svnrep, $subs, $level, $limit, $rev, $peg, $listing, 0, $config->treeView);
}
 
// Make sure that we have a repository
if (!isset($rep))
if (!$rep)
{
echo $lang["NOREP"];
exit;
renderTemplate404('directory','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
// Revision info to pass along chain
$passrev = $rev;
if (!empty($rev))
{
$info = $svnrep->getInfo($path, $rev, $peg);
 
// Get the directory contents of the given revision, or HEAD if not defined
$contents = $svnrep->dirContents($path, @$rev);
if ($info)
{
$path = $info->path;
$peg = (int)$info->rev;
}
}
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, "", "", false);
$history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg);
 
if (!empty($history->entries[0]))
$youngest = $history->entries[0]->rev;
else
$youngest = -1;
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg);
 
if (!$history)
{
renderTemplate404('directory','NOPATH');
}
}
 
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : 0;
 
// Unless otherwise specified, we get the log details of the latest change
if (empty($rev))
$logrev = $youngest;
else
$logrev = $rev;
$lastChangedRev = ($passrev) ? $passrev : $youngest;
 
if ($logrev != $youngest)
if ($lastChangedRev != $youngest)
{
$logEntry = $svnrep->getLog($path, $logrev, $logrev, false);
$logEntry = $logEntry->entries[0];
$history = $svnrep->getLog($path, $lastChangedRev, 1, false, 2, $peg);
}
else
$logEntry = $history->entries[0];
 
$headlog = $svnrep->getLog("/", "", "", true, 1);
$headrev = $headlog->entries[0]->rev;
$logEntry = ($history && isset($history->entries[0])) ? $history->entries[0] : 0;
 
$headlog = $svnrep->getLog('/', '', '', true, 1);
$headrev = ($headlog && isset($headlog->entries[0])) ? $headlog->entries[0]->rev : 0;
 
// If we're not looking at a specific revision, get the HEAD revision number
// (the revision of the rest of the tree display)
 
if (empty($rev))
{
$rev = $headrev;
$rev = $headrev;
}
 
if ($path == "" || $path{0} != "/")
$ppath = "/".$path;
if ($path == '' || $path[0] != '/')
{
$ppath = '/'.$path;
}
else
$ppath = $path;
{
$ppath = $path;
}
 
$vars["repname"] = $rep->getDisplayName();
createPathLinks($rep, $ppath, $passrev, $peg);
$passRevString = createRevAndPegString($passrev, $peg);
$isDirString = 'isdir=1&amp;';
 
$dirurl = $config->getURL($rep, $path, "dir");
$logurl = $config->getURL($rep, $path, "log");
$rssurl = $config->getURL($rep, $path, "rss");
$dlurl = $config->getURL($rep, $path, "dl");
$compurl = $config->getURL($rep, "/", "comp");
$revurl = $config->getURL($rep, $path != '/' ? $path : '', 'dir');
$revurlSuffix = $path != '/' ? '#'.anchorForPath($path) : '';
 
if ($passrev != 0 && $passrev != $headrev && $youngest != -1)
$vars["goyoungestlink"] = "<a href=\"${dirurl}opt=dir&amp;sc=1\">${lang["GOYOUNGEST"]}</a>";
else
$vars["goyoungestlink"] = "";
if ($rev < $youngest)
{
if ($path == '/')
{
$vars['goyoungesturl'] = $config->getURL($rep, '', 'dir');
}
else
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'dir').createRevAndPegString($youngest, $peg ? $peg: $rev).$revurlSuffix;
}
 
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
 
$vars["action"] = "";
$vars["rev"] = $rev;
$vars["path"] = $ppath;
$vars["lastchangedrev"] = $logrev;
$vars["date"] = $logEntry->date;
$vars["author"] = $logEntry->author;
$vars["log"] = nl2br($bugtraq->replaceIDs(create_anchors($logEntry->msg)));
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg);
 
if (!$showchanged)
{
$vars["showchangeslink"] = "<a href=\"${dirurl}rev=$passrev&amp;sc=1\">${lang["SHOWCHANGED"]}</a>";
$vars["hidechangeslink"] = "";
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$revurlSuffix;
}
}
 
$vars["hidechanges"] = true;
$vars["showchanges"] = false;
unset($vars['error']);
}
else
 
if (isset($history->entries[1]))
{
$vars["showchangeslink"] = "";
$changes = $logEntry->mods;
$firstAdded = true;
$firstModded = true;
$firstDeleted = true;
$prevRev = $history->entries[1]->rev;
$prevPath = $history->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$revurlSuffix;
}
 
$vars["newfilesbr"] = "";
$vars["newfiles"] = "";
$vars["changedfilesbr"] = "";
$vars["changedfiles"] = "";
$vars["deletedfilesbr"] = "";
$vars["deletedfiles"] = "";
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
 
foreach ($changes as $file)
{
switch ($file->action)
{
case "A":
if (!$firstAdded) $vars["newfilesbr"] .= "<br />";
$firstAdded = false;
$vars["newfilesbr"] .= fileLink("", $file->path);
$vars["newfiles"] .= " ".fileLink("", $file->path);
break;
$vars['action'] = '';
$vars['rev'] = $rev;
$vars['peg'] = $peg;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
$vars['lastchangedrev'] = $lastChangedRev;
 
case "M":
if (!$firstModded) $vars["changedfilesbr"] .= "<br />";
$firstModded = false;
$vars["changedfilesbr"] .= fileLink("", $file->path);
$vars["changedfiles"] .= " ".fileLink("", $file->path);
break;
if ($logEntry)
{
$vars['date'] = $logEntry->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date));
$vars['author'] = $logEntry->author;
$vars['log'] = nl2br($bugtraq->replaceIDs(create_anchors(xml_entities($logEntry->msg))));
}
 
case "D":
if (!$firstDeleted) $vars["deletedfilesbr"] .= "<br />";
$firstDeleted = false;
$vars["deletedfilesbr"] .= $file->path;
$vars["deletedfiles"] .= " ".$file->path;
break;
}
}
$vars['revurl'] = $config->getURL($rep, ($path == '/' ? '' : $path), 'revision').$isDirString.$passRevString;
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
 
$vars["hidechangeslink"] = "<a href=\"${dirurl}rev=$passrev&amp;sc=0\">${lang["HIDECHANGED"]}</a>";
if ($history && count($history->entries) > 1)
{
$vars['compareurl'] = $config->getURL($rep, '', 'comp').'compare[]='.rawurlencode($history->entries[1]->path).'@'.$history->entries[1]->rev. '&amp;compare[]='.rawurlencode($history->entries[0]->path).'@'.$history->entries[0]->rev;
$vars['comparelink'] = '<a href="'.$vars['compareurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
$vars["hidechanges"] = false;
$vars["showchanges"] = true;
$vars['logurl'] = $config->getURL($rep, $path, 'log').$isDirString.$passRevString;
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').$isDirString.createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
createDirLinks($rep, $ppath, $passrev, $showchanged);
$vars["curdirloglink"] = "<a href=\"${logurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=1\">${lang["VIEWLOG"]}</a>";
// Set up the tarball link
$subs = explode('/', $path);
$level = count($subs) - 2;
 
if ($rev != $headrev)
if ($rep->isDownloadAllowed($path) && !isset($vars['warning']))
{
$history = $svnrep->getLog($path, $rev, "", false);
$vars['downloadurl'] = $config->getURL($rep, $path, 'dl').$isDirString.$passRevString;
}
 
if (isset($history->entries[1]->rev))
$vars['compare_form'] = '<form method="get" action="'.$config->getURL($rep, '', 'comp').'" id="compare">';
 
if ($config->multiViews)
{
$vars["curdircomplink"] = "<a href=\"${compurl}compare[]=".
urlencode($history->entries[1]->path)."@".$history->entries[1]->rev.
"&amp;compare[]=".urlencode($history->entries[0]->path)."@".$history->entries[0]->rev.
"\">${lang["DIFFPREV"]}</a>";
$vars['compare_form'] .= '<input type="hidden" name="op" value="comp"/>';
}
else
{
$vars["curdircomplink"] = "";
}
 
if ($rep->getHideRss())
{
$vars["curdirrsslink"] = "<a href=\"${rssurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=1\">${lang["RSSFEED"]}</a>";
$vars["curdirrsshref"] = "${rssurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=1";
$vars["curdirrssanchor"] = "<a href=\"${rssurl}rev=$passrev&amp;sc=$showchanged&amp;isdir=1\">";
$vars['compare_form'] .= '<input type="hidden" name="repname" value="'.$repname.'" />';
}
 
// Set up the tarball link
$vars['compare_submit'] = '<input type="submit" value="'.$lang['COMPAREPATHS'].'" />';
$vars['compare_endform'] = '</form>';
 
$subs = explode("/", $path);
$level = count($subs) - 2;
if ($rep->isDownloadAllowed($path))
$vars["curdirdllink"] = "<a href=\"${dlurl}rev=$passrev&amp;isdir=1\">${lang["TARBALL"]}</a>";
else
$vars["curdirdllink"] = "";
$url = $config->getURL($rep, "/", "comp");
$vars['showlastmod'] = $config->showLastModInListing();
 
$vars["compare_form"] = "<form action=\"$url\" method=\"post\" name=\"compareform\">";
$vars["compare_submit"] = "<input name=\"comparesubmit\" type=\"submit\" value=\"${lang["COMPAREPATHS"]}\" />";
$vars["compare_endform"] = "<input type=\"hidden\" name=\"op\" value=\"comp\" /><input type=\"hidden\" name=\"sc\" value=\"$showchanged\" /></form>";
$vars['loadalldir'] = $config->showLoadAllRepos();
$listing = showTreeDir($svnrep, $path, $rev, $peg, array());
 
$listing = array();
$listing = showTreeDir($svnrep, $path, $rev, $listing);
if (!$rep->hasReadAccess($path))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
$vars["version"] = $version;
 
if (!$rep->hasReadAccess($path, true))
$vars["noaccess"] = true;
 
if (!$rep->hasReadAccess($path, false))
$vars["restricted"] = true;
 
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."directory.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
 
?>
$vars['restricted'] = !$rep->hasReadAccess($path, false);
renderTemplate('directory', $path);
/WebSVN/log.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
24,310 → 22,537
//
// Show the logs for the given path
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
require_once("include/bugtraq.inc");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
require_once 'include/bugtraq.php';
 
$page = (int)@$_REQUEST["page"];
$all = (@$_REQUEST["all"] == 1)?1:0;
$isDir = (@$_REQUEST["isdir"] == 1)?1:0;
$dosearch = (@$_REQUEST["logsearch"] == 1)?1:0;
$search = trim(@$_REQUEST["search"]);
$page = (int)@$_REQUEST['page'];
$all = @$_REQUEST['all'] == 1;
$isDir = @$_REQUEST['isdir'] == 1 || $path == '' || $path == '/';
 
// Make sure that we have a repository
if (!$rep)
{
renderTemplate404('log','NOREP');
}
 
if (isset($_REQUEST['showchanges']))
{
$showchanges = @$_REQUEST['showchanges'] == 1;
}
else
{
$showchanges = $rep->logsShowChanges();
}
 
$search = trim((string) @$_REQUEST['search']);
$dosearch = strlen($search) > 0;
 
$words = preg_split('#\s+#', $search);
$fromRev = (int)@$_REQUEST["fr"];
$startrev = strtoupper(trim(@$_REQUEST["sr"]));
$endrev = strtoupper(trim(@$_REQUEST["er"]));
$max = @$_REQUEST["max"];
$fromRev = (int)@$_REQUEST['fr'];
$startrev = strtoupper(trim((string) @$_REQUEST['sr']));
$endrev = strtoupper(trim((string) @$_REQUEST['er']));
$max = isset($_REQUEST['max']) ? (int)$_REQUEST['max'] : false;
 
// Max number of results to find at a time
$numSearchResults = 15;
$numSearchResults = 20;
 
if ($search == "")
$dosearch = false;
if ($search == '')
{
$dosearch = false;
}
 
// removeAccents
//
// Remove all the accents from a string. This function doesn't seem
// Remove all the accents from a string. This function doesn't seem
// ideal, but expecting everyone to install 'unac' seems a little
// excessive as well...
 
function removeAccents($string)
{
return strtr($string,
"ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ",
"AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn");
}
function removeAccents($string)
{
$string = htmlentities($string, ENT_QUOTES, 'ISO-8859-1');
$string = preg_replace('/&([A-Za-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron);/', '$1', $string);
return $string;
}
 
// Normalise the search words
foreach ($words as $index => $word)
foreach ($words as $index => $word)
{
$words[$index] = strtolower(removeAccents($word));
// Remove empty string introduced by multiple spaces
if (empty($words[$index]))
unset($words[$index]);
$words[$index] = strtolower(removeAccents($word));
 
// Remove empty string introduced by multiple spaces
if (empty($words[$index]))
unset($words[$index]);
}
 
if (empty($page)) $page = 1;
if (empty($page))
{
$page = 1;
}
 
// If searching, display all the results
$all = (bool) $dosearch;
if ($dosearch)
{
$all = true;
}
 
$maxperpage = 20;
 
// Make sure that we have a repository
if (!isset($rep))
$svnrep = new SVNRepository($rep);
 
$history = $svnrep->getLog($path, 'HEAD', '', false, 1, ($path == '/') ? '' : $peg);
 
if (!$history)
{
echo $lang["NOREP"];
exit;
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', false, 1, ($path == '/') ? '' : $peg);
 
if (!$history)
{
renderTemplate404('log','NOPATH');
}
}
 
$svnrep = new SVNRepository($rep);
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : 0;
 
$passrev = $rev;
if (empty($startrev))
{
//$startrev = ($rev) ? $rev : 'HEAD';
$startrev = $rev;
}
else if ($startrev != 'HEAD' && $startrev != 'BASE' && $startrev != 'PREV' && $startrev != 'COMMITTED')
{
$startrev = (int)$startrev;
}
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, "", "", true);
$youngest = $history->entries[0]->rev;
if (empty($endrev))
{
$endrev = 1;
}
else if ($endrev != 'HEAD' && $endrev != 'BASE' && $endrev != 'PREV' && $endrev != 'COMMITTED')
{
$endrev = (int)$endrev;
}
 
if (empty($rev))
$rev = $youngest;
if (empty($rev))
{
$rev = $youngest;
}
 
if (empty($startrev))
{
$startrev = $rev;
}
 
// make sure path is prefixed by a /
$ppath = $path;
if ($path == "" || $path{0} != "/")
$ppath = "/".$path;
 
$vars["action"] = $lang["LOG"];
$vars["repname"] = $rep->getDisplayName();
$vars["rev"] = $rev;
$vars["path"] = $ppath;
if ($path == '' || $path[0] != '/')
{
$ppath = '/'.$path;
}
 
createDirLinks($rep, $ppath, $passrev, $showchanged);
$vars['action'] = $lang['LOG'];
$vars['rev'] = $rev;
$vars['peg'] = $peg;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
 
$logurl = $config->getURL($rep, $path, "log");
if ($history && isset($history->entries[0]))
{
$vars['log'] = xml_entities($history->entries[0]->msg);
$vars['date'] = $history->entries[0]->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
$vars['author'] = $history->entries[0]->author;
}
 
if ($rev != $youngest)
$vars["goyoungestlink"] = "<a href=\"${logurl}sc=1\">${lang["GOYOUNGEST"]}</a>";
if ($max === false)
{
$max = ($dosearch) ? 0 : 40;
}
else if ($max < 0)
{
$max = 40;
}
 
// TODO: If the rev is less than the head, get the path (may have been renamed!)
// Will probably need to call `svn info`, parse XML output, and substring a path
 
createPathLinks($rep, $ppath, $passrev, $peg);
$passRevString = createRevAndPegString($rev, $peg);
$isDirString = ($isDir) ? 'isdir=1&amp;' : '';
 
unset($queryParams['repname']);
unset($queryParams['path']);
 
// Toggle 'showchanges' param for link to switch from the current behavior
if ($showchanges == $rep->logsShowChanges())
{
$queryParams['showchanges'] = (int)!$showchanges;
}
else
$vars["goyoungestlink"] = "";
{
unset($queryParams['showchanges']);
}
 
$vars['changesurl'] = $config->getURL($rep, $path, 'log').buildQuery($queryParams);
$vars['changeslink'] = '<a href="'.$vars['changesurl'].'">'.$lang[($showchanges ? 'HIDECHANGED' : 'SHOWCHANGED')].'</a>';
$vars['showchanges'] = $showchanges;
 
// Revert 'showchanges' param to propagate the current behavior
if ($showchanges == $rep->logsShowChanges())
{
unset($queryParams['showchanges']);
}
else
{
$queryParams['showchanges'] = (int)$showchanges;
}
 
$vars['revurl'] = $config->getURL($rep, $path, 'revision').$isDirString.$passRevString;
 
if ($isDir)
{
$vars['directoryurl'] = $config->getURL($rep, $path, 'dir').$passRevString.'#'.anchorForPath($path);
$vars['directorylink'] = '<a href="'.$vars['directoryurl'].'">'.$lang['LISTING'].'</a>';
}
else
{
$vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
$vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
 
$vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
$vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
 
$vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString;
$vars['difflink'] = '<a href="'.$vars['diffurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').$isDirString.createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
if ($rev != $youngest)
{
if ($path == '/')
{
$vars['goyoungesturl'] = $config->getURL($rep, '', 'log').$isDirString;
}
else
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'log').$isDirString.'peg='.($peg ? $peg : $rev);
}
 
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
}
 
// We get the bugtraq variable just once based on the HEAD
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
 
if ($startrev != "HEAD") $startrev = (int)$startrev;
if (empty($startrev)) $startrev = $rev;
if (empty($endrev)) $endrev = 1;
$vars['logsearch_moreresultslink'] = '';
$vars['pagelinks'] = '';
$vars['showalllink'] = '';
 
if (empty($_REQUEST["max"]))
if ($history)
{
if (empty($_REQUEST["logsearch"]))
$max = 30;
else
$max = 0;
$history = $svnrep->getLog($path, $startrev, $endrev, true, $max, $peg);
 
if (empty($history))
{
unset($vars['error']);
$vars['warning'] = 'Revision '.$startrev.' of this resource does not exist.';
}
}
else
 
if (!empty($history))
{
$max = (int)$max;
if ($max < 0) $max = 30;
// Get the number of separate revisions
$revisions = count($history->entries);
 
if ($all)
{
$firstrevindex = 0;
$lastrevindex = $revisions - 1;
$pages = 1;
}
else
{
// Calculate the number of pages
$pages = floor($revisions / $maxperpage);
if (($revisions % $maxperpage) > 0) $pages++;
 
if ($page > $pages) $page = $pages;
 
// Work out where to start and stop
$firstrevindex = ($page - 1) * $maxperpage;
$lastrevindex = min($firstrevindex + $maxperpage - 1, $revisions - 1);
}
 
$frev = isset($history->entries[0]) ? $history->entries[0]->rev : false;
$brev = isset($history->entries[$firstrevindex]) ? $history->entries[$firstrevindex]->rev : false;
$erev = isset($history->entries[$lastrevindex]) ? $history->entries[$lastrevindex]->rev : false;
 
$entries = array();
 
if ($brev && $erev)
{
$history = $svnrep->getLog($path, $brev, $erev, false, 0, $peg, true);
if ($history)
{
$entries = $history->entries;
}
}
 
$row = 0;
$index = 0;
$found = false;
 
foreach ($entries as $revision)
{
// Assume a good match
$match = true;
$thisrev = $revision->rev;
 
// Check the log for the search words, if searching
if ($dosearch)
{
if ((empty($fromRev) || $fromRev > $thisrev))
{
// Turn all the HTML entities into real characters.
 
// Make sure that each word in the search in also in the log
foreach ($words as $word)
{
if (strpos(strtolower(removeAccents($revision->msg)), $word) === false && strpos(strtolower(removeAccents($revision->author)), $word) === false)
{
$match = false;
break;
}
}
 
if ($match)
{
$numSearchResults--;
$found = true;
}
}
else
{
$match = false;
}
}
 
$thisRevString = createRevAndPegString($thisrev, ($peg ? $peg : $thisrev));
 
if ($match)
{
// Add the trailing slash if we need to (svnlook history doesn't return trailing slashes!)
$rpath = $revision->path;
 
if (empty($rpath))
{
$rpath = '/';
}
else if ($isDir && $rpath[strlen($rpath) - 1] != '/')
{
$rpath .= '/';
}
 
$precisePath = $revision->precisePath;
if (empty($precisePath))
{
$precisePath = '/';
}
else if ($isDir && $precisePath[strlen($precisePath) - 1] != '/')
{
$precisePath .= '/';
}
 
// Find the parent path (or the whole path if it's already a directory)
$pos = strrpos($rpath, '/');
$parent = substr($rpath, 0, $pos + 1);
 
$compareValue = (($isDir) ? $parent : $rpath).'@'.$thisrev;
 
$listvar = &$listing[$index];
$listvar['compare_box'] = '<input type="checkbox" name="compare[]" value="'.$compareValue.'" onclick="enforceOnlyTwoChecked(this)" />';
$url = $config->getURL($rep, $rpath, 'revision').$thisRevString;
$listvar['revlink'] = '<a href="'.$url.'">'.$thisrev.'</a>';
 
$url = $config->getURL($rep, $precisePath, ($isDir ? 'dir' : 'file')).$thisRevString;
 
$listvar['revpathlink'] = '<a href="'.$url.'">'.escape($precisePath).'</a>';
$listvar['revpath'] = escape($precisePath);
$listvar['revauthor'] = $revision->author;
$listvar['revdate'] = $revision->date;
$listvar['revage'] = $revision->age;
$listvar['revlog'] = nl2br($bugtraq->replaceIDs(create_anchors(xml_entities($revision->msg))));
$listvar['rowparity'] = $row;
$listvar['compareurl'] = $config->getURL($rep, '', 'comp').'compare[]='.urlencode($rpath).'@'.($thisrev - 1).'&amp;compare[]='.urlencode($rpath).'@'.$thisrev;
 
if ($showchanges)
{
// Aggregate added/deleted/modified paths for display in table
$modpaths = array();
 
foreach ($revision->mods as $mod)
{
$modpaths[$mod->action][] = $mod->path;
}
 
ksort($modpaths);
 
foreach ($modpaths as $action => $paths)
{
sort($paths);
$modpaths[$action] = $paths;
}
 
$listvar['revadded'] = (isset($modpaths['A'])) ? implode('<br/>', escape($modpaths['A'])) : '';
$listvar['revdeleted'] = (isset($modpaths['D'])) ? implode('<br/>', escape($modpaths['D'])) : '';
$listvar['revmodified'] = (isset($modpaths['M'])) ? implode('<br/>', escape($modpaths['M'])) : '';
}
 
$row = 1 - $row;
$index++;
}
 
// If we've reached the search limit, stop here...
if (!$numSearchResults)
{
$url = $config->getURL($rep, $path, 'log').$isDirString.$thisRevString;
$vars['logsearch_moreresultslink'] = '<a href="'.$url.'&amp;search='.$search.'&amp;fr='.$thisrev.'">'.$lang['MORERESULTS'].'</a>';
break;
}
}
 
$vars['logsearch_resultsfound'] = true;
 
if ($dosearch && !$found)
{
if ($fromRev == 0)
{
$vars['logsearch_nomatches'] = true;
$vars['logsearch_resultsfound'] = false;
}
else
{
$vars['logsearch_nomorematches'] = true;
}
}
else if ($dosearch && $numSearchResults > 0)
{
$vars['logsearch_nomorematches'] = true;
}
 
// Work out the paging options, create links to pages of results
if ($pages > 1)
{
$prev = $page - 1;
$next = $page + 1;
 
unset($queryParams['page']);
$logurl = $config->getURL($rep, $path, 'log').buildQuery($queryParams);
 
if ($page > 1)
{
$vars['pagelinks'] .= '<a href="'.$logurl.(!$peg && $frev && $prev != 1 ? '&amp;peg='.$frev : '').'&amp;page='.$prev.'">&larr;'.$lang['PREV'].'</a>';
}
else
{
$vars['pagelinks'] .= '<span>&larr;'.$lang['PREV'].'</span>';
}
 
for ($p = 1; $p <= $pages; $p++)
{
if ($p != $page)
{
$vars['pagelinks'] .= '<a href="'.$logurl.(!$peg && $frev && $p != 1 ? '&amp;peg='.$frev : '').'&amp;page='.$p.'">'.$p.'</a>';
}
else
{
$vars['pagelinks'] .= '<span id="curpage">'.$p.'</span>';
}
}
 
if ($page < $pages)
{
$vars['pagelinks'] .= '<a href="'.$logurl.(!$peg && $frev ? '&amp;peg='.$frev : '').'&amp;page='.$next.'">'.$lang['NEXT'].'&rarr;</a>';
}
else
{
$vars['pagelinks'] .= '<span>'.$lang['NEXT'].'&rarr;</span>';
}
 
$vars['showalllink'] = '<a href="'.$logurl.'&amp;all=1">'.$lang['SHOWALL'].'</a>';
}
}
 
$history = $svnrep->getLog($path, $startrev, $endrev, true, $max);
$vars["logsearch_moreresultslink"] = "";
$vars["pagelinks"] = "";
$vars["showalllink"] = "";
$listing = array();
// Create form elements for filtering and searching log messages
if ($config->multiViews)
{
$hidden = '<input type="hidden" name="op" value="log" />';
}
else
{
$hidden = '<input type="hidden" name="repname" value="'.$repname.'" />';
$hidden .= '<input type="hidden" name="path" value="'.$path.'" />';
}
 
if (!empty($history))
if ($isDir)
{
// Get the number of separate revisions
$revisions = count($history->entries);
if ($all)
{
$firstrevindex = 0;
$lastrevindex = $revisions - 1;
$pages = 1;
}
else
{
// Calculate the number of pages
$pages = floor($revisions / $maxperpage);
if (($revisions % $maxperpage) > 0) $pages++;
if ($page > $pages) $page = $pages;
// Word out where to start and stop
$firstrevindex = ($page - 1) * $maxperpage;
$lastrevindex = $firstrevindex + $maxperpage - 1;
if ($lastrevindex > $revisions - 1) $lastrevindex = $revisions - 1;
}
$history = $svnrep->getLog($path, $history->entries[$firstrevindex ]->rev, $history->entries[$lastrevindex]->rev, false, 0);
$row = 0;
$index = 0;
$listing = array();
$found = false;
foreach ($history->entries as $r)
{
// Assume a good match
$match = true;
$thisrev = $r->rev;
// Check the log for the search words, if searching
if ($dosearch)
{
if ((empty($fromRev) || $fromRev > $thisrev))
{
// Turn all the HTML entities into real characters.
// Make sure that each word in the search in also in the log
foreach($words as $word)
{
if (strpos(strtolower(removeAccents($r->msg)), $word) === false)
{
$match = false;
break;
}
}
if ($match)
{
$numSearchResults--;
$found = true;
}
}
else
$match = false;
}
if ($match)
{
// Add the trailing slash if we need to (svnlook history doesn't return trailing slashes!)
$rpath = $r->path;
if (empty($rpath))
$rpath = "/";
else if ($isDir && $rpath{strlen($rpath) - 1} != "/")
$rpath .= "/";
// Find the parent path (or the whole path if it's already a directory)
$pos = strrpos($rpath, "/");
$parent = substr($rpath, 0, $pos + 1);
$url = $config->getURL($rep, $parent, "dir");
$listing[$index]["revlink"] = "<a href=\"${url}rev=$thisrev&amp;sc=1\">$thisrev</a>";
if ($isDir)
{
$listing[$index]["compare_box"] = "<input type=\"checkbox\" name=\"compare[]\" value=\"$parent@$thisrev\" onclick=\"checkCB(this)\" />";
$url = $config->getURL($rep, $rpath, "dir");
$listing[$index]["revpathlink"] = "<a href=\"${url}rev=$thisrev&amp;sc=$showchanged\">$rpath</a>";
}
else
{
$listing[$index]["compare_box"] = "<input type=\"checkbox\" name=\"compare[]\" value=\"$rpath@$thisrev\" onclick=\"checkCB(this)\" />";
$url = $config->getURL($rep, $rpath, "file");
$listing[$index]["revpathlink"] = "<a href=\"${url}rev=$thisrev&amp;sc=$showchanged\">$rpath</a>";
}
$listing[$index]["revauthor"] = $r->author;
$listing[$index]["revage"] = $r->age;
$listing[$index]["revlog"] = nl2br($bugtraq->replaceIDs(create_anchors($r->msg)));
$listing[$index]["rowparity"] = "$row";
$row = 1 - $row;
$index++;
}
// If we've reached the search limit, stop here...
if (!$numSearchResults)
{
$url = $config->getURL($rep, $path, "log");
$vars["logsearch_moreresultslink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;isdir=$isDir&amp;logsearch=1&amp;search=$search&amp;fr=$thisrev\">${lang["MORERESULTS"]}</a>";
break;
}
}
$vars["logsearch_resultsfound"] = true;
if ($dosearch && !$found)
{
if ($fromRev == 0)
{
$vars["logsearch_nomatches"] = true;
$vars["logsearch_resultsfound"] = false;
}
else
$vars["logsearch_nomorematches"] = true;
}
else if ($dosearch && $numSearchResults > 0)
{
$vars["logsearch_nomorematches"] = true;
}
// Work out the paging options
if ($pages > 1)
{
$prev = $page - 1;
$next = $page + 1;
echo "<p><center>";
if ($page > 1) $vars["pagelinks"] .= "<a href=\"${logurl}rev=$rev&amp;sr=$startrev&amp;er=$endrev&amp;sc=$showchanged&amp;max=$max&amp;page=$prev\"><&nbsp;${lang["PREV"]}</a> ";
for ($p = 1; $p <= $pages; $p++)
{
if ($p != $page)
$vars["pagelinks"].= "<a href=\"${logurl}rev=$rev&amp;sr=$startrev&amp;er=$endrev&amp;sc=$showchanged&amp;max=$max&amp;page=$p\">$p</a> ";
else
$vars["pagelinks"] .= "<b>$p </b>";
}
if ($page < $pages) $vars["pagelinks"] .=" <a href=\"${logurl}rev=$rev&amp;sr=$startrev&amp;er=$endrev&amp;sc=$showchanged&amp;max=$max&amp;page=$next\">${lang["NEXT"]}&nbsp;></a>";
$vars["showalllink"] = "<a href=\"${logurl}rev=$rev&amp;sr=$startrev&amp;er=$endrev&amp;sc=$showchanged&amp;all=1&amp;max=$max\">${lang["SHOWALL"]}</a>";
echo "</center>";
}
$hidden .= '<input type="hidden" name="isdir" value="'.$isDir.'" />';
}
 
// Create the project change combo box
$url = $config->getURL($rep, $path, "log");
# XXX: forms don't have the name attribute, but _everything_ has the id attribute,
# so what you're trying to do (if anything?) should be done via that ~J
$vars["logsearch_form"] = "<form action=\"$url\" method=\"post\" name=\"logsearchform\">";
if ($peg)
{
$hidden .= '<input type="hidden" name="peg" value="'.$peg.'" />';
}
 
$vars["logsearch_startbox"] = "<input name=\"sr\" size=\"5\" value=\"$startrev\" />";
$vars["logsearch_endbox" ] = "<input name=\"er\" size=\"5\" value=\"$endrev\" />";
$vars["logsearch_maxbox" ] = "<input name=\"max\" size=\"5\" value=\"".($max==0?"":$max)."\" />";
$vars["logsearch_inputbox"] = "<input name=\"search\" value=\"$search\" />";
if ($showchanges != $rep->logsShowChanges())
{
$hidden .= '<input type="hidden" name="showchanges" value="'.$showchanges.'" />';
}
 
$vars["logsearch_submit"] = "<input type=\"submit\" value=\"${lang["GO"]}\" />";
$vars["logsearch_endform"] = "<input type=\"hidden\" name=\"logsearch\" value=\"1\" />".
"<input type=\"hidden\" name=\"op\" value=\"log\" />".
"<input type=\"hidden\" name=\"rev\" value=\"$rev\" />".
"<input type=\"hidden\" name=\"sc\" value=\"$showchanged\" />".
"<input type=\"hidden\" name=\"isdir\" value=\"$isDir\" />".
"</form>";
$vars['logsearch_form'] = '<form method="get" action="'.$config->getURL($rep, $path, 'log').'" id="search">'.$hidden;
$vars['logsearch_startbox'] = '<input name="sr" size="5" value="'.$startrev.'" />';
$vars['logsearch_endbox'] = '<input name="er" size="5" value="'.$endrev.'" />';
$vars['logsearch_maxbox'] = '<input name="max" size="5" value="'.($max == 0 ? 40 : $max).'" />';
$vars['logsearch_inputbox'] = '<input name="search" value="'.escape($search).'" />';
$vars['logsearch_showall'] = '<input type="checkbox" name="all" value="1"'.($all ? ' checked="checked"' : '').' />';
$vars['logsearch_submit'] = '<input type="submit" value="'.$lang['GO'].'" />';
$vars['logsearch_endform'] = '</form>';
 
$url = $config->getURL($rep, $path, "log");
$vars["logsearch_clearloglink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;isdir=$isDir\">${lang["CLEARLOG"]}</a>";
// If a filter is in place, produce a link to clear all filter parameters
if ($page !== 1 || $all || $dosearch || $fromRev || $startrev !== $rev || $endrev !== 1 || $max !== 40)
{
$url = $config->getURL($rep, $path, 'log').$isDirString.$passRevString;
$vars['logsearch_clearloglink'] = '<a href="'.$url.'">'.$lang['CLEARLOG'].'</a>';
}
 
$url = $config->getURL($rep, "/", "comp");
$vars["compare_form"] = "<form action=\"$url\" method=\"post\" name=\"compareform\">";
$vars["compare_submit"] = "<input name=\"comparesubmit\" type=\"submit\" value=\"${lang["COMPAREREVS"]}\" />";
$vars["compare_endform"] = "<input type=\"hidden\" name=\"op\" value=\"comp\" /><input type=\"hidden\" name=\"sc\" value=\"$showchanged\" /></form>";
// Create form elements for comparing selected revisions
$vars['compare_form'] = '<form method="get" action="'.$config->getURL($rep, '', 'comp').'" id="compare">';
 
$vars["version"] = $version;
if ($config->multiViews)
{
$vars['compare_form'] .= '<input type="hidden" name="op" value="comp" />';
}
else
{
$vars['compare_form'] .= '<input type="hidden" name="repname" value="'.$repname.'" />';
}
 
if (!$rep->hasReadAccess($path, false))
$vars["noaccess"] = true;
$vars['compare_submit'] = '<input type="submit" value="'.$lang['COMPAREREVS'].'" />';
$vars['compare_endform'] = '</form>';
 
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."log.tmpl", $vars, $listing);
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
if (!$rep->hasReadAccess($path, false))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
?>
renderTemplate('log');
/WebSVN/multiviews.php
0,0 → 1,139
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// multiviews.php
//
// Glue for MultiViews
chdir($locwebsvnreal);
 
// Tell files that we are using multiviews if they are unable to access $config.
if (!defined('WSVN_MULTIVIEWS')) {
define('WSVN_MULTIVIEWS', 1);
}
 
require_once 'include/setup.php';
require_once 'include/svnlook.php';
 
if (!isset($_REQUEST['sc'])) {
$_REQUEST['sc'] = 1;
}
 
if (!$config->multiViews) {
$vars['error'] = 'MultiViews must be enabled in <code>include/config.php</code> in order to use <code>browse.php</code>. See <a href="'.$locwebsvnhttp.'/doc/install.html#multiviews">the install docs</a> for details, or use <a href="'.$locwebsvnhttp.'">this path</a> instead.';
include $locwebsvnreal.'/index.php';
exit;
}
 
$op = @$_REQUEST['op'];
// This means the user wants to browse another project, so we switch to it and exit.
if ($op == 'rep') {
$rep =& $config->findRepository(@$_REQUEST['repname']);
if ($rep != null) {
header('Location: '.$config->getURL($rep, '', 'dir'));
} else {
include $locwebsvnreal.'/index.php';
}
exit;
}
 
$origPathInfo = isset($_SERVER['ORIG_PATH_INFO']) ? $_SERVER['ORIG_PATH_INFO'] : '';
$pathInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
$path = trim(empty($pathInfo) ? $origPathInfo : $pathInfo);
 
// Remove initial slash
$path = substr($path, 1);
if (empty($path)) {
include $locwebsvnreal.'/index.php';
exit;
}
 
// Split the path into repository and path elements
// Note: we have to cope with the repository name having a slash in it
 
$pos = strpos($path, '/');
if ($pos === false) {
$pos = strlen($path);
}
$name = substr($path, 0, $pos);
 
$rep =& $config->findRepository($name);
if ($rep != null && is_object($rep)) {
$path = substr($path, $pos);
if ($path == '') {
$path = '/';
}
$repname = $name;
} else {
include $locwebsvnreal.'/index.php';
exit;
}
 
createProjectSelectionForm();
createRevisionSelectionForm();
 
$vars['repurl'] = $config->getURL($rep, '', 'dir');
$vars['clientrooturl'] = $rep->clientRootURL;
$vars['allowdownload'] = $rep->getAllowDownload();
$vars['repname'] = escape($rep->getDisplayName());
 
// find the operation type
switch ($op) {
case 'dir':
$file = 'listing.php';
break;
case 'revision':
$file = 'revision.php';
break;
case 'file':
$file = 'filedetails.php';
break;
case 'log':
$file = 'log.php';
break;
case 'diff':
$file = 'diff.php';
break;
case 'blame':
$file = 'blame.php';
break;
case 'rss':
$file = 'rss.php';
break;
case 'dl':
$file = 'dl.php';
break;
case 'comp':
$file = 'comp.php';
break;
case 'search':
$file = 'search.php';
break;
default:
$svnrep = new SVNRepository($rep);
if ($svnrep->isFile($path, $rev, $peg)) {
$file = 'filedetails.php';
} else {
$file = 'listing.php';
}
break;
}
 
// Now include the file that handles it
include $locwebsvnreal.'/'.$file;
/WebSVN/revision.php
0,0 → 1,222
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// revision.php
//
// Show the details for a given revision
 
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
require_once 'include/bugtraq.php';
 
// Make sure that we have a repository
if (!$rep)
{
renderTemplate404('revision','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
$ppath = ($path == '' || $path[0] != '/') ? '/'.$path : $path;
createPathLinks($rep, $ppath, $rev, $peg);
$passRevString = createRevAndPegString($rev, $peg);
 
// Find the youngest revision containing changes for the given path
$history = $svnrep->getLog($path, 'HEAD', 1, true, 2, ($path == '/') ? '' : $peg);
 
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', true, 2, ($path == '/') ? '' : $peg);
 
if (!$history)
{
renderTemplate404('revision','NOPATH');
}
}
 
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : 0;
$vars['youngestrev'] = $youngest;
 
// TODO The "youngest" rev is often incorrect when both path and rev are specified.
// If a path was last modified at rev M and the URL contains rev N, it uses rev N.
 
// Unless otherwise specified, we get the log details of the latest change
$lastChangedRev = ($rev) ? $rev : $youngest;
$history = $svnrep->getLog($path, $lastChangedRev, 1, false, 2, $peg, true);
 
if (!$history)
{
renderTemplate404('revision','NOPATH');
}
 
if (empty($rev))
{
$rev = $lastChangedRev;
}
 
// Generate links to newer and older revisions
$revurl = $config->getURL($rep, $path, 'revision');
 
if ($rev < $youngest)
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'revision');
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
 
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg);
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $path != '/' ? $peg ? $peg : $rev : '');
//echo 'NEXT='.$vars['nextrevurl'].'<br/>';
}
}
 
unset($vars['error']);
}
 
if (isset($history->entries[1]))
{
$prevRev = $history->entries[1]->rev;
$prevPath = $history->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $path != '/' ? ($peg ? $peg : $rev) : '');
//echo 'PREV='.$vars['prevrevurl'].'<br/>';
}
 
// Save the entry from which we pull information for the current revision.
$logEntry = (isset($history->entries[0])) ? $history->entries[0] : null;
 
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
 
$vars['action'] = '';
$vars['rev'] = $rev;
$vars['peg'] = $peg;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
 
if ($logEntry)
{
$vars['date'] = $logEntry->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date));
$vars['author'] = $logEntry->author;
$vars['log'] = nl2br($bugtraq->replaceIDs(create_anchors(xml_entities($logEntry->msg))));
}
 
$isDir = @$_REQUEST['isdir'] == 1 || $path == '' || $path == '/';
$vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString.($isDir ? '&amp;isdir=1' : '');
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
$dirPath = $isDir ? $path : dirname($path).'/';
$vars['directoryurl'] = $config->getURL($rep, $dirPath, 'dir').$passRevString.'#'.anchorForPath($dirPath);
$vars['directorylink'] = '<a href="'.$vars['directoryurl'].'">'.$lang['LISTING'].'</a>';
 
if ($path != $dirPath)
{
$vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
$vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
$vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
$vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
}
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
$changes = $logEntry ? $logEntry->mods : array();
 
if (!is_array($changes))
{
$changes = array();
}
 
usort($changes, 'SVNLogEntry_compare');
 
$row = 0;
 
$prevRevString = createRevAndPegString($rev - 1, $rev - 1);
$thisRevString = createRevAndPegString($rev, $rev);
 
foreach ($changes as $change)
{
$linkRevString = ($change->action == 'D') ? $prevRevString : $thisRevString;
$isDir = $change->isdir;
 
if ($isDir !== null)
{
$isFile = !$isDir;
}
else
{
// NOTE: This is a hack (runs `svn info` on each path) to see if it's a file.
// `svn log --verbose --xml` should really provide this info, but does only in recent version?
$lastSeenRev = ($change->action == 'D') ? $rev - 1 : $rev;
$isFile = $svnrep->isFile($change->path, $lastSeenRev, $lastSeenRev);
}
 
if (!$isFile && $change->path != '/')
{
$change->path .= '/';
}
 
$resourceExisted = $change->action == 'M' || $change->copyfrom;
$listing[] = array(
'path' => str_replace('%2F', '/', rawurlencode($change->path)),
'safepath' => escape($change->path),
'oldpath' => str_replace('%2F', '/', rawurlencode($change->copyfrom)).($change->copyfrom ? '@'.$change->copyrev : ''),
'oldsafepath' => escape($change->copyfrom ? $change->copyfrom.'@'.$change->copyrev : ''),
'action' => $change->action,
'added' => $change->action == 'A',
'deleted' => $change->action == 'D',
'modified' => $change->action == 'M',
'detailurl' => $config->getURL($rep, $change->path, ($isFile ? 'file' : 'dir')).$linkRevString,
// For deleted resources, the log link points to the previous revision.
'logurl' => $config->getURL($rep, $change->path, 'log').$linkRevString.($isFile ? '' : '&amp;isdir=1'),
'diffurl' => $resourceExisted ? $config->getURL($rep, $change->path, 'diff').$linkRevString : '',
'blameurl' => $resourceExisted ? $config->getURL($rep, $change->path, 'blame').$linkRevString : '',
'rowparity' => $row,
'notinpath' => substr($change->path, 0, strlen($path)) != $path,
);
 
$row = 1 - $row;
}
 
if (isset($prevRev))
{
$vars['compareurl'] = $config->getURL($rep, '', 'comp').'compare[]='.rawurlencode($prevPath).'@'.$prevRev. '&amp;compare[]='.rawurlencode($path).'@'.$rev;
$vars['comparelink'] = '<a href="'.$vars['compareurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
if (!$rep->hasReadAccess($path))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
$vars['restricted'] = !$rep->hasReadAccess($path, false);
 
renderTemplate('revision');
/WebSVN/rss.php
1,8 → 1,6
<?php
# vim:et:ts=3:sts=3:sw=3:fdm=marker:
 
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright © 2004-2006 Tim Armes, Matt Sicker
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
11,12 → 9,12
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
24,147 → 22,140
//
// Creates an rss feed for the given repository number
 
include("include/feedcreator.class.php");
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
require_once 'include/bugtraq.php';
 
require_once("include/setup.inc");
require_once("include/svnlook.inc");
require_once("include/utils.inc");
require_once("include/template.inc");
$max = (int)@$_REQUEST['max'];
if ($max == 0)
$max = $config->getRssMaxEntries();
$quiet = (isset($_REQUEST['quiet']));
 
$isDir = (@$_REQUEST["isdir"] == 1)?1:0;
 
$maxmessages = 20;
 
// Find the base URL name
if ($config->multiViews)
{
$baseurl = "";
if ($config->multiViews) {
$baseurl = '';
} else {
$baseurl = dirname($_SERVER['PHP_SELF']);
if ($baseurl != '' && $baseurl != DIRECTORY_SEPARATOR && $baseurl != '\\' && $baseurl != '/') {
$baseurl .= '/';
} else {
$baseurl = '/';
}
}
else
{
$baseurl = dirname($_SERVER["PHP_SELF"]);
if ($baseurl != "" && $baseurl != DIRECTORY_SEPARATOR && $baseurl != "\\" && $baseurl != "/" )
$baseurl .= "/";
else
$baseurl = "/";
 
if ($path == '' || $path[0] != '/') {
$ppath = '/'.$path;
} else {
$ppath = $path;
}
 
$svnrep = new SVNRepository($rep);
 
if ($path == "" || $path{0} != "/")
$ppath = "/".$path;
else
$ppath = $path;
 
if (!$rep) {
http_response_code(404);
print 'Unable to access resource at path: '.xml_entities($path);
exit;
}
// Make sure that the user has full access to the specified directory
if (!$rep->hasReadAccess($path, false))
exit;
if (!$rep->hasReadAccess($path, false)) {
http_response_code(403);
print 'Unable to access resource at path: '.xml_entities($path);
exit;
}
 
$url = $config->getURL($rep, $path, "log");
$listurl = $config->getURL($rep, $path, "dir");
 
// If there's no revision info, go to the lastest revision for this path
$history = $svnrep->getLog($path, $rev, "", false, 20);
$youngest = $history->entries[0]->rev;
$svnrep = new SVNRepository($rep);
$history = $svnrep->getLog($path, $rev, '', false, $max, $peg, !$quiet);
if (!$history) {
http_response_code(404);
echo $lang['NOPATH'];
exit;
}
 
// Cachename reflecting full path to and rev for rssfeed. Must end with xml to work
$cachename = strtr(getFullURL($listurl), ":/\\?", "____");
$cachename = $locwebsvnreal.DIRECTORY_SEPARATOR."cache".DIRECTORY_SEPARATOR.$cachename.@$_REQUEST["rev"]."_rssfeed.xml";
header('Content-Type: application/xml; charset=utf-8');
 
$rss = new UniversalFeedCreator();
$rss->useCached("RSS2.0", $cachename);
$rss->title = $rep->getDisplayName();
$rss->description = "${lang["RSSFEEDTITLE"]} - $repname";
$rss->link = html_entity_decode(getFullURL($baseurl.$listurl));
$rss->syndicationURL = $rss->link;
$rss->xslStyleSheet = ""; //required for UniversalFeedCreator since 1.7
$rss->cssStyleSheet = ""; //required for UniversalFeedCreator since 1.7
if ($rep->isRssCachingEnabled()) {
// Filename for storing a cached RSS feed for this particular path/revision
$cache = $locwebsvnreal.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR.strtr($rep->getDisplayName().$path, '\\/:*?"<>|.', '__________').($peg ? '@'.$peg : '').($rev ? '_r'.$rev : '').'m'.$max.($quiet ? 'q' : '').'.rss.xml';
// If a recent-enough cached version exists, use it and avoid the work below
if (file_exists($cache) && filemtime($cache) >= $history->curEntry->committime) {
readfile($cache);
exit();
}
}
 
//$divbox = "<div>";
//$divfont = "<span>";
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
 
foreach ($history->entries as $r)
{
$thisrev = $r->rev;
$changes = $r->mods;
$files = count($changes);
// Generate RSS 2.0 feed
$rss = '<?xml version="1.0" encoding="utf-8"?>';
$rss .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel>';
$rss .= '<title>'.escape($rep->getDisplayName()).($path ? ' &#x2013; '.$path : '').'</title>';
$rss .= '<description>'.escape($lang['RSSFEEDTITLE']).' &#x2013; '.escape($repname).'</description>';
$rss .= '<lastBuildDate>'.date('r').'</lastBuildDate>'; // RFC 2822 date format
$rss .= '<generator>WebSVN '.$vars['version'].'</generator>';
$rss .= '<language>'.$lang['LANGUAGETAG'].'</language>';
// URL for matching WebSVN log page
$rss .= '<link>'.getFullURL($baseurl.$config->getURL($rep, $path, 'log').(@$_REQUEST['isdir'] == 1 ? 'isdir=1&amp;' : '').'max='.$max.'&amp;'.createRevAndPegString($passrev, $peg)).'</link>';
// URL where this original RSS feed can be found
$rss .= '<atom:link href="'.escape(getFullURL($_SERVER['REQUEST_URI'])).'" rel="self" type="application/rss+xml" />'."\n";
if (is_array($history->entries)) {
$itemURL = $baseurl.$config->getURL($rep, $path, 'revision');
if (@$_REQUEST['isdir'] == 1 || $path == '' || $path == '/')
$itemURL .= 'isdir=1&amp;';
foreach ($history->entries as $r) {
$wordLimit = 10; // Display only up to the first 10 words of the log message
$title = trim(explode('\n', $r->msg)[0]);
$title = str_replace(array("\r\n", "\r", "\n", "\t"), ' ', $title);
$words = explode(' ', $title, $wordLimit + 1);
if (count($words) > $wordLimit) {
$title = implode(' ', array_slice($words, 0, $wordLimit)).' ...';
}
$title = $lang['REV'].' '.$r->rev.' '.mb_convert_encoding('&#x2013;', 'UTF-8', 'HTML-ENTITIES').' '.$title;
$description = '<div><strong>'.$r->author;
if (!$quiet) {
$description .= ' '.mb_convert_encoding('&#x2013;', 'UTF-8', 'HTML-ENTITIES').' '.count($r->mods).' '.$lang['FILESMODIFIED'];
}
$description .= '</strong><br/>'.nl2br($bugtraq->replaceIDs(create_anchors(str_replace('<', '&lt;', $r->msg)))).'</div>';
if (!$quiet) {
usort($r->mods, 'SVNLogEntry_compare');
foreach ($r->mods as $modifiedResource) {
switch ($modifiedResource->action) {
case 'A': $description .= '+ '; break;
case 'M': $description .= '~ '; break;
case 'D': $description .= 'x '; break;
}
$description .= $modifiedResource->path;
if ($modifiedResource->copyfrom != '') {
$description .= ' <i>(copied from '.$modifiedResource->copyfrom.'@'.$modifiedResource->copyrev.')</i>';
}
$description .= '<br />';
}
}
 
// Add the trailing slash if we need to (svnlook history doesn't return trailing slashes!)
$rpath = $r->path;
if ($isDir && $rpath{strlen($rpath) - 1} != "/")
$rpath .= "/";
// Find the parent path (or the whole path if it's already a directory)
$pos = strrpos($rpath, "/");
$parent = substr($rpath, 0, $pos + 1);
$url = $config->getURL($rep, $parent, "dir");
$desc = $r->msg;
$item = new FeedItem();
// For the title, we show the first 10 words of the description
$pos = 0;
$len = strlen($desc);
for ($i = 0; $i < 10; $i++)
{
if ($pos >= $len) break;
$pos = strpos($desc, " ", $pos);
if ($pos === FALSE) break;
$pos++;
}
if ($pos !== FALSE)
{
$sdesc = substr($desc, 0, $pos) . "...";
}
else
{
$sdesc = $desc;
}
if ($desc == "") $sdesc = "${lang["REV"]} $thisrev";
$item->title = "$sdesc";
$item->link = html_entity_decode(getFullURL($baseurl."${url}rev=$thisrev&amp;sc=$showchanged"));
$item->description = "<div><strong>${lang["REV"]} $thisrev - ".$r->author."</strong> ($files ${lang["FILESMODIFIED"]})</div><div>".nl2br(create_anchors($desc))."</div>";
// skip items with no access
if ($r->committime) {
$rss .= '<item>';
$rss .= '<pubDate>'.date('r', $r->committime).'</pubDate>';
$rss .= '<dc:creator>'.escape($r->author).'</dc:creator>';
$rss .= '<title>'.escape($title).'</title>';
$rss .= '<description>'.escape($description).'</description>';
$itemLink = getFullURL($itemURL.createRevAndPegString($r->rev,$peg));
$rss .= '<link>'.$itemLink.'</link>';
$rss .= '<guid>'.$itemLink.'</guid>';
$rss .= '</item>'."\n";
}
}
}
$rss .= '</channel></rss>';
 
if ($showchanged)
{
foreach ($changes as $file)
{
switch ($file->action)
{
case "A":
$item->description .= "+ ".$file->path."<br />";
break;
case "M":
$item->description .= "~ ".$file->path."<br />";
break;
case "D":
$item->description .= "-".$file->path."<br />";
break;
}
}
}
 
$item->date = $r->committime;
$item->author = $r->author;
$rss->addItem($item);
if ($rep->isRssCachingEnabled()) {
$file = fopen($cache, 'w+');
if ($file) {
fputs($file, $rss);
fclose($file);
touch($cache, $history->curEntry->committime); // set timestamp to commit time
} else {
echo 'Error creating RSS cache file, please check write permissions.';
}
}
 
// valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML
 
// Save the feed
$rss->saveFeed("RSS2.0",$cachename, false);
header("Content-Type: application/xml");
echo $rss->createFeed("RSS2.0");
 
?>
echo $rss;
/WebSVN/search.php
0,0 → 1,393
<?php
// WebSVN - Subversion repository viewing via the web using PHP
// Copyright (C) 2004-2006 Tim Armes
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// --
//
// search.php
//
// Show the search listing for the given term in repository/path/revision
 
require_once 'include/setup.php';
require_once 'include/svnlook.php';
require_once 'include/utils.php';
require_once 'include/template.php';
require_once 'include/bugtraq.php';
 
function removeURLSeparator($url)
{
return preg_replace('#(\?|&(amp;)?)$#', '', $url);
}
 
function urlForPath($fullpath, $passRevString)
{
global $config, $rep;
 
$isDir = $fullpath[strlen($fullpath) - 1] == '/';
 
if ($isDir)
{
if ($config->treeView)
{
$url = $config->getURL($rep, $fullpath, 'dir').$passRevString;
$id = anchorForPath($fullpath);
$url .= '#'.$id.'" id="'.$id;
}
else
{
$url = $config->getURL($rep, $fullpath, 'dir').$passRevString;
}
}
else
{
$url = $config->getURL($rep, $fullpath, 'file').$passRevString;
}
 
return removeURLSeparator($url);
}
 
function showSearchResults($svnrep, $path, $searchstring, $rev, $peg, $listing, $index=0, $treeview = true)
{
 
global $config, $lang, $rep, $passrev, $peg, $passRevString;
 
// List each file in the current directory
$loop = 0;
$last_index = 0;
$accessToThisDir = $rep->hasReadAccess($path, false);
 
$openDir = false;
$logList = $svnrep->getListSearch($path, $searchstring, $rev, $peg);
if (!$logList)
{
return $listing;
}
 
$downloadRevAndPeg = createRevAndPegString($rev, $peg ? $peg : $rev);
 
foreach ($logList->entries as $entry)
{
$isDir = $entry->isdir;
$file = $entry->file;
$isDirString = ($isDir) ? 'isdir=1&amp;' : '';
 
// Only list files/directories that are not designated as off-limits
$access = ($isDir) ? $rep->hasReadAccess($path.$file, false)
: $accessToThisDir;
 
if (!$access)
{
continue;
}
 
$listvar = &$listing[$index];
$listvar['rowparity'] = $index % 2;
 
if ($isDir)
{
$listvar['filetype'] = ($openDir) ? 'diropen' : 'dir';
$openDir = true;
}
else
{
$listvar['filetype'] = strtolower(strrchr($file, '.'));
$openDir = false;
}
 
$listvar['isDir'] = $isDir;
$listvar['openDir'] = $openDir;
$listvar['path'] = str_replace('%2F', '/', rawurlencode($path.$file));
 
$tempelements = explode('/',$file);
 
if ($tempelements[count($tempelements)-1] === "")
{
$lastindexfile = count($tempelements)-1 - 1;
$listvar['node'] = $lastindexfile; // t-node
$listvar['level'] = ($treeview) ? $lastindexfile : 0;
$listvar['filename'] = escape($tempelements[$lastindexfile]);
}
else
{
$lastindexfile = count($tempelements)-1;
$listvar['node'] = $lastindexfile; // t-node
$listvar['level'] = ($treeview) ? $lastindexfile : 0;
$listvar['filename'] = escape($tempelements[$lastindexfile]);
}
 
for ($j=1;$j<=$lastindexfile;$j++)
{
$listvar['last_i_node'][$j] = false;
}
 
if ($isDir)
{
$listvar['fileurl'] = urlForPath($path.$file, $passRevString);
}
else
{
$listvar['fileurl'] = urlForPath($path.$file, createDifferentRevAndPegString($passrev, $peg));
}
 
$listvar['filelink'] = '<a href="'.$listvar['fileurl'].'">'.$listvar['filename'].'</a>';
 
if ($isDir)
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.$passRevString;
}
else
{
$listvar['logurl'] = $config->getURL($rep, $path.$file, 'log').$isDirString.createDifferentRevAndPegString($passrev, $peg);
}
 
if ($treeview)
{
$listvar['compare_box'] = '<input type="checkbox" name="compare[]" value="'.escape($path.$file).'@'.$passrev.'" onclick="enforceOnlyTwoChecked(this)" />';
}
 
if ($config->showLastModInListing())
{
$listvar['committime'] = $entry->committime;
$listvar['revision'] = $entry->rev;
$listvar['author'] = $entry->author;
$listvar['age'] = $entry->age;
$listvar['date'] = $entry->date;
$listvar['revurl'] = $config->getURL($rep, $path.$file, 'revision').$isDirString.createRevAndPegString($entry->rev, $peg ? $peg : $rev);
}
 
if ($rep->isDownloadAllowed($path.$file))
{
$downloadurl = $config->getURL($rep, $path.$file, 'dl').$isDirString.$downloadRevAndPeg;
 
if ($isDir)
{
$listvar['downloadurl'] = $downloadurl;
$listvar['downloadplainurl'] = '';
}
else
{
$listvar['downloadplainurl'] = $downloadurl;
$listvar['downloadurl'] = '';
}
}
else
{
$listvar['downloadplainurl'] = '';
$listvar['downloadurl'] = '';
}
 
if ($rep->isRssEnabled())
{
// RSS should always point to the latest revision, so don't include rev
$listvar['rssurl'] = $config->getURL($rep, $path.$file, 'rss').$isDirString.createRevAndPegString('', $peg);
}
 
$loop++;
$index++;
$last_index = $index;
}
 
return $listing;
}
 
// Make sure that we have a repository
if (!$rep)
{
renderTemplate404('directory','NOREP');
}
 
$svnrep = new SVNRepository($rep);
 
if (!empty($rev))
{
$info = $svnrep->getInfo($path, $rev, $peg);
 
if ($info)
{
$path = $info->path;
$peg = (int)$info->rev;
}
}
 
$history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg);
 
if (!$history)
{
unset($vars['error']);
$history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg);
if (!$history)
{
renderTemplate404('directory','NOPATH');
}
}
 
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : 0;
 
// Unless otherwise specified, we get the log details of the latest change
$lastChangedRev = ($passrev) ? $passrev : $youngest;
 
if ($lastChangedRev != $youngest)
{
$history = $svnrep->getLog($path, $lastChangedRev, 1, false, 2, $peg);
}
 
$logEntry = ($history && isset($history->entries[0])) ? $history->entries[0] : 0;
 
$headlog = $svnrep->getLog('/', '', '', true, 1);
$headrev = ($headlog && isset($headlog->entries[0])) ? $headlog->entries[0]->rev : 0;
 
// If we're not looking at a specific revision, get the HEAD revision number
// (the revision of the rest of the tree display)
 
if (empty($rev))
{
$rev = $headrev;
}
 
if ($path == '' || $path[0] != '/')
{
$ppath = '/'.$path;
}
else
{
$ppath = $path;
}
 
createPathLinks($rep, $ppath, $passrev, $peg);
$passRevString = createRevAndPegString($passrev, $peg);
$isDirString = 'isdir=1&amp;';
 
$revurl = $config->getURL($rep, $path != '/' ? $path : '', 'dir');
$revurlSuffix = $path != '/' ? '#'.anchorForPath($path) : '';
 
if ($rev < $youngest)
{
if ($path == '/')
{
$vars['goyoungesturl'] = $config->getURL($rep, '', 'dir');
}
else
{
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'dir').createRevAndPegString($youngest, $peg ? $peg: $rev).$revurlSuffix;
}
 
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
 
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg);
 
if (isset($history2->entries[1]))
{
$nextRev = $history2->entries[1]->rev;
if ($nextRev != $youngest)
{
$vars['nextrev'] = $nextRev;
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$revurlSuffix;
}
}
 
unset($vars['error']);
}
 
if (isset($history->entries[1]))
{
$prevRev = $history->entries[1]->rev;
$prevPath = $history->entries[1]->path;
$vars['prevrev'] = $prevRev;
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$revurlSuffix;
}
 
$bugtraq = new Bugtraq($rep, $svnrep, $ppath);
 
$vars['action'] = '';
$vars['rev'] = $rev;
$vars['peg'] = $peg;
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
$vars['safepath'] = escape($ppath);
$vars['lastchangedrev'] = $lastChangedRev;
 
if ($logEntry)
{
$vars['date'] = $logEntry->date;
$vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date));
$vars['author'] = $logEntry->author;
$vars['log'] = nl2br($bugtraq->replaceIDs(create_anchors(xml_entities($logEntry->msg))));
}
 
$vars['revurl'] = $config->getURL($rep, ($path == '/' ? '' : $path), 'revision').$isDirString.$passRevString;
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
 
if ($history && count($history->entries) > 1)
{
$vars['compareurl'] = $config->getURL($rep, '', 'comp').'compare[]='.rawurlencode($history->entries[1]->path).'@'.$history->entries[1]->rev. '&amp;compare[]='.rawurlencode($history->entries[0]->path).'@'.$history->entries[0]->rev;
$vars['comparelink'] = '<a href="'.$vars['compareurl'].'">'.$lang['DIFFPREV'].'</a>';
}
 
$vars['logurl'] = $config->getURL($rep, $path, 'log').$isDirString.$passRevString;
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
 
if ($rep->isRssEnabled())
{
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').$isDirString.createRevAndPegString('', $peg);
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
}
 
// Set up the tarball link
$subs = explode('/', $path);
$level = count($subs) - 2;
if ($rep->isDownloadAllowed($path) && !isset($vars['warning']))
{
$vars['downloadurl'] = $config->getURL($rep, $path, 'dl').$isDirString.$passRevString;
}
 
$vars['compare_form'] = '<form method="get" action="'.$config->getURL($rep, '', 'comp').'" id="compare">';
 
if ($config->multiViews)
{
$vars['compare_form'] .= '<input type="hidden" name="op" value="comp"/>';
}
else
{
$vars['compare_form'] .= '<input type="hidden" name="repname" value="'.$repname.'" />';
}
 
$vars['compare_submit'] = '<input type="submit" value="'.$lang['COMPAREPATHS'].'" />';
$vars['compare_endform'] = '</form>';
 
$vars['showlastmod'] = $config->showLastModInListing();
 
if (empty($_GET["search"]))
{
$vars['warning'] = $lang['NOSEARCHTERM'];
createSearchSelectionForm();
}
else
{
createSearchSelectionForm();
$vars['compare_box'] = '';
$listing = showSearchResults($svnrep, $path, $_GET["search"], $rev, $peg, array(),0,$config->treeView);
}
 
if (!$rep->hasReadAccess($path))
{
$vars['error'] = $lang['NOACCESS'];
sendHeaderForbidden();
}
 
$vars['restricted'] = !$rep->hasReadAccess($path, false);
 
renderTemplate('directory');
/WebSVN/templates/Standard/compare.tmpl
File deleted
/WebSVN/templates/Standard/index.tmpl
File deleted
/WebSVN/templates/Standard/diff.tmpl
File deleted
/WebSVN/templates/Standard/header.tmpl
File deleted
/WebSVN/templates/Standard/xml.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/Standard/footer.tmpl
File deleted
/WebSVN/templates/Standard/styles.css
File deleted
/WebSVN/templates/Standard/file.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Standard/blame.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Standard/log.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Standard/collapse.js
File deleted
/WebSVN/templates/Standard/directory.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Zinn/directory.tmpl
File deleted
/WebSVN/templates/Zinn/compare.tmpl
File deleted
/WebSVN/templates/Zinn/index.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Zinn/diff.tmpl
File deleted
/WebSVN/templates/Zinn/header.tmpl
File deleted
/WebSVN/templates/Zinn/footer.tmpl
File deleted
/WebSVN/templates/Zinn/styles.css
File deleted
/WebSVN/templates/Zinn/file.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Zinn/blame.tmpl
File deleted
/WebSVN/templates/Zinn/log.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/Zinn/collapse.js
File deleted
/WebSVN/templates/StandardNG/compare.tmpl
File deleted
/WebSVN/templates/StandardNG/index.tmpl
File deleted
/WebSVN/templates/StandardNG/diff.tmpl
File deleted
/WebSVN/templates/StandardNG/header.tmpl
File deleted
/WebSVN/templates/StandardNG/xml.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/StandardNG/ie7/ie7-core.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-html4.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-recalc.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-standard-p.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-css-strict.js
File deleted
/WebSVN/templates/StandardNG/ie7/blank.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/StandardNG/ie7/ie7-base64.php
File deleted
\ No newline at end of file
/WebSVN/templates/StandardNG/ie7/ie7-fixed.js
File deleted
\ No newline at end of file
/WebSVN/templates/StandardNG/ie7/ie7-graphics.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-overflow.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-xml-extras.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-object.htc
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-dynamic-attributes.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-dhtml.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-css2-selectors.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-css3-selectors.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-squish.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-content.htc
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-layout.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-quirks.js
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-load.htc
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-server.css
File deleted
/WebSVN/templates/StandardNG/ie7/ie7-ie5.js
File deleted
/WebSVN/templates/StandardNG/footer.tmpl
File deleted
/WebSVN/templates/StandardNG/styles.css
File deleted
/WebSVN/templates/StandardNG/file.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/StandardNG/blame.tmpl
File deleted
/WebSVN/templates/StandardNG/log.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/StandardNG/collapse.js
File deleted
/WebSVN/templates/StandardNG/directory.tmpl
File deleted
\ No newline at end of file
/WebSVN/templates/BlueGrey/png.js
File deleted
/WebSVN/templates/BlueGrey/file.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/fileh.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/folder-open.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/xml.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/filejava.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/filem.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/e-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/folder.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/files.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/repo.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/i-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/l-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/filepy.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/t-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/filecpp.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/subversion.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/filec.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/collapse.js
File deleted
/WebSVN/templates/BlueGrey/filehtml.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/blame.tmpl
1,32 → 1,62
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
 
[websvn:curdirlinks] - <h2> [lang:BLAMEFOR] [websvn:rev]</h2>
<p>
 
[websvn-test:noaccess]
[lang:NOACCESS]
<h1>[websvn:repname] &ndash; [lang:BLAMEFOR] [websvn:rev]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<table cellpadding="2px" cellspacing="0" width="100%">
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
<div id="nav">
[websvn-test:prevrevurl]
<a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a> &ndash;
[websvn-endtest]
[websvn-test:nextrevurl]
<a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a> &ndash;
[websvn-endtest]
[websvn-test:goyoungestlink]
[websvn:goyoungestlink] &ndash;
[websvn-endtest]
[websvn-test:mimelink]
[websvn:mimelink] &ndash;
[websvn-endtest]
[websvn:filedetaillink] &ndash;
[websvn-test:difflink]
[websvn:difflink] &ndash;
[websvn-endtest]
[websvn-test:downloadlink]
[websvn:downloadlink] &ndash;
[websvn-endtest]
[websvn:revlink] &ndash;
[websvn:loglink]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rssurl]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<table>
<thead>
<tr>
<th class="HdrClmn"><b>[lang:LINENO]</b></th>
<th class="HdrClmn"><b>[lang:REV]</b></th>
<th class="HdrClmn"><b>[lang:AUTHOR]</b></th>
<th class="HdrClmnEnd"><b>[lang:LINE]</b></th>
<th>[lang:REV]</th>
<th>[lang:AUTHOR]</th>
<th>[lang:LINENO]</th>
<th>[lang:LINE]</th>
</tr>
</thead>
<tbody style="font-size: 90%;">
[websvn-startlisting]
<tr>
<td class="CatClmn0" style="border-right: 1px solid black" valign="top">[websvn:lineno]</td>
<td class="CatClmn0" style="border-right: 1px solid black" valign="top">[websvn:revision]</td>
<td class="CatClmn0" style="border-right: 1px solid black" valign="top">[websvn:author]</td>
<td style="border-right: 1px solid black" valign="top">[websvn:line]</td>
</tr>
<tr class="[websvn:row_class]">
<th>[websvn:revision]</th>
<th>[websvn:author]</th>
<th><a name="l[websvn:lineno]" href="#l[websvn:lineno]">[websvn:lineno]</a></th>
<td>[websvn:line]</td>
</tr>
[websvn-endlisting]
</table>
</tbody>
</table>
[websvn:javascript]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/compare.tmpl
1,65 → 1,63
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
 
[websvn-test:noaccess]
[lang:NOACCESS]
<h1>[websvn:repname]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
[websvn:compare_form]
<table>
<tr><td>[lang:COMPPATH]&nbsp</td><td>[websvn:compare_path1input] [lang:REV] [websvn:compare_rev1input]</td></tr>
<tr><td>[lang:WITHPATH]</td><td>[websvn:compare_path2input] [lang:REV] [websvn:compare_rev2input]</td></tr>
</table>
[websvn:compare_submit]
[websvn:compare_endform]
[websvn-test:success]
<hr>
<p>[lang:CONVFROM] <b>[websvn:path1] ([lang:REV] [websvn:rev1])</b> [lang:TO] <b>[websvn:path2] ([lang:REV] [websvn:rev2])</b>
<p>
[websvn:revlink]
<p>
[websvn-endtest]
[websvn-startlisting]
<center>
[websvn:compare_form]
<table id="params">
<tr>
<td>[lang:COMPPATH]</td>
<td>[websvn:compare_path1input] [lang:REV] [websvn:compare_rev1input]</td>
<td rowspan="2">[websvn:compare_submit]</td>
</tr>
<tr>
<td>[lang:WITHPATH]</td>
<td>[websvn:compare_path2input] [lang:REV] [websvn:compare_rev2input]</td>
</tr>
</table>
[websvn:compare_endform]
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-endtest]
[websvn-test:success]
<div id="nav">
[websvn:reverselink] &#124;
[websvn-test:regardwhitespacelink]
[websvn:regardwhitespacelink]
[websvn-else]
[websvn:ignorewhitespacelink]
[websvn-endtest]
</div>
<div><a href="[websvn:rev1url]">[websvn:safepath1] @ [websvn:rev1]</a> &nbsp;&rarr;&nbsp; <a href="[websvn:rev2url]">[websvn:safepath2] @ [websvn:rev2]</a></div>
[websvn-endtest]
</center>
[websvn-startlisting]
[websvn-test:newpath]
<p>
<div class="newpath">
<b>[websvn:newpath]</b><br>
<table class="comparison collapsible">
<thead>
<tr><th><a href="[websvn:fileurl]">[websvn:newpath]</a></th></tr>
</thead>
[websvn-endtest]
[websvn-test:info]
[websvn:info]<br>
[websvn:info]<br />
[websvn-endtest]
[websvn-test:difflines]
<div class="difflines">
<p>
[websvn:difflines]<br>
<table class="diff" cellspacing="0">
<tr class="row1"><th>[websvn:difflines]</th></tr>
[websvn-endtest]
[websvn-test:diffclass]
<tr><td class="[websvn:diffclass]">[websvn:line]</td></tr>
<tr><td class="[websvn:diffclass]">[websvn:line]</td></tr>
[websvn-endtest]
[websvn-test:enddifflines]
</table>
</div>
[websvn-test:endpath]
</table>
[websvn-endtest]
[websvn-test:endpath]
</div>
<p><hr>
[websvn-endtest]
[websvn-test:properties]
<p><i>[lang:PROPCHANGES]</i><p>
<p><i>[lang:PROPCHANGES]</i><p>
[websvn-endtest]
[websvn-endlisting]
</table>
[websvn-endtest]
[websvn-endlisting]
[websvn-endtest]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
/WebSVN/templates/BlueGrey/diff.tmpl
1,46 → 1,85
[websvn-test:noaccess]
[lang:NOACCESS]
[websvn-test:rev2]
<h1>[websvn:repname] &ndash; [lang:DIFFREVS] [websvn:rev2] [lang:AND] [websvn:rev1]</h1>
[websvn-else]
<h1>[websvn:repname] &ndash; [lang:DIFF]</h1>
[websvn-endtest]
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
[websvn-test:noprev]
[lang:NOPREVREV]
[websvn-else]
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
[websvn:curdirlinks] - [lang:DIFFREVS] <b>[websvn:rev2]</b> [lang:AND] <b>[websvn:rev1]</b>
<p>
<p><center>
[websvn:showcompactlink]
[websvn:showalllink]
</center>
<p>
<table class="diff" width="100%" cellspacing="0">
<tr>
<th class="HdrClmnEnd" style="padding-bottom: 5px" width="50%" align="left"><b>[lang:REV] [websvn:rev2]</b></th>
<th width="5"></th>
<th class="HdrClmnEnd" style="padding-bottom: 5px" width="50%" align="left"><b>[lang:REV] [websvn:rev1]</b></th>
</tr>
[websvn-startlisting]
[websvn-test:rev1lineno]
<tr>
<td width="50%" style="padding: 3px 0 3px 0" align="center" class="row1"><b>[lang:LINE] [websvn:rev1lineno]...</b></td>
<td width="5"></td>
<td width="50%" style="padding: 3px 0 3px 0" align="center" class="row1"><b>[lang:LINE] [websvn:rev2lineno]...</b></td>
<tr>
[websvn-else]
<tr><td class="[websvn:rev1diffclass]">[websvn:rev1line]</td>
<td width="5"></td>
<td class="[websvn:rev2diffclass]">[websvn:rev2line]</td></tr>
[websvn-endtest]
[websvn-endlisting]
</table>
[websvn-endtest]
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
<div id="nav">
[websvn-test:prevrevurl]
<a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a> &ndash;
[websvn-endtest]
[websvn-test:nextrevurl]
<a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a> &ndash;
[websvn-endtest]
[websvn-test:goyoungestlink]
[websvn:goyoungestlink] &ndash;
[websvn-endtest]
[websvn:filedetaillink] &ndash;
[websvn:blamelink] &ndash;
[websvn-test:downloadlink]
[websvn:downloadlink] &ndash;
[websvn-endtest]
[websvn:revlink] &ndash;
[websvn:loglink]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rssurl]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
[websvn-test:noprev]
<div id="warning">[lang:NOPREVREV].</div>
[websvn-else]
<center>
[websvn-test:showcompactlink]
[websvn:showcompactlink] &ndash;
[websvn-endtest]
[websvn-test:showalllink]
[websvn:showalllink] &ndash;
[websvn-endtest]
[websvn-test:regardwhitespacelink]
[websvn:regardwhitespacelink]
[websvn-endtest]
[websvn-test:ignorewhitespacelink]
[websvn:ignorewhitespacelink]
[websvn-endtest]
</center>
<table class="diff" cellspacing="0">
<thead>
<tr>
<th width="50%" colspan="2"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:rev2]</a></th>
<td width="5"></td>
<th width="50%" colspan="2"><a href="[websvn:revurl]">[lang:REV] [websvn:rev1]</a></th>
</tr>
</thead>
[websvn-startlisting]
[websvn-test:startblock]
<tr>
<th class="row1" colspan="2">[lang:LINE] [websvn:rev1lineno]...</th>
<td width="5" style="background: none;"></td>
<th class="row1" colspan="2">[lang:LINE] [websvn:rev2lineno]...</th>
</tr>
[websvn-endtest]
<tr>
<td class="lineno">[websvn:rev1lineno]</td>
<td class="[websvn:rev1diffclass]">[websvn:rev1line]</td>
<td width="5"></td>
<td class="lineno">[websvn:rev2lineno]</td>
<td class="[websvn:rev2diffclass]">[websvn:rev2line]</td>
</tr>
[websvn-endlisting]
</table>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
 
/WebSVN/templates/BlueGrey/directory.tmpl
1,142 → 1,142
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
 
[websvn-test:noaccess]
[lang:NOACCESS]
<h1>[websvn:repname] &ndash; [lang:REV] [websvn:rev]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<table cellpadding="2px" cellspacing="0px" class="outline">
<tr><th colspan=2 class="HdrClmnEnd">[lang:REVINFO]</th></tr>
<tr><td class="CatClmn1" valign="top">[lang:CURDIR]:</td><td class="row1">[websvn:path]</td></tr>
<tr><td class="CatClmn0">[lang:REV] &amp; [lang:AUTHOR]:</td><td class="row0">[lang:REV] [websvn:rev] - [websvn:author]
[websvn-test:goyoungestlink]
- [websvn:goyoungestlink]
[websvn-endtest]
</td></tr>
[websvn-test:restricted]
[websvn-else]
<tr><td class="CatClmn1" valign="top">[lang:LASTMOD]:</td><td class="row1">[lang:REV] [websvn:lastchangedrev] - [websvn:date]</td></tr>
<tr><td class="CatClmn0" valign="top">[lang:LOGMSG]:</td><td class="row0">[websvn:log]</td></tr>
[websvn-test:hidechanges]
<tr><td class="CatClmn1" valign="top">&nbsp;</td><td class="row1">([websvn:showchangeslink])</td></tr>
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
[websvn-test:search]
<div id="searchcss">[websvn:search_form]<div>[lang:SEARCH] [websvn:search_input]<span class="submit">[websvn:search_submit]</span></div>[websvn:search_endform]</div>
[websvn-endtest]
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
[websvn-test:warning]
[websvn-else]
<table cellpadding="2" cellspacing="0" class="outline">
<thead>
<tr><th colspan="2">[lang:REVINFO]</th></tr>
</thead>
[websvn-test:restricted]
[websvn-else]
[websvn:showchangeslink]
<tr><td class="CatClmn1" valign="top">&nbsp;</td><td class="row1">([websvn:hidechangeslink])</td></tr>
[websvn-test:changedfilesbr]
<tr><td class="CatClmn0" valign="top">[lang:CHANGEDFILES]:</td><td class="row0">[websvn:changedfilesbr]</td></tr>
[websvn-endtest]
[websvn-test:newfilesbr]
[websvn-test:changedfilesbr]
<tr><td class="CatClmn1" valign="top">[lang:NEWFILES]:</td><td class="row1">[websvn:newfilesbr]</td></tr>
[websvn-else]
<tr><td class="CatClmn0" valign="top">[lang:NEWFILES]:</td><td class="row0">[websvn:newfilesbr]</td></tr>
[websvn-endtest]
[websvn-endtest]
[websvn-test:deletedfilesbr]
[websvn-test:changedfilesbr]
[websvn-test:newfilesbr]
<tr><td class="CatClmn0" valign="top">[lang:DELETEDFILES]:</td><td class="row0">[websvn:deletedfilesbr]</td></tr>
[websvn-else]
<tr><td class="CatClmn1" valign="top">[lang:DELETEDFILES]:</td><td class="row1">[websvn:deletedfilesbr]</td></tr>
[websvn-endtest]
[websvn-else]
[websvn-test:newfilesbr]
<tr><td class="CatClmn1" valign="top">[lang:DELETEDFILES]:</td><td class="row1">[websvn:deletedfilesbr]</td></tr>
[websvn-else]
<tr><td class="CatClmn0" valign="top">[lang:DELETEDFILES]:</td><td class="row0">[websvn:deletedfilesbr]</td></tr>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
<tr class="row0"><th>[lang:LASTMOD]:</th><td>[lang:REV] [websvn:lastchangedrev] &ndash; [websvn:author] &ndash; [websvn:date]
[websvn-test:prevrevurl]
&ndash; <a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a>
[websvn-endtest]
[websvn-endtest]
</table>
[websvn-defineicons]
dir=<img align="middle" valign="center" src="[websvn:locwebsvnhttp]/templates/BlueGrey/folder.png" alt="[FOLDER]">
diropen=<img align="middle" valign="center" src="[websvn:locwebsvnhttp]/templates/BlueGrey/folder.png" alt="[OPEN-FOLDER]">
*=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/file.png" alt="[FILE]">
.c=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filec.png" alt="[C-FILE]">
.cpp=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filecpp.png" alt="[CPP-FILE]">
.h=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/fileh.png" alt="[H-FILE]">
.html=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filehtml.png" alt="[HTML-FILE]">
.java=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filejava.png" alt="[JAVA-FILE]">
.m=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filem.png" alt="[M-FILE]">
.py=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/filepy.png" alt="[PY-FILE]">
.s=<img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/files.png" alt="[S-FILE]">
i-node=<img align="middle" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/i-node.png" alt="[NODE]">
t-node=<img align="middle" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/t-node.png" alt="[NODE]">
l-node=<img align="middle" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/l-node.png" alt="[NODE]">
e-node=<img align="middle" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/e-node.png" alt="[NODE]">
[websvn-enddefineicons]
<p><hr>
[websvn:curdirlinks] - [websvn:curdirloglink]
[websvn-test:curdircomplink]
- [websvn:curdircomplink]
[websvn-endtest]
[websvn-test:curdirdllink]
- [websvn:curdirdllink]
[websvn-endtest]
[websvn-test:curdirrsslink]
- [websvn:curdirrssanchor]<img style="border: 0;" src="[websvn:locwebsvnhttp]/templates/BlueGrey/xml.gif" width="36" height="14" alt="[lang:RSSFEED]"></a>
[websvn-endtest]
<p>
[websvn:compare_form]
<table cellpadding="2px" cellspacing="0px" width="100%" class="outline">
<tr>
<th class="HdrClmn" width="100%"><b>[lang:PATH]</b></th>
[websvn-test:allowdownload]
[websvn-test:curdirrsslink]
<th class="HdrClmn"><b>[lang:NOBR][lang:LOG][lang:ENDNOBR]</b></th>
<th class="HdrClmn"><b>[lang:TARBALL]</b></th>
<th class="HdrClmnEnd"><b>RSS</b></th>
[websvn-else]
<th class="HdrClmn"><b>[lang:NOBR][lang:LOG][lang:ENDNOBR]</b></th>
<th class="HdrClmnEnd"><b>[lang:TARBALL]</b></th>
[websvn-endtest]
[websvn-else]
[websvn-test:curdirrsslink]
<th class="HdrClmn"><b>[lang:LOG]</b></th>
<th class="HdrClmnEnd"><b>RSS</b></th>
[websvn-else]
<th class="HdrClmnEnd"><b>[lang:NOBR][lang:LOG][lang:ENDNOBR]</b></th>
[websvn-endtest]
[websvn-endtest]
</tr>
[websvn-startlisting]
<tr>
<td valign="middle" style="border-right: 1px solid black; padding: 0 2px 0 2px;" class="row[websvn:rowparity]">
[websvn:compare_box]
[websvn-treenode]
[websvn-icon]
[websvn:filelink]
</td>
[websvn-test:allowdownload]
[websvn-test:curdirrsslink]
<td style="border-right: 1px solid black; padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[lang:NOBR][websvn:fileviewloglink][lang:ENDNOBR]</td>
<td style="border-right: 1px solid black; padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[websvn:fileviewdllink]</td>
<td style="padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[websvn:rssanchor]<img style="border: 0;" src="[websvn:locwebsvnhttp]/templates/BlueGrey/xml.gif" width="36" height="14" alt="[lang:RSSFEED]"></a></td>
[websvn-else]
<td style="border-right: 1px solid black; padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[lang:NOBR][websvn:fileviewloglink][lang:ENDNOBR]</td>
<td style="padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[websvn:fileviewdllink]</td>
[websvn-endtest]
[websvn-else]
[websvn-test:curdirrsslink]
<td style="border-right: 1px solid black; padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[lang:NOBR][websvn:fileviewloglink][lang:ENDNOBR]</td>
<td style="padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[websvn:rssanchor]<img style="border: 0;" src="[websvn:locwebsvnhttp]/templates/BlueGrey/xml.gif" width="36" height="14" alt="[lang:RSSFEED]"></a></td>
[websvn-else]
<td style="padding: 0 2px 0 2px;" class="row[websvn:rowparity]">[lang:NOBR][websvn:fileviewloglink][lang:ENDNOBR]</td>
[websvn-endtest]
[websvn-endtest]
</tr>
[websvn-endlisting]
[websvn-test:nextrevurl]
&ndash; <a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a>
[websvn-endtest]
[websvn-test:goyoungestlink]
&ndash; [websvn:goyoungestlink]
[websvn-endtest]
</td></tr>
<tr class="row1"><th>[lang:LOGMSG]:</th><td>[websvn:log]</td></tr>
[websvn-endtest]
</table>
[websvn-endtest]
 
<div id="nav">
[websvn:revlink] &ndash;
[websvn-test:comparelink]
[websvn:comparelink] &ndash;
[websvn-endtest]
[websvn:loglink]
[websvn-test:downloadurl]
&ndash; <a href="[websvn:downloadurl]" rel="nofollow">[lang:DOWNLOAD]</a>
[websvn-endtest]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rssurl]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
[websvn-defineicons]
dir=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/directory.png" alt="[DIRECTORY]"/>
diropen=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/directory.png" alt="[OPEN-DIRECTORY]"/>
*=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/file.png" alt="[FILE]"/>
.c=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filec.png" alt="[C-FILE]"/>
.cpp=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filecpp.png" alt="[CPP-FILE]"/>
.h=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/fileh.png" alt="[H-FILE]"/>
.html=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filehtml.png" alt="[HTML-FILE]"/>
.java=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filejava.png" alt="[JAVA-FILE]"/>
.m=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filem.png" alt="[M-FILE]"/>
.py=<img class="icon" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/filepy.png" alt="[PY-FILE]"/>
 
i-node=<img class="icon" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/i-node.png" alt="[NODE]"/>
t-node=<img class="icon" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/t-node.png" alt="[NODE]"/>
l-node=<img class="icon" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/l-node.png" alt="[NODE]"/>
e-node=<img class="icon" border="0" width="24" height="22" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/e-node.png" alt="[NODE]"/>
[websvn-enddefineicons]
[websvn:compare_form]
<table cellpadding="2" cellspacing="0" id="listing">
<thead>
<tr>
<th class="path">[lang:PATH]</th>
[websvn-test:showlastmod]
<th class="last_mod" scope="col" colspan="3">[lang:LASTMOD]</th>
[websvn-endtest]
<th class="view_log" nowrap="nowrap">[lang:VIEWLOG]</th>
[websvn-test:allowdownload]
<th class="download">[lang:DOWNLOAD]</th>
[websvn-endtest]
[websvn-test:clientrooturl]
<th>SVN</th>
[websvn-endtest]
[websvn-test:rssurl]
<th>RSS</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr class="row[websvn:rowparity]"
[websvn-test:loadalldir]
title="[websvn:classname]"
[websvn-endtest]
>
<td class="path" valign="middle">
[websvn:compare_box]
[websvn-treenode]
<a href="[websvn:fileurl]">
[websvn-icon]
[websvn:filename]
</a>
</td>
[websvn-test:showlastmod]
<td class="rev"><a href="[websvn:revurl]">[websvn:revision]</a>&nbsp;</td>
[websvn-test:showageinsteadofdate]
<td class="age" title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td class="date" title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td class="author">[websvn:author]</td>
[websvn-endtest]
<td><a href="[websvn:logurl]">[lang:LOG]</a></td>
[websvn-test:allowdownload]
<td>
[websvn-test:downloadurl]
<a href="[websvn:downloadurl]" rel="nofollow">[lang:DOWNLOAD]</a>
[websvn-endtest]
[websvn-test:downloadplainurl]
<a href="[websvn:downloadplainurl]" rel="nofollow">[lang:DOWNLOAD]</a>
[websvn-endtest]
</td>
[websvn-endtest]
[websvn-test:clientrooturl]
<td><a href="[websvn:clientrooturl][websvn:path]">SVN</a></td>
[websvn-endtest]
[websvn-test:rssurl]
<td><a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
<p>
[websvn:compare_submit]
[websvn:compare_endform]
<hr>
[websvn:compare_submit][websvn:compare_endform]
[websvn-endtest]
[websvn-test:loadalldir]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/file.tmpl
1,19 → 1,48
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
 
[websvn-test:noaccess]
[lang:NOACCESS]
<h1>[websvn:repname] &ndash; [lang:REV] [websvn:rev]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
[websvn:curdirlinks] - [lang:REV] [websvn:rev]
[websvn-test:goyoungestlink]
[websvn:goyoungestlink]<p>
[websvn-endtest]
<p>[websvn:prevdifflink] - [websvn:blamelink]</p>
<hr />
[websvn-getlisting]
<hr />
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
<div id="nav">
[websvn-test:prevrevurl]
<a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a> &ndash;
[websvn-endtest]
[websvn-test:nextrevurl]
<a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a> &ndash;
[websvn-endtest]
[websvn-test:goyoungestlink]
[websvn:goyoungestlink] &ndash;
[websvn-endtest]
[websvn-test:mimelink]
[websvn:mimelink] &ndash;
[websvn-endtest]
[websvn:blamelink] &ndash;
[websvn-test:difflink]
[websvn:difflink] &ndash;
[websvn-endtest]
[websvn:revlink] &ndash;
[websvn:loglink]
[websvn-test:downloadlink]
&ndash; [websvn:downloadlink]
[websvn-endtest]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rssurl]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div id="listing">
[websvn-getlisting]
</div>
[websvn-test:warning]
<!-- check for warnings generated by getlisting -->
<div id="warning">[websvn:warning]</div>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/footer.tmpl
1,3 → 1,4
<p><center><font size="-1"><i><b>[lang:POWERED] v[websvn:version]</b></i></font></center>
</body>
</div>
<div id="footer">[lang:POWERED] [websvn:version] [lang:AND] <a href="http://subversion.apache.org">Apache Subversion</a> [websvn:svnversion] &nbsp; &nbsp; &#x2713; <a href="http://validator.w3.org/check?uri=[websvn:validationurl]">XHTML</a> &amp; <a href="http://jigsaw.w3.org/css-validator/validator?uri=[websvn:validationurl]">CSS</a></div>
</body>
</html>
/WebSVN/templates/BlueGrey/header.tmpl
1,73 → 1,58
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=[websvn:charset]">
<link href="[websvn:locwebsvnhttp]/templates/BlueGrey/styles.css" rel="stylesheet" media="screen">
<!--[if lt IE 7]>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/templates/BlueGrey/png.js"></script>
<![endif]-->
<script type="text/javascript" src="[websvn:locwebsvnhttp]/templates/BlueGrey/collapse.js"></script>
<title>
WebSVN
[websvn-test:repname]
- [websvn:repname]
[websvn-endtest]
[websvn-test:action]
- [websvn:action]
[websvn-endtest]
[websvn-test:rev2]
[websvn-test:path2]
- [websvn:safepath1] [lang:REV] [websvn:rev1] [lang:AND] [websvn:safepath2] [lang:REV] [websvn:rev2]
[websvn-else]
- [lang:REV] [websvn:rev1] [lang:AND] [websvn:rev2]
[websvn-endtest]
[websvn-else]
[websvn-test:rev]
- [lang:REV] [websvn:rev]
[websvn-endtest]
[websvn-endtest]
[websvn-test:path]
- [websvn:safepath]
[websvn-endtest]
</title>
 
<script type="text/javascript">
function checkCB(chBox)
{
count = 0
first = null
f = chBox.form
for (i = 0 ; i < f.elements.length ; i++)
if (f.elements[i].type == 'checkbox' && f.elements[i].checked)
{
if (first == null && f.elements[i] != chBox)
first = f.elements[i]
count += 1
}
if (count > 2)
{
first.checked = false
count -= 1
}
}
[websvn-test:opentree]
expandonload = true
[websvn-endtest]
</script>
 
[websvn-test:curdirrsslink]
<link rel="alternate" type="application/rss+xml" title="WebSVN RSS" href="[websvn:curdirrsshref]">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[websvn:language_code]" lang="[websvn:language_code]">
<head>
<title>
WebSVN
[websvn-test:repname]
&ndash; [websvn:repname]
[websvn-endtest]
[websvn-test:error]
&ndash; ERROR
[websvn-else]
[websvn-test:action]
&ndash; [websvn:action]
[websvn-endtest]
 
[websvn-test:rev2]
[websvn-test:safepath2]
&ndash; [websvn:safepath1] [lang:REV] [websvn:rev1] [lang:AND] [websvn:safepath2] [lang:REV] [websvn:rev2]
[websvn-else]
&ndash; [lang:REV] [websvn:rev1] [lang:AND] [websvn:rev2]
[websvn-endtest]
[websvn-else]
[websvn-test:rev]
&ndash; [lang:REV] [websvn:rev]
[websvn-endtest]
[websvn-endtest]
[websvn-test:safepath]
&ndash; [websvn:safepath]
[websvn-endtest]
[websvn-endtest]
</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
<meta http-equiv="generator" content="WebSVN [websvn:version]"/> <!-- leave this for stats -->
[websvn-test:blockrobots]
<meta name="robots" content="noindex,nofollow"/>
[websvn-endtest]
<link rel="shortcut icon" type="image/x-icon" href="[websvn:locwebsvnhttp]/templates/BlueGrey/images/favicon.ico"/>
<link type="text/css" href="[websvn:locwebsvnhttp]/templates/BlueGrey/styles.css" rel="stylesheet" media="screen"/>
[websvn-test:rssurl]
<link rel="alternate" type="application/rss+xml" title="WebSVN RSS" href="[websvn:rssurl]"/>
[websvn-endtest]
<!--[if lt IE 7]>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/ie-png-transparency.js"></script>
<![endif]-->
</head>
<body>
<table width="100%" border="0">
<tr>
<td width="33%">&nbsp;</td>
<td width="33%" align="center"><a href="http://subversion.tigris.org/"><img style="border: 0; width: 468px; height: 64px;" src="[websvn:locwebsvnhttp]/templates/BlueGrey/subversion.png" alt="Subversion" /></a></td>
<td width="33%"><div style="float: right">[websvn:lang_form][websvn:lang_select][websvn:lang_submit][websvn:lang_endform]</div></td>
</tr>
</table>
<hr />
<body id="[websvn:template]">
<div id="header">
<table border="0">
<tr>
<td width="33%">&nbsp;</td>
<td width="33%" align="center"><a href="[websvn:indexurl]" title="[lang:PROJECTS]"><img style="border: 0; width: 272px; height: 64px;" src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/websvn.png" alt="WebSVN" /></a></td>
<td width="33%"><div style="float: right">
[websvn:language_form][websvn:language_select][websvn:language_submit][websvn:language_endform]
[websvn:template_form][websvn:template_select][websvn:template_submit][websvn:template_endform]
</div></td>
</tr>
</table>
</div>
<div id="content">
/WebSVN/templates/BlueGrey/images/directory-open.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/directory.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/e-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/favicon.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/file.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filec.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filecpp.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/fileh.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filehtml.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filejava.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filem.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/filepy.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/i-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/l-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/repo.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/rss.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/t-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/images/websvn.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/BlueGrey/index.tmpl
1,26 → 1,69
<p>
[websvn-test:flatview]
<table align="center" cellspacing="0" cellpadding="0" width="50%">
<tr><th align="center" colspan=2 class="HdrClmnEnd">[lang:PROJECTS]</th></tr>
[websvn-startlisting]
<tr><td class="row[websvn:rowparity]"><img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/repo.png" alt="[FOLDER]"> [websvn:projlink]</td>
</tr>
[websvn-endlisting]
</table>
[websvn-else]
<table align="center" cellspacing=0 cellpadding=0 width="50%">
<tr><th align="left" colspan=2 class="HdrClmnEnd">[lang:PROJECTS]</th></tr>
<td>
[websvn-startlisting]
[websvn-test:isprojlink]
<div class="row[websvn:rowparity]"><img align="middle" src="[websvn:locwebsvnhttp]/templates/BlueGrey/repo.png" alt="[FOLDER]"> [websvn:listitem]</div>
[websvn-else]
[websvn:listitem]
[websvn-endtest]
[websvn-endlisting]
</td>
</tr>
</table>
[websvn-endtest]
<hr />
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<table>
[websvn-test:showlastmod]
<thead><tr><th colspan="4">[lang:PROJECTS]</th></tr></thead>
[websvn-else]
<thead><tr><th>[lang:PROJECTS]</th></tr></thead>
[websvn-endtest]
[websvn-test:flatview]
[websvn-startlisting]
[websvn-test:groupid]
[websvn-else]
<tr class="row[websvn:rowparity]">
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-else]
[websvn-startlisting]
[websvn-test:groupid]
[websvn-test:showlastmod]
<tr><th onclick="toggleGroup('[websvn:groupname]');" colspan="4">[websvn:groupname]</th></tr>
[websvn-else]
<tr><th onclick="toggleGroup('[websvn:groupname]');">[websvn:groupname]</th></tr>
[websvn-endtest]
[websvn-else]
<tr title="[websvn:groupname]" class="row[websvn:groupparity]">
[websvn-test:groupname]
<td class="project group"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-else]
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-endtest]
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-endtest]
</table>
[websvn-test:treeview]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-test:opentree]
[websvn-else]
<script type="text/javascript">
//<![CDATA[
collapseAllGroups();
//]]>
</script>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/log.tmpl
1,70 → 1,96
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="left"><h1>[websvn:repname] - [lang:REV] [websvn:rev]</h1></td>
<td align="right"><b>[lang:PROJECTS]:</b> [websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</td>
</tr>
</table>
 
[websvn:curdirlinks]<p>
[websvn-test:goyoungestlink]
[websvn:goyoungestlink]<p>
[websvn-endtest]
<hr>
[websvn-test:noaccess]
[lang:NOACCESS]
<h1>[websvn:repname]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<center>
[websvn:logsearch_form]
<b>[lang:FILTER]</b><p>
[lang:STARTLOG]:[websvn:logsearch_startbox] [lang:ENDLOG]:[websvn:logsearch_endbox] [lang:MAXLOG]:[websvn:logsearch_maxbox] [lang:SEARCHLOG]:[websvn:logsearch_inputbox]
[websvn:logsearch_submit]
[websvn-test:logsearch_clearloglink]
<p><font size="-1">[websvn:logsearch_clearloglink]</font><p>
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
<div id="nav">
[websvn-test:goyoungestlink]
[websvn:goyoungestlink] &ndash;
[websvn-endtest]
[websvn:logsearch_endform]
</center>
[websvn-test:logsearch_nomatches]
<center>[lang:NORESULTS]</center>
[websvn-endtest]
[websvn-test:error]
<center>[websvn:error]</center>
[websvn-endtest]
[websvn:changeslink] &ndash;
[websvn-test:filedetaillink]
[websvn:filedetaillink] &ndash;
[websvn:blamelink] &ndash;
[websvn:difflink]
[websvn-else]
[websvn:directorylink]
[websvn-endtest]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rsslink]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<center>
[websvn:logsearch_form]
[lang:STARTLOG]:[websvn:logsearch_startbox] [lang:ENDLOG]:[websvn:logsearch_endbox] [lang:MAXLOG]:[websvn:logsearch_maxbox] [lang:SEARCHLOG]:[websvn:logsearch_inputbox] [lang:SHOWALL]:[websvn:logsearch_showall]
[websvn:logsearch_submit]
[websvn-test:logsearch_clearloglink]
<br/>[websvn:logsearch_clearloglink]
[websvn-endtest]
[websvn:logsearch_endform]
[websvn-test:logsearch_nomatches]
<p>[lang:NORESULTS]</p>
[websvn-endtest]
[websvn-test:logsearch_nomorematches]
<p>[lang:NOMORERESULTS]</p>
[websvn-endtest]
[websvn:logsearch_moreresultslink]
<span id="logpagelinks">[websvn:pagelinks]</span> &nbsp; &nbsp; [websvn:showalllink]
</center>
 
[websvn-test:logsearch_resultsfound]
[websvn:compare_form]
<table cellpadding="2px" cellspacing="0" width="100%">
<tr>
<th class="HdrClmn">[lang:REV]</th>
<th class="HdrClmn">[lang:PATH]</th>
<th class="HdrClmn">[lang:AUTHOR]</th>
<th class="HdrClmn">[lang:AGE]</th>
<th class="HdrClmnEnd">[lang:LOGMSG]</th>
</tr>
[websvn-startlisting]
<tr>
<td style="border-right: 1px solid black" valign="top" class="row[websvn:rowparity]"><nobr>[websvn:compare_box][websvn:revlink]</nobr></td>
<td style="border-right: 1px solid black" valign="top" class="row[websvn:rowparity]">[websvn:revpathlink]</td>
<td style="border-right: 1px solid black" valign="top" class="row[websvn:rowparity]">[websvn:revauthor]</td>
<td style="border-right: 1px solid black" valign="top" class="row[websvn:rowparity]">[websvn:revage]</td>
<td valign="top" class="row[websvn:rowparity]">[websvn:revlog]</td>
</tr>
[websvn-endlisting]
</table>
<p>
[websvn:compare_submit]
[websvn:compare_endform]
[websvn-endtest]
[websvn-test:logsearch_nomorematches]
<p><center>[lang:NOMORERESULTS]</center>
[websvn-endtest]
<p><center>[websvn:logsearch_moreresultslink]</center>
<hr>
<p><center>[websvn:pagelinks]<p>[websvn:showalllink]</center>
[websvn-test:logsearch_resultsfound]
[websvn:compare_form]
<table cellpadding="2" cellspacing="0">
<thead>
<tr>
<th>[lang:REV]</th>
<th>[lang:AGE]</th>
<th>[lang:AUTHOR]</th>
<th>[lang:PATH]</th>
<th>[lang:LOGMSG]</th>
<th>[lang:DIFF]</th>
[websvn-test:showchanges]
<th>[lang:CHANGES]</th>
[websvn-endtest]
</tr>
</thead>
[websvn-startlisting]
<tr class="row[websvn:rowparity]">
<td style="white-space: nowrap;">[websvn:compare_box][websvn:revlink]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:revdate]">[websvn:revage]</td>
[websvn-else]
<td title="[websvn:revage]">[websvn:revdate]</td>
[websvn-endtest]
<td>[websvn:revauthor]</td>
<td>[websvn:revpathlink]</td>
<td valign="top">[websvn:revlog]</td>
<td><a href="[websvn:compareurl]" title="[lang:DIFFPREV]">[lang:DIFF]</a></td>
[websvn-test:showchanges]
<td class="changes"><table>
[websvn-test:revadded]
<tr><td>A</td><td>[websvn:revadded]</td></tr>
[websvn-endtest]
[websvn-test:revdeleted]
<tr><td>D</td><td>[websvn:revdeleted]</td></tr>
[websvn-endtest]
[websvn-test:revmodified]
<tr><td>M</td><td>[websvn:revmodified]</td></tr>
[websvn-endtest]
</table></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</table>
<center>[websvn:compare_submit]</center>
[websvn:compare_endform]
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/revision.tmpl
0,0 → 1,102
<h1>[websvn:repname] &ndash; [lang:REV] [websvn:rev]</h1>
<div id="projects">[websvn:projects_form]<b>[lang:PROJECTS]:</b> [websvn:projects_select][websvn:projects_submit][websvn:projects_endform]</div>
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<div id="revjump">[websvn:revision_form]<b>[lang:REV]:</b>[websvn:revision_input][websvn:revision_submit][websvn:revision_endform]</div>
<div id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</div>
[websvn-test:warning]
[websvn-else]
<table cellpadding="2" cellspacing="0" class="outline">
<thead>
<tr><th colspan="2">[lang:REVINFO]</th></tr>
</thead>
[websvn-test:restricted]
[websvn-else]
<tr class="row0"><th>[lang:LASTMOD]:</th><td>[lang:REV] [websvn:rev] &ndash; [websvn:author]
[websvn-test:showageinsteadofdate]
&ndash; <span title="[websvn:date]">[websvn:age]</span>
[websvn-else]
&ndash; <span title="[websvn:age]">[websvn:date]</span>
[websvn-endtest]
[websvn-test:prevrevurl]
&ndash; <a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a>
[websvn-endtest]
[websvn-test:nextrevurl]
&ndash; <a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a>
[websvn-endtest]
[websvn-test:goyoungestlink]
&ndash; [websvn:goyoungestlink]
[websvn-endtest]
</td></tr>
<tr class="row1"><th>[lang:LOGMSG]:</th><td>[websvn:log]</td></tr>
[websvn-endtest]
</table>
[websvn-endtest]
<div id="nav">
[websvn-test:comparelink]
[websvn:comparelink] &ndash;
[websvn-endtest]
[websvn:directorylink] &ndash;
[websvn:loglink]
[websvn-test:filedetaillink]
&ndash; [websvn:filedetaillink]
[websvn-endtest]
[websvn-test:blamelink]
&ndash; [websvn:blamelink]
[websvn-endtest]
[websvn-test:clientrooturl]
&ndash; <a href="[websvn:clientrooturl][websvn:path]">SVN</a>
[websvn-endtest]
[websvn-test:rssurl]
&ndash; <a href="[websvn:rssurl]"><img src="[websvn:locwebsvnhttp]/templates/BlueGrey/images/rss.gif" width="27" height="15" alt="[lang:RSSFEED]"/></a>
[websvn-endtest]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<table cellpadding="2" cellspacing="0" class="outline">
<thead>
<tr>
<th>[lang:PATH]</th>
<th>[lang:BLAME]</th>
<th>[lang:DIFF]</th>
<th>[lang:VIEWLOG]</th>
[websvn-test:clientrooturl]
<th>SVN</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr class="[websvn:action] row[websvn:rowparity]">
<td>[websvn:action]
[websvn-test:notinpath]
<a href="[websvn:detailurl]" class="notinpath">[websvn:safepath]</a>
[websvn-else]
<a href="[websvn:detailurl]">[websvn:safepath]</a>
[websvn-endtest]
[websvn-test:oldsafepath]
<br/>&nbsp; &nbsp;<del>[websvn:oldsafepath] ([lang:PREV])</del>
[websvn-endtest]
</td>
[websvn-test:blameurl]
<td><a href="[websvn:blameurl]">[lang:BLAME]</a></td>
[websvn-else]
<td></td>
[websvn-endtest]
[websvn-test:diffurl]
<td><a href="[websvn:diffurl]">[lang:DIFF]</a></td>
[websvn-else]
<td></td>
[websvn-endtest]
<td><a href="[websvn:logurl]">[lang:LOG]</a></td>
[websvn-test:clientrooturl]
<td><a href="[websvn:clientrooturl][websvn:path]">SVN</a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/BlueGrey/styles.css
1,131 → 1,401
body
{
font-family: verdana, sans-serif;
color: black;
background-color: white
/* @group General Styles */
 
body {
margin: 0;
font-family: Verdana, Helvetica, Arial, sans-serif;
font-size: 10pt;
color: black;
background-color: white;
}
body *
{
font-size: 10pt;
h1 {
font-size: 150%;
margin: 0;
float: left;
}
h1
{
font-size: 150%;
h2 {
font-size: 125%;
}
h2
{
font-size: 125%;
h3 {
font-size: 105%;
}
hr
{
border: 0px;
padding: 0px;
height: 1px;
background-color: #808080
a:link, a:visited {
color: #004080;
text-decoration: none;
}
a:link, a:visited
{
color: #004080;
text-decoration: none;
a:hover, a:active {
text-decoration: underline;
}
a:hover, a:active
{
text-decoration: underline;
thead th a:link, thead th a:visited {
color: white;
}
.HdrClmn,
.HdrClmnEnd
{
border: black 1px solid;
font-weight: bold;
color: white;
background-color: #809cc8
a img {
border: none;
}
table
{
border-width:0px;
border-collapse:collapse;
 
table {
border-width: 0px;
border-collapse: collapse;
width: 100%;
}
.row0,
.row1
{
height:22px;
border-width:0px;
 
pre {
padding: 4px;
background-color: #eee;
border: solid 1px #ccc;
}
.row0 img,
.row1 img {
padding: 0px;
margin: 0px;
vertical-align:middle;
 
code {
white-space: pre-wrap;
}
.row0
{
background-color: #f0f0f0;
 
/* Semantic sections */
 
#header {
padding: 5px 0;
border-bottom: 1px solid #555;
}
.row1
{
background-color: #e0e0e0;
 
#projects, #revjump {
float: right;
}
 
.CatClmn0
{
border-right: black 1px solid;
background-color: #e0e0ff
#revjump, #error {
clear: both;
}
 
.CatClmn1
{
border-right: black 1px solid;
background-color: #d0d0ee
#path_links {
clear: left;
padding-top: 5px;
}
#nav {
margin: 10px 0;
}
 
table.outline
{
border-collapse:collapse;
border: 1px black solid;
#content {
margin: 10px;
}
#content table {
border: 1px solid #555;
margin: 10px 0;
}
#content th, #content td {
padding: 0 3px;
}
#content thead th {
border: 1px solid #555;
font-weight: bold;
color: white;
background-color: #809cc8;
padding: 1px 4px 2px 1px;
}
#content thead th.path {
text-align: left;
width: 60%;
}
#content thead th.last_mod {
width: 25%;
}
#content thead th.view_log,
#content thead th.download,
#content thead th.rss {
width: 5%;
}
 
td.diffdeleted
{
font-size: 11px;
background-color: #ff8888;
.row0, .row1 {
border-width: 0px;
}
.row0 img, .row1 img {
padding: 0px;
margin: 0px;
vertical-align: middle;
}
.row0 {
background-color: #f0f0f0;
}
.row1 {
background-color: #e0e0e0;
}
 
td.diffchanged
{
font-size: 11px;
background-color: #ffff88;
tr.row0 th, tr.row1 th, #content td {
font-weight: normal;
text-align: left;
vertical-align: top;
border-right: 1px solid #555;
}
tr.row0 th {
background-color: #e0e0ff
}
tr.row1 th {
background-color: #d0d0ee;
}
th.row1 {
background-color: #d0d0ee;
border-right: 1px solid #555;
}
div.clearer {
clear: both;
height: 0;
}
 
td.diffadded
{
font-size: 11px;
background-color: #88ff88;
#footer {
padding: 3px;
text-align: center;
font-size: 80%;
font-weight: bold;
background-color: #e5e9fe;
border: solid #555;
border-width: 1px 0;
}
 
td.diff
{
font-size: 11px;
background-color: #F0F0F0;
div#error, div#warning {
font-weight: bold;
display: table;
padding: 5px;
margin: 10px auto;
border: 1px solid;
}
 
div.newpath
{
padding: 10px;
background-color: #d0d0ee
div#error {
border-color: #b2595a;
background-color: #ffe2e2;
}
 
div.difflines
{
div#warning {
border-color: #b2ac00;
background-color: #ffd;
}
 
.plusbox { float: left; clear: both; position: relative; top: -3px; font-size: 13px; font-weight: bold; width: 16px; text-indent: 0; height: 16px; color: black; background-color: #D0D0D0; text-align: center; padding: 0px 2px 0px 3px; border: black solid 1px; margin-right: 5px; }
.minusbox { float: left; clear: both; position: relative; top: -3px; font-size: 13px; font-weight: bold; width: 16px; text-indent: 0; height: 16px; color: black; background-color: #809cc8; text-align: center; padding: 0px 2px 0px 3px; border: black solid 1px; margin-right: 5px; }
/* @end */
 
.groupname { padding-left: 0px; text-indent: -25px; margin: 3px 0 3px 0;}
.switchcontent { margin: 3px 0 0 20px; }
.project { padding: 2px; }
/* @group blame.tmpl */
 
code
{
white-space: pre-wrap;
}
#blame #content table {
width: 100%;
}
 
#blame #content table tbody th {
font-weight: normal;
text-align: right;
}
 
#blame #content table tbody .light th {
border-right: black 1px solid;
background-color: #e0e0ff;
}
 
#blame #content table tbody .dark th {
border-right: black 1px solid;
background-color: #d0d0ee;
}
 
div.blame-popup {
position: absolute;
text-align: left;
background-color: white;
border: solid 2px #809cc8;
padding: 5px;
max-width: 600px;
}
 
div.blame-popup .date {
font-weight: bold;
}
 
/* @end */
 
/* @group compare.tmpl */
 
#compare #params, #params td {
border-width: 0;
}
 
#compare #params td {
vertical-align: middle;
}
 
#compare .comparison {
width: 100%;
margin: 20px 0 10px;
}
 
#compare .comparison tbody th {
text-align: center;
font-weight: bold;
border: 1px solid #555;
}
 
#compare .comparison td {
font-family: monospace;
font-size: 90%;
white-space: pre-wrap;
}
 
/* Whitespace hacks for IE 4-7 */
 
* html #compare .comparison td {
white-space: pre;
}
 
*:first-child+html #compare .comparison td {
white-space: pre;
}
 
/* @end */
 
/* @group diff.tmpl */
 
#diff td {
font-size: 90%;
}
 
#diff td.lineno {
text-align: right;
vertical-align: top;
}
 
td.diffdeleted {
background-color: #ff8888;
}
 
td.diffchanged {
background-color: #ffff88;
}
td.diffchanged ins {
background-color: #88ff88;
text-decoration: none;
}
td.diffchanged del {
background-color: #ff8888;
text-decoration: none;
}
 
td.diffadded {
background-color: #88ff88;
}
 
td.diff {
background-color: #f0f0f0;
}
 
div.newpath {
padding: 10px;
background-color: #d0d0ee;
}
 
div.difflines {
}
 
#diff th.row1 {
border: solid 1px #555;
}
 
/* @end */
 
/* @group directory.tmpl */
 
#directory table#listing tbody tr {
height: 22px;
}
 
#directory td.age, #directory td.date, #directory td.rev {
border-right-width: 0;
}
 
img.icon {
vertical-align: middle;
}
 
/* @end */
 
/* @group file.tmpl */
 
#file #listing {
font-size: 90%;
border: 1px solid #999;
padding: 5px;
background-color: #f0f0f0;
}
 
/* @end */
 
/* @group index.tmpl */
 
#index #content table {
margin: 0 auto;
}
 
#index #content th {
padding: 4px;
}
 
#index #content td {
padding: 0px;
vertical-align: middle;
padding-right: 6px;
border-width: 0;
text-align: right;
}
 
#index #content td.project {
text-align: left;
}
 
#index #content td a {
background: url(images/repo.png) no-repeat 3px 3px;
width: 100%;
display: block;
padding-top: 6px;
padding-bottom: 6px;
}
 
#index #content td a, #index #content td.group, #index #content tbody th {
padding-left: 32px;
text-align: left;
}
 
#index #content tbody th {
background-color: #D0D0D0;
text-decoration: underline;
}
 
.groupname {
font-weight: bold;
padding-left: 0px;
text-indent: 4px;
margin: 3px 0 3px 0;
}
 
.switchcontent {
margin: 3px 0 0 20px;
}
 
/* @end */
 
/* @group log.tmpl */
 
#logpagelinks > * {
padding: 0 3px;
}
 
#content td.changes table {
margin: 0;
}
 
#content td.changes * {
border-width: 0;
}
 
/* @end */
 
/* @group revision.tmpl */
 
#revision del {
color: #555;
text-decoration: none;
}
 
#revision a.notinpath {
color: #8d0208;
}
 
/* @end */
/WebSVN/templates/Elegant/blame.tmpl
0,0 → 1,65
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev]</a></h2>
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:prevrevurl]
<li class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></li>
[websvn-endtest]
[websvn-test:nextrevurl]
<li class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></li>
[websvn-endtest]
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
<li class="file">[websvn:filedetaillink]</li>
[websvn-test:difflink]
<li class="diff">[websvn:difflink]</li>
[websvn-endtest]
<li class="rev">[websvn:revlink]</li>
<li class="log">[websvn:loglink]</li>
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
<table>
<thead>
<tr>
<th>[lang:REV]</th>
<th>[lang:AUTHOR]</th>
<th>[lang:LINENO]</th>
<th>[lang:LINE]</th>
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr class="[websvn:row_class]">
<td class="rev">[websvn:revision]</td>
<td class="author">[websvn:author]</td>
<td class="line"><a name="l[websvn:lineno]" href="#l[websvn:lineno]"></a>[websvn:lineno]</td>
<td class="code">[websvn:line]</td>
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn-endtest]
[websvn-endtest]
[websvn-test:javascript]
[websvn:javascript]
[websvn-endtest]
/WebSVN/templates/Elegant/compare.tmpl
0,0 → 1,68
[websvn-test:error]
</div>
[websvn-else]
<h2><a href="[websvn:rev1url]">[websvn:safepath1] @ [websvn:rev1]</a> &nbsp; &rarr; &nbsp; <a href="[websvn:rev2url]">[websvn:safepath2] @ [websvn:rev2]</a></h2>
<div class="clearer"></div>
</div>
<ul id="links">
<li class="reverse">[websvn:reverselink]</li>
[websvn-test:ignorewhitespacelink]
<li class="ignore">[websvn:ignorewhitespacelink]</li>
[websvn-else]
<li class="regard">[websvn:regardwhitespacelink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
<div id="compare_form">
[websvn:compare_form]
<table>
<tr>
<td class="path"><label>[lang:COMPPATH]</label> [websvn:compare_path1input]</td>
<td><label>[lang:REV]</label> [websvn:compare_rev1input]</td>
<td rowspan="2">[websvn:compare_submit]</td>
</tr>
<tr>
<td class="path"><label>[lang:WITHPATH]</label> [websvn:compare_path2input]</td>
<td><label>[lang:REV]</label> [websvn:compare_rev2input]</td>
</tr>
</table>
[websvn:compare_endform]
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-endtest]
<div id="comparisons">
[websvn-startlisting]
[websvn-test:newpath]
<table class="collapsible">
<thead>
<tr><th><a href="[websvn:fileurl]">[websvn:newpath]</a></th></tr>
</thead>
<tbody>
[websvn-endtest]
[websvn-test:info]
<tr><th class="info">[websvn:info]</th></tr>
[websvn-endtest]
[websvn-test:difflines]
<tr><th>[websvn:rev1line],[websvn:rev1len] &rarr; [websvn:rev2line],[websvn:rev2len]</th></tr>
[websvn-endtest]
[websvn-test:diffclass]
<tr><td class="[websvn:diffclass]">[websvn:line]</td></tr>
[websvn-endtest]
[websvn-test:properties]
<tr><th>[lang:PROPCHANGES]</th></tr>
[websvn-endtest]
[websvn-test:endpath]
</tbody>
</table>
[websvn-endtest]
[websvn-endlisting]
</div>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
/WebSVN/templates/Elegant/diff.tmpl
0,0 → 1,84
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
[websvn-test:noprev]
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev1]</a></h2>
[websvn-else]
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev2] &rarr; [lang:REV] [websvn:rev1]</a></h2>
[websvn-endtest]
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:prevrevurl]
<li class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></li>
[websvn-endtest]
[websvn-test:nextrevurl]
<li class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></li>
[websvn-endtest]
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
[websvn-test:showalllink]
<li class="entire">[websvn:showalllink]</li>
[websvn-endtest]
[websvn-test:showcompactlink]
<li class="compact">[websvn:showcompactlink]</li>
[websvn-endtest]
[websvn-test:ignorewhitespacelink]
<li class="ignore">[websvn:ignorewhitespacelink]</li>
[websvn-endtest]
[websvn-test:regardwhitespacelink]
<li class="regard">[websvn:regardwhitespacelink]</li>
[websvn-endtest]
<li class="file">[websvn:filedetaillink]</li>
<li class="blame">[websvn:blamelink]</li>
<li class="rev">[websvn:revlink]</li>
<li class="log">[websvn:loglink]</li>
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
[websvn-test:noprev]
<div class="warning"><span>[lang:NOPREVREV]</span></div>
[websvn-else]
<table>
<thead>
<tr>
<th colspan="2">[lang:REV] [websvn:rev2]</th>
<th colspan="2">[lang:REV] [websvn:rev1]</th>
</tr>
</thead>
<tbody>
[websvn-startlisting]
[websvn-test:startblock]
<tr>
<th colspan="2">[lang:LINE] [websvn:rev1lineno]...</th>
<th colspan="2">[lang:LINE] [websvn:rev2lineno]...</th>
</tr>
[websvn-endtest]
<tr>
<td class="line">[websvn:rev1lineno]</td>
<td class="[websvn:rev1diffclass]">[websvn:rev1line]</td>
<td class="line">[websvn:rev2lineno]</td>
<td class="[websvn:rev2diffclass]">[websvn:rev2line]</td>
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn-endtest] <!-- noprev -->
[websvn-endtest] <!-- warning -->
[websvn-endtest] <!-- noaccess -->
/WebSVN/templates/Elegant/directory.tmpl
0,0 → 1,150
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
[websvn-test:search]
<div id="searchcss">[websvn:search_form]<div>[lang:SEARCH] [websvn:search_input]<span class="submit">[websvn:search_submit]</span></div>[websvn:search_endform]</div>
[websvn-endtest]
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev]</a></h2>
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:prevrevurl]
<li class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></li>
[websvn-endtest]
[websvn-test:nextrevurl]
<li class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></li>
[websvn-endtest]
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
[websvn-test:comparelink]
<li class="diff">[websvn:comparelink]</li>
[websvn-endtest]
<li class="rev">[websvn:revlink]</li>
<li class="log">[websvn:loglink]</li>
[websvn-test:downloadurl]
<li class="download"><a href="[websvn:downloadurl]" rel="nofollow">[lang:DOWNLOAD]</a></li>
[websvn-endtest]
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
[websvn-defineicons]
*=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file.png" alt="file" />
.c=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-c.png" alt=".c file" />
.cpp=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-cpp.png" alt=".cpp FILE" />
.h=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-h.png" alt=".h file" />
.m=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-m.png" alt=".m file" />
.java=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-java.png" alt=".java file" />
.py=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-py.png" alt=".py file" />
 
.png=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-image.png" alt="PNG image" />
.gif=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-image.png" alt="GIF image" />
.bmp=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-image.png" alt="BMP image" />
.jpg=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-image.png" alt="JPG image" />
.jpeg=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-image.png" alt="JPG image" />
 
.html=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-html.png" alt="HTML file" />
.htm=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-html.png" alt="HTML file" />
.xml=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-xml.png" alt="XML file" />
.php=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-php.png" alt="PHP file" />
.css=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/file-css.png" alt="CSS file" />
 
dir=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/directory.png" alt="[DIRECTORY]" />
diropen=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/directory.png" alt="[DIRECTORY]" />
i-node=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/blank.png" alt="node" />
t-node=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/blank.png" alt="node" />
l-node=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/blank.png" alt="node" />
e-node=<img src="[websvn:locwebsvnhttp]/templates/Elegant/images/blank.png" alt="node" />
[websvn-enddefineicons]
[websvn:compare_form]
<table id="listing">
<thead>
<tr>
<th>[lang:PATH]</th>
[websvn-test:showlastmod]
<th colspan="3">[lang:LASTMOD]</th>
[websvn-endtest]
<th>[lang:LOG]</th>
[websvn-test:allowdownload]
<th>[lang:DOWNLOAD]</th>
[websvn-endtest]
[websvn-test:clientrooturl]
<th>SVN</th>
[websvn-endtest]
[websvn-test:rssurl]
<th>[lang:RSSFEED]</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
[websvn-test:rowparity]
<tr class="shaded"
[websvn-test:loadalldir]
title="[websvn:classname]"
[websvn-endtest]
>
[websvn-else]
<tr [websvn-test:loadalldir]customaction="closed" title="[websvn:classname]"[websvn-endtest]>
[websvn-endtest]
<td class="path" valign="middle">
[websvn:compare_box]
[websvn-treenode]
<a href="[websvn:fileurl]">
[websvn-icon]
[websvn:filename]
</a>
</td>
[websvn-test:showlastmod]
<td class="rev"><a href="[websvn:revurl]" title="[lang:REV] [websvn:revision]">[websvn:revision]</a>&nbsp;</td>
[websvn-test:showageinsteadofdate]
<td class="date" title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td class="date" title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td class="author">[websvn:author]</td>
[websvn-endtest]
<td class="log"><a href="[websvn:logurl]" title="[lang:LOG]">[lang:LOG]</a></td>
[websvn-test:allowdownload]
<td class="download">
[websvn-test:downloadurl]
<a href="[websvn:downloadurl]" rel="nofollow" title="[lang:DOWNLOAD]">[lang:DOWNLOAD]</a>
[websvn-endtest]
[websvn-test:downloadplainurl]
<a href="[websvn:downloadplainurl]" rel="nofollow" title="[lang:DOWNLOAD]">[lang:DOWNLOAD]</a>
[websvn-endtest]
</td>
[websvn-endtest]
[websvn-test:clientrooturl]
<td class="svn"><a href="[websvn:clientrooturl][websvn:path]" title="SVN">SVN</a></td>
[websvn-endtest]
[websvn-test:rssurl]
<td class="rss"><a href="[websvn:rssurl]" title="[lang:RSSFEED]">[lang:RSSFEED]</a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
<div id="compare-submit">[websvn:compare_submit]</div>
[websvn:compare_endform]
[websvn-endtest]
[websvn-test:loadalldir]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/Elegant/file.tmpl
0,0 → 1,55
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev]</a></h2>
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:prevrevurl]
<li class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></li>
[websvn-endtest]
[websvn-test:nextrevurl]
<li class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></li>
[websvn-endtest]
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
[websvn-test:mimelink]
<li class="mime">[websvn:mimelink]</li>
[websvn-endtest]
<li class="blame">[websvn:blamelink]</li>
[websvn-test:difflink]
<li class="diff">[websvn:difflink]</li>
[websvn-endtest]
<li class="rev">[websvn:revlink]</li>
<li class="log">[websvn:loglink]</li>
[websvn-test:downloadlink]
<li class="download">[websvn:downloadlink]</li>
[websvn-endtest]
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
<div id="listing">
[websvn-getlisting]
</div>
[websvn-test:warning]
<!-- check for warnings generated by getlisting -->
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/Elegant/footer.tmpl
0,0 → 1,17
</div> <!-- content -->
</div> <!-- wrapper -->
<div id="footer">
<div id="valid">
<a href="http://validator.w3.org/check?uri=[websvn:validationurl]">XHTML</a> |
<a href="http://jigsaw.w3.org/css-validator/validator?uri=[websvn:validationurl]">CSS</a>
[websvn-test:rssurl]
| <a href="http://feedvalidator.org/check.cgi?url=[websvn:validationurl]">RSS</a>
[websvn-endtest]
</div>
<div id="poweredby">[lang:POWERED] [websvn:version] [lang:AND] <a href="http://subversion.apache.org">Apache Subversion</a> [websvn:svnversion]</div>
</div>
[websvn-test:repname]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/templates/Elegant/revision-popup.js"></script>
[websvn-endtest]
</body>
</html>
/WebSVN/templates/Elegant/header.tmpl
0,0 → 1,77
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[websvn:language_code]" lang="[websvn:language_code]">
<head>
<title>
WebSVN
[websvn-test:repname]
&ndash; [websvn:repname]
[websvn-endtest]
[websvn-test:error]
&ndash; ERROR
[websvn-else]
[websvn-test:rev2]
[websvn-test:safepath2]
&ndash; [websvn:safepath1] [lang:REV] [websvn:rev1] [lang:AND] [websvn:safepath2] [lang:REV] [websvn:rev2]
[websvn-else]
&ndash; [lang:REV] [websvn:rev1] [lang:AND] [websvn:rev2]
[websvn-endtest]
[websvn-else]
[websvn-test:rev]
&ndash; [lang:REV] [websvn:rev]
[websvn-endtest]
[websvn-endtest]
[websvn-test:action]
&ndash; [websvn:action]
[websvn-endtest]
[websvn-test:safepath]
&ndash; [websvn:safepath]
[websvn-endtest]
[websvn-endtest]
</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="generator" content="WebSVN [websvn:version]" /> <!-- leave this for stats -->
[websvn-test:blockrobots]
<meta name="robots" content="noindex,nofollow" />
[websvn-endtest]
<link rel="stylesheet" type="text/css" href="[websvn:locwebsvnhttp]/templates/Elegant/styles.css" />
<link rel="shortcut icon" type="image/x-icon" href="[websvn:locwebsvnhttp]/templates/Elegant/images/favicon.ico" />
[websvn-test:rssurl]
<link rel="alternate" type="application/rss+xml" title="WebSVN RSS" href="[websvn:rssurl]" />
[websvn-endtest]
<!--[if lt IE 7]>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/ie-png-transparency.js"></script>
<![endif]-->
</head>
<body id="[websvn:template]">
<div id="wrapper">
[websvn-test:repname]
<div id="rev-popup" style="display: none;">
[websvn-test:lastchangedrev]
<div class="info">[lang:REV] [websvn:lastchangedrev]
[websvn-else]
<div class="info">[lang:REV] [websvn:rev]
[websvn-endtest]
&ndash; [websvn:author]
[websvn-test:showageinsteadofdate]
&ndash; [websvn:age] ([websvn:date])
[websvn-else]
&ndash; [websvn:date] ([websvn:age])
[websvn-endtest]
</div>
<div class="msg">[websvn:log]</div>
</div>
[websvn-endtest]
<div id="header">
<div id="info">
<h1><a href="[websvn:indexurl]" title="[lang:PROJECTS]">[lang:PROJECTS]</a>
[websvn-test:repname]
&ndash; <a href="[websvn:repurl]">[websvn:repname]</a>
[websvn-endtest]
</h1>
<div id="menus">
[websvn-test:projects_form]
[websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]
[websvn-endtest]
[websvn:template_form][websvn:template_select][websvn:template_submit][websvn:template_endform]
[websvn:language_form][websvn:language_select][websvn:language_submit][websvn:language_endform]
</div>
/WebSVN/templates/Elegant/images/README.txt
0,0 → 1,9
Icons have been selected (and sometimes adapted) from the following icon sets:
 
Fugue - http://www.pinvoke.com
Led - http://led24.de/iconset/
RSS Icons - http://www.icojoy.com/articles/23/
Splashyfish - http://splashyfish.com/icons/
Vaga - http://www.edmerritt.com
 
Some of the icons have been drawn from or influenced by Mac OS X.
/WebSVN/templates/Elegant/images/added.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/arrow-in.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/arrow-out.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/bg-gray-dark.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/bg-gray-light.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/bg-page-header.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/bg-table-divider.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/bg-table-header.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/blame.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/blank.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/cube-blue.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/deleted.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/detail.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/diff.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/directory.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/download.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/eye.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/favicon.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-c.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-cpp.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-css.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-h.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-html.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-image.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-java.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-m.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-php.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-py.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file-xml.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/file.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/home.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/information.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/log.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/modified.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/next.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/parent.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/pilcrow.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/previous.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/remove.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/repository.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/repository24.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/reverse.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/revision.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/rss.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/stop.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/subversion-s.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/valid.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/warning.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/images/youngest.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/Elegant/index.tmpl
0,0 → 1,85
</div>
</div>
<!--
NOTE: This template file is not compatible with WebSVN 2.2.x and earlier since
the information passed from index.php uses drastically different organization.
-->
<div id="content">
[websvn-include:user_greeting.tmpl]
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
<table>
[websvn-test:showlastmod]
<thead><tr><th colspan="4">[lang:PROJECTS]</th></tr></thead>
[websvn-else]
<thead><tr><th>[lang:PROJECTS]</th></tr></thead>
[websvn-endtest]
[websvn-test:flatview]
[websvn-startlisting]
[websvn-test:groupid]
[websvn-else]
[websvn-test:rowparity]
<tr class="shaded">
[websvn-else]
<tr>
[websvn-endtest]
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-else]
[websvn-startlisting]
[websvn-test:groupid]
<tr><th onclick="toggleGroup('[websvn:groupname]');"
[websvn-test:showlastmod]
colspan="4"
[websvn-endtest]
>[websvn:groupname]</th></tr>
[websvn-else]
[websvn-test:groupparity]
<tr title="[websvn:groupname]" class="shaded">
[websvn-else]
<tr title="[websvn:groupname]">
[websvn-endtest]
[websvn-test:groupname]
<td class="project group"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-else]
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-endtest]
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-endtest]
</table>
[websvn-test:treeview]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-test:opentree]
[websvn-else]
<script type="text/javascript">
//<![CDATA[
collapseAllGroups();
//]]>
</script>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/Elegant/log.tmpl
0,0 → 1,125
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<h2 id="revnum"><a href="[websvn:revurl]">[lang:REV] [websvn:rev]</a></h2>
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
<li class="rev">[websvn:changeslink]</li>
[websvn-test:filedetaillink]
<li class="file">[websvn:filedetaillink]</li>
<li class="blame">[websvn:blamelink]</li>
<li class="diff">[websvn:difflink]</li>
[websvn-else]
<li class="dir">[websvn:directorylink]</li>
[websvn-endtest]
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
<div id="filter">
[websvn:logsearch_form]
[lang:STARTLOG]:[websvn:logsearch_startbox]
[lang:ENDLOG]:[websvn:logsearch_endbox]
[lang:MAXLOG]:[websvn:logsearch_maxbox]
[lang:SEARCHLOG]:[websvn:logsearch_inputbox]
<!-- [lang:SHOWALL]:[websvn:logsearch_showall] -->
[websvn:logsearch_submit]
[websvn:logsearch_endform]
</div>
<div id="filternav">
<span id="pagelinks">[websvn:pagelinks]</span>
[websvn-test:showalllink]
<span id="showall">[websvn:showalllink]</span>
[websvn-endtest]
[websvn-test:logsearch_moreresultslink]
<span id="moreresuls">[websvn:logsearch_moreresultslink]</span>
[websvn-endtest]
[websvn-test:logsearch_clearloglink]
<span id="clearlog">[websvn:logsearch_clearloglink]</span>
[websvn-endtest]
</div>
[websvn-test:logsearch_nomatches]
[lang:NORESULTS]
[websvn-endtest]
[websvn-test:logsearch_nomorematches]
<p>[lang:NOMORERESULTS]</p>
[websvn-endtest]
 
[websvn-test:logsearch_resultsfound]
[websvn:compare_form]
<table id="logs">
<thead>
<tr>
<th>[lang:REV]</th>
[websvn-test:showageinsteadofdate]
<th>[lang:AGE]</th>
[websvn-else]
<th>[lang:AGE]</th>
<!-- <th>[lang:DATE]</th> Note: [lang:DATE] doesn't exist yet... -->
[websvn-endtest]
<th>[lang:AUTHOR]</th>
<th>[lang:PATH]</th>
<th>[lang:LOGMSG]</th>
<th>[lang:DIFF]</th>
[websvn-test:showchanges]
<th>[lang:CHANGES]</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
[websvn-test:rowparity]
<tr class="shaded">
[websvn-else]
<tr>
[websvn-endtest]
<td class="rev">[websvn:compare_box][websvn:revlink]</td>
[websvn-test:showageinsteadofdate]
<td class="age" title="[websvn:revdate]">[websvn:revage]</td>
[websvn-else]
<td class="date" title="[websvn:revage]">[websvn:revdate]</td>
[websvn-endtest]
<td class="author">[websvn:revauthor]</td>
<td class="path">[websvn:revpathlink]</td>
<td class="logmsg">[websvn:revlog]</td>
<td class="diff"><a href="[websvn:compareurl]" title="[lang:DIFFPREV]">[lang:DIFF]</a></td>
[websvn-test:showchanges]
<td class="changes"><table>
[websvn-test:revadded]
<tr><td class="add">[websvn:revadded]</td></tr>
[websvn-endtest]
[websvn-test:revdeleted]
<tr><td class="del">[websvn:revdeleted]</td></tr>
[websvn-endtest]
[websvn-test:revmodified]
<tr><td class="mod">[websvn:revmodified]</td></tr>
[websvn-endtest]
</table></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
<div id="comparesubmit">[websvn:compare_submit]</div>
[websvn:compare_endform]
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/Elegant/revision-popup.js
0,0 → 1,20
// This div is generated by header.tmpl; remove it to display only on mouseover
var popup = document.getElementById('rev-popup');
document.getElementById('wrapper').removeChild(popup);
popup.style.display = 'block';
 
// Add event listeners to display/hide the popup when hovering the revnum header
var revnum = document.getElementById('revnum');
addEvent(revnum, 'mouseover', function() {this.parentNode.appendChild(popup)});
addEvent(revnum, 'mouseout', function() {this.parentNode.removeChild(popup)});
 
function addEvent(obj, type, func) {
if (obj.addEventListener) {
obj.addEventListener(type, func, false);
return true;
} else if (obj.attachEvent) {
return obj.attachEvent('on'+type, func);
} else {
return false;
}
}
/WebSVN/templates/Elegant/revision.tmpl
0,0 → 1,102
[websvn-test:error]
</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links]</h2>
<div id="revjump">[websvn:revision_form][websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<h2 id="revnum">[lang:REV] [websvn:rev]</h2>
<div class="clearer"></div>
</div>
<ul id="links">
[websvn-test:prevrevurl]
<li class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></li>
[websvn-endtest]
[websvn-test:nextrevurl]
<li class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></li>
[websvn-endtest]
[websvn-test:goyoungestlink]
<li class="youngest">[websvn:goyoungestlink]</li>
[websvn-endtest]
[websvn-test:comparelink]
<li class="diff">[websvn:comparelink]</li>
[websvn-endtest]
<li class="dir">[websvn:directorylink]</li>
[websvn-test:filedetaillink]
<li class="file">[websvn:filedetaillink]</li>
<li class="blame">[websvn:blamelink]</li>
[websvn-endtest]
<li class="log">[websvn:loglink]</li>
[websvn-test:clientrooturl]
<li class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></li>
[websvn-endtest]
[websvn-test:rsslink]
<li class="rss">[websvn:rsslink]</li>
[websvn-endtest]
</ul>
[websvn-endtest]
</div>
<div id="content">
[websvn-test:error]
<div class="error"><span>[websvn:error]</span></div>
[websvn-else]
[websvn-test:warning]
<div class="warning"><span>[websvn:warning]</span></div>
[websvn-else]
<dl>
<dt>[lang:LASTMOD]</dt><dd>[lang:REV] [websvn:rev] &ndash; [websvn:author] &ndash;
[websvn-test:showageinsteadofdate]
<span title="[websvn:date]">[websvn:age]</span></dd>
[websvn-else]
<span title="[websvn:age]">[websvn:date]</span></dd>
[websvn-endtest]
<dt>[lang:LOGMSG]</dt>
<dd>[websvn:log]</dd>
</dl>
<table id="changes">
<thead>
<tr align="left" valign="middle">
<th>[lang:PATH]</th>
<th>[lang:BLAME]</th>
<th>[lang:DIFF]</th>
<th>[lang:LOG]</th>
[websvn-test:clientrooturl]
<th>SVN</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
[websvn-test:rowparity]
<tr class="[websvn:action] shaded">
[websvn-else]
<tr class="[websvn:action]">
[websvn-endtest]
<td class="path">
[websvn-test:notinpath]
<a href="[websvn:detailurl]" class="notinpath">[websvn:safepath]</a>
[websvn-else]
<a href="[websvn:detailurl]">[websvn:safepath]</a>
[websvn-endtest]
[websvn-test:oldsafepath]
<br/><del>[websvn:oldsafepath] ([lang:PREV])</del>
[websvn-endtest]
</td>
[websvn-test:blameurl]
<td class="blame"><a href="[websvn:blameurl]" title="[lang:BLAME]">[lang:BLAME]</a></td>
[websvn-else]
<td></td>
[websvn-endtest]
[websvn-test:diffurl]
<td class="diff"><a href="[websvn:diffurl]" title="[lang:DIFFPREV]">[lang:DIFF]</a></td>
[websvn-else]
<td></td>
[websvn-endtest]
<td class="log"><a href="[websvn:logurl]" title="[lang:LOG]">[lang:LOG]</a></td>
[websvn-test:clientrooturl]
<td class="svn"><a href="[websvn:clientrooturl][websvn:path]" title="SVN">SVN</a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/Elegant/styles.css
0,0 → 1,1001
/* @group Global Styles */
 
/* @group Common Elements */
 
html, body {
margin: 0;
padding: 0;
height: 100%;
}
 
body {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
font-size: 8pt;
background-color: white;
}
 
@media print {
body {
font-size: 7pt;
}
}
 
h1 {
font-size: 2em;
margin-top: 0;
padding-top: 8px;
}
 
h2 {
font-size: 1.5em;
margin: 5px 0;
}
 
dt {
font-weight: bold;
margin-top: 6px;
}
 
a {
color: black;
text-decoration: none;
}
 
a:hover {
text-decoration: underline;
}
 
a img {
border: none;
}
 
form {
margin: 0;
}
 
/* @end */
 
/* @group Header */
 
#header {
margin: 0;
padding: 0;
}
 
#header #info {
font-size: 85%;
margin: 0;
padding: 0 10px;
background: url(images/bg-page-header.png) repeat-x 0 top;
border-bottom: solid 1px #4b4b4b;
}
 
#header #info, #header #info * {
position: relative;
}
 
#header #info, h1, h2 {
font-weight: normal;
}
 
#header #info, #header #info a {
color: white;
}
 
#header #info a {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
}
 
#header h1 {
margin: 0;
padding: 8px 0;
}
 
* html #header h1 {
padding-bottom: 15px;
}
 
#header h1 a {
padding: 0 2px;
}
 
#header #info a:hover, #header #info h2#path_links a:hover {
background-color: rgba(63,63,63,0.35);
}
 
#header h2 {
float: left;
margin: 1px 1px 5px;
}
 
#header h2#revnum {
float: right;
background: url(images/information.png) no-repeat 0 1px;
padding-left: 22px;
}
 
#header #menus {
position: absolute;
top: 0;
right: 0;
padding: 9px;
}
 
#header #menus form {
display: inline;
}
 
#header #menus * {
margin: 0;
padding: 0;
}
 
@media print {
#header #menus {
display: none;
}
}
 
#header #revjump {
float: right;
clear: none;
margin: -3px -3px 0 15px;
}
 
#header #revjump span input {
margin: 2px;
padding: 0 8px;
}
 
* html #header #revjump {
padding-right: 5px;
}
 
* html #header #revjump form {
margin: 0;
}
 
#header #searchcss {
float: center;
clear: none;
margin: -3px -3px 0 15px;
}
 
#header #searchcss span input {
margin: 2px;
padding: 0 8px;
}
 
* html #header #searchcss {
padding-right: 5px;
}
 
* html #header #searchcss form {
margin: 0;
}
 
#header div {
clear: both;
}
 
#header h2#path_links > * {
padding: 1px;
}
 
#header h2#path_links a.root {
background: url(images/home.png) no-repeat 0 1px;
padding-left: 16px;
}
 
#header h2#path_links a.root span {
display: none;
}
 
#header h2#path_links a.peg {
background: url(images/remove.png) no-repeat right 1px;
padding-right: 20px;
}
 
/* @end */
 
/* @group Revision Pop-ups */
 
#revnum:hover {
cursor: default;
}
 
#header #rev-popup, .blame-popup {
font-size: 11px;
color: black;
background-color: rgba(255,255,255,0.9);
padding: 4px;
white-space: normal;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
position: absolute;
border: solid 1px #4b4b4b;
max-width: 600px;
}
 
#rev-popup {
top: 5.5em;
right: 10px;
margin-left: 10px;
z-index: 1;
}
 
.blame-popup {
text-align: left;
margin-top: 4px;
}
 
#rev-popup .info, .blame-popup .date {
font-weight: bold;
}
 
#rev-popup .msg, .blame-popup .msg {
margin-top: 6px;
}
 
#header #info #rev-popup a {
color: black;
}
 
#revision #rev-popup {
display: none;
}
 
/* @end */
 
/* @group Navigation Links */
 
#links {
padding: 0;
margin: 0;
text-align: center;
background: url(images/bg-gray-light.png) repeat-x 0 top;
border-bottom: solid 1px #a1a5a9;
white-space: nowrap;
}
 
#links li {
font-size: 110%;
display: inline-block;
padding: 0;
margin: 0;
white-space: nowrap;
}
 
* html #links li {
display: inline;
}
 
#links li:hover {
background: url(images/bg-gray-dark.png) repeat-x 0 top;
}
 
#links a:hover {
text-decoration: none;
}
 
#links li a {
padding: 4px 3px 4px 22px;
display: block;
background-position: 3px 4px;
background-repeat: no-repeat;
}
 
#links li.entire a {
background-image: url(images/arrow-out.png);
}
 
#links li.compact a {
background-image: url(images/arrow-in.png);
}
 
#links li.regard a, #links li.ignore a {
background-image: url(images/pilcrow.png);
}
 
#links li.blame a {
background-image: url(images/blame.png);
}
 
#links li.file a {
background-image: url(images/detail.png);
}
 
#links li.diff a {
background-image: url(images/diff.png);
}
 
#links li.download a {
background-image: url(images/download.png);
}
 
#links li.dir a {
background-image: url(images/parent.png);
}
 
#links li.log a {
background-image: url(images/log.png);
}
 
#links li.mime a {
background-image: url(images/eye.png);
}
 
#links li.next a {
background-image: url(images/next.png);
}
 
#links li.prev a {
background-image: url(images/previous.png);
}
 
#links li.rev a {
background-image: url(images/revision.png);
}
 
#links li.reverse a {
background-image: url(images/reverse.png);
}
 
#links li.rss a {
background-image: url(images/rss.png);
}
 
#links li.svn a {
background-image: url(images/subversion-s.png);
}
 
#links li.youngest a {
background-image: url(images/youngest.png);
}
 
@media print {
#dropdowns, #links {
display: none;
}
}
 
/* @end */
 
#content {
padding: 10px;
border-top: 1px solid #cfcfcf;
}
 
#wrapper {
margin: 0;
}
 
/* @group Notification Bubbles */
 
.error, .warning, .information {
display: table;
font-weight: bold;
margin: 0 auto;
padding: 5px 7px 3px 10px;
border: solid 1px;
vertical-align: middle;
background-repeat: no-repeat;
background-position: 6px 4px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
}
 
.error span, .warning span, .information span {
display: block;
max-width: 400px;
margin-left: 33px;
padding: 10px 0;
position: relative;
top: -2px;
}
 
.error a, .warning a, .information a {
text-decoration: underline;
}
 
.error a:hover, .warning a:hover, .information a:hover {
text-decoration: none;
}
 
.error {
border-color: red;
background-color: #fcc;
background-image: url(images/stop.png);
}
 
.warning {
border-color: #d5ce00;
background-color: #ffc;
background-image: url(images/warning.png);
}
 
.information {
border-color: #4467aa;
background-color: #d5e0ee;
background-image: url(images/information.png);
}
 
/* @end */
 
/* @group Table Elements */
 
table {
border-collapse: collapse;
margin: 0 auto;
}
 
table, th, td {
border-style: solid;
border-color: #ccc;
border-width: 1px;
}
 
th, td {
vertical-align: middle;
white-space: nowrap;
padding: 0 5px;
}
 
th {
height: 16px;
text-align: center;
border-width: 1px;
}
 
td {
border-top-width: 0;
border-bottom-width: 0;
overflow: hidden;
}
 
td a {
padding: 1px 0;
}
 
td.path a {
display: inline-block;
width: 100%;
}
 
td input {
position: relative;
top: -2px;
}
 
thead * {
color: white;
}
 
thead th {
background-image: url(images/bg-table-header.png);
border-color: #73a2be;
}
 
tbody th {
background-image: url(images/bg-table-divider.png);
}
 
tbody tr.shaded, tbody tr.dark {
background-color: #ecf3fe;
}
 
tbody tr:hover {
background-color: #d6dde5;
}
 
@media print {
tbody tr.shaded {
border-width: 1px;
}
 
tbody tr:hover {
background-color: white;
}
}
 
/* @end */
 
/* @group Image-Only table links */
/* directory / revision */
 
td.blame a, td.download a, #log td.diff a, #revision td.diff a, td.log a, td.rss a, td.svn a {
text-indent: -5000px;
overflow: hidden;
display: block;
width: 100%;
min-width: 16px;
min-height: 16px;
margin: 0 auto;
padding: 0;
background-position: center;
background-repeat: no-repeat;
}
 
td.download a {
background-image: url(images/download.png);
}
 
td.blame a {
background-image: url(images/blame.png);
}
 
#log td.diff a, #revision td.diff a {
background-image: url(images/diff.png);
}
 
td.log a {
background-image: url(images/log.png);
}
 
td.rss a {
background-image: url(images/rss.png);
}
 
td.svn a {
background-image: url(images/subversion-s.png);
}
 
/* @end */
 
#comparesubmit {
margin-top: 10px;
text-align: center;
}
 
#comparesubmit input {
margin: 0;
}
 
/* @group Footer */
 
#footer {
text-align: center;
clear: both;
}
 
#footer a {
font-weight: bold;
}
 
#footer #poweredby {
padding: 3px 3px 4px;
border-top: solid 1px #a1a5a9;
background: #f0f0f0 url(images/bg-gray-light.png) repeat-x 0 top;
}
 
#footer #valid {
padding: 4px 5px 4px 16px;
vertical-align: middle;
position: absolute;
border: 0;
right: 0;
background: url(images/valid.png) no-repeat 0 5px;
}
 
/* @group Sticky Footer */
 
html, body, #wrapper {
height: 100%;
}
 
body > #wrapper {
height: auto;
min-height: 100%;
}
 
#content {
padding-bottom: 3em;
}
 
#footer {
clear: both;
height: 2em;
margin-top: -2em;
}
 
/* @end */
 
/* @end */
 
@media print {
#header {
border: solid 1px #4b4b4b;
}
 
#footer, #comparesubmit {
display: none;
}
}
 
/* @end */
 
/* @group blame.tmpl */
 
#blame td {
vertical-align: top;
text-align: right;
}
 
#blame td.author, #blame td.line {
color: #777;
}
 
#blame td.author {
text-align: center;
}
 
#blame td.code {
text-align: left;
white-space: pre-wrap;
}
 
#blame td.code, #blame td.line {
font-family: Consolas, Menlo, Monaco, monospace;
}
 
/* @end */
 
/* @group compare.tmpl */
 
#compare #header h2 {
float: none;
text-align: center;
}
 
#compare #header h2 span {
white-space: pre;
}
 
#compare_form table {
border: none;
}
 
#compare_form table td {
border: none;
text-align: right;
}
 
#compare_form table tr:hover {
background: none;
}
 
#comparisons {
margin: 0 auto;
display: table;
}
 
#comparisons h3 {
text-align: center;
margin-bottom: 0;
}
 
#comparisons table {
margin: 10px 0 15px;
width: 100%;
}
 
#comparisons td {
padding: 1px 3px;
white-space: pre-wrap;
font-family: Consolas, Menlo, Monaco, monospace;
}
 
#comparisons th.info, #comparisons tr:hover th.info {
background-image: none;
background-color: #cde;
}
 
/* @end */
 
/* @group diff.tmpl */
 
#diff td {
white-space: normal;
vertical-align: top;
font-family: Consolas, Menlo, Monaco, monospace;
}
 
#diff td.line {
text-align: right;
padding: 0 2px;
color: #777;
}
 
ins, del {
text-decoration: none;
}
td.diffadded, ins {
background-color: #bfb;
}
td.diffchanged {
background-color: #ffc;
}
td.diffdeleted, del {
background-color: #f88;
}
 
@media screen {
tr:hover td.diffadded, tr:hover ins {
background-color: #5f5;
}
tr:hover td.diffchanged {
background-color: #ff5;
}
tr:hover td.diffdeleted, tr:hover del {
background-color: #f55;
}
}
 
/* @end */
 
/* @group directory.tmpl */
 
#listing td {
text-align: center;
color: #777;
}
 
#listing td.rev, #listing td.date, #listing td.author {
text-align: right;
border-width: 0;
}
 
@media print {
#listing td.rev, #listing td.date, #listing td.author {
border-width: 1px 0;
}
}
 
#listing td.path {
text-align: left;
padding-bottom: 4px;
}
 
#listing td img {
position: relative;
top: 3px;
}
 
#listing td.rev a {
padding-right: 18px;
background: url(images/revision.png) no-repeat right;
}
 
#listing td input {
position: relative;
top: -1px;
margin: 0;
margin-right: 3px;
}
 
#compare-submit {
text-align: center;
margin-top: 10px;
}
 
/* @end */
 
/* @group file.tmpl */
 
#file #listing {
font-family: Consolas, Menlo, Monaco, monospace;
}
 
#file #listing pre {
white-space: pre-wrap;
}
 
/* @end */
 
/* @group index.tmpl */
 
#index #menus #projectform {
display: none;
}
 
#index .information {
margin: 10px auto 20px;
}
 
#index table {
margin: 10px auto;
}
 
#index tr.shaded {
background-color: #ecf3fe;
}
 
#index tr.shaded:hover {
background-color: #d6dde5;
}
 
#index td a {
padding: 5px 6px 6px;
}
 
#index tbody th {
border-bottom-color: #bbb;
background-image: url(images/bg-gray-light.png);
text-align: left;
}
 
#index tbody th:hover {
background-image: url(images/bg-gray-dark.png);
text-decoration: underline;
}
 
#index td {
border-width: 0;
color: #777;
text-align: right;
}
 
#index td.project {
text-align: left;
}
 
#index td a {
background: url(images/cube-blue.png) no-repeat 0 4px;
display: block;
padding-left: 20px;
width: 100%;
}
 
#index tbody th, #index td.group {
padding-left: 25px;
}
 
/* @end */
 
/* @group log.tmpl */
 
#filter, #filternav {
text-align: center;
margin-bottom: 8px;
}
 
table#logs {
clear: both;
}
 
#logs td {
vertical-align: text-top;
padding-top: 2px;
padding-bottom: 2px;
}
 
#logs td.rev a {
margin-left: 3px;
padding-left: 18px;
background: url(images/revision.png) no-repeat;
}
 
#logs td.author, #logs td.age, #logs td.date {
text-align: center;
color: #777;
}
 
#logs td.logmsg {
white-space: normal;
}
 
#logs td.changes {
color: #777;
padding: 0;
}
 
#logs td.changes table {
border-width: 0;
width: 100%;
margin-bottom: 2px;
}
 
#logs td.changes td {
border-width: 0;
padding-left: 20px;
background: url(images/added.png) no-repeat 3px 3px;
}
 
#logs td.changes td.add {
background-image: url(images/added.png);
}
 
#logs td.changes td.del {
background-image: url(images/deleted.png);
}
 
#logs td.changes td.mod {
background-image: url(images/modified.png);
}
 
#filternav {
font-weight: bold;
}
 
#filternav > * {
margin: 0 10px;
}
 
#filternav #pagelinks > * {
padding: 0 2px;
}
 
#filternav #pagelinks span {
color: #999;
}
 
#filternav #pagelinks span#curpage {
background-color: #999;
color: white;
padding-bottom: 1px;
padding-left: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
}
 
@media print {
#filter, #filternav, #logs td.rev input {
display: none;
}
}
 
/* @end */
 
/* @group revision.tmpl */
 
#revision dl, #revision dl dt:first-child {
margin-top: 0;
}
 
#revision dl dt {
font-size: 120%;
}
 
#revision #changes td {
text-align: center;
padding-top: 3px;
padding-bottom: 4px;
}
 
#revision #changes td.path {
text-align: left;
white-space: normal;
}
 
#revision #changes td.path a {
background-repeat: no-repeat;
background-position: 0 1px;
padding: 1px 0;
padding-left: 18px;
overflow: visible;
}
 
#revision #changes td.path a.notinpath {
color: #b70000;
}
 
#revision #changes tr.A td.path a {
background-image: url(images/added.png);
}
 
#revision #changes tr.D td.path a {
background-image: url(images/deleted.png);
}
 
#revision #changes tr.M td.path a {
background-image: url(images/modified.png);
}
 
#revision del {
background: none;
color: gray;
padding-left: 18px;
}
 
/* @end */
/WebSVN/templates/Elegant/user_greeting.tmpl
0,0 → 1,6
<div class="information">
<span>
You can customize this message in 'templates/Elegant/user_greeting.tmpl' to tell your
visitors what they'll find in your repositories.
</span>
</div>
/WebSVN/templates/calm/README.txt
0,0 → 1,61
______________________________________________________________________________
| |
| "CALM" THEME FOR WEBSVN |
| |
| (Theme : http://calm-theme-for-websvn.devjavu.com) |
|______________________________________________________________________________|
______________________________________________________________________________
| |
| Copyright 2007 Erik Poehler (email : iroybot@gmail.com) |
| (blog : http://contactsheet.de) |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|______________________________________________________________________________|
______________________________________________________________________________
| |
| INSTALLATION |
|______________________________________________________________________________|
1) Place the complete directory "calm" in your "templates" directory/
2) Open include/config.php and look for a line similar to the following:
$config->setTemplatePath("$locwebsvnreal/templates/Standard/");
 
and change it into:
 
$config->setTemplatePath("$locwebsvnreal/templates/calm/");
 
3) Enjoy.
If you like the template, please feel free to donate
some cents via paypal to erikpoehler@gmx.de.
In case you found errors, bugs or have improvement suggestions,
send me a email or visit:
http://calm-theme-for-websvn.devjavu.com
Please keep the backlink in the footer intact. Thanks.
______________________________________________________________________________
| |
| CREDITS |
|______________________________________________________________________________|
1. Icons picked from: "Sweetie", "Silk" and "Tango" Iconsets. Much Thanks to the creators.
2. Dean Edwards for making his "star-light" Syntax Highlighting available.
3. You for developing (hopefully good) software.
/WebSVN/templates/calm/blame.tmpl
0,0 → 1,56
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev]</h2>
<div id="revjump">[websvn:revision_form][lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<p>
[websvn-test:prevrevurl]
<span class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:nextrevurl]
<span class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
<span class="detail">[websvn:filedetaillink]</span> &#124;
[websvn-test:difflink]
<span class="diff">[websvn:difflink]</span> &#124;
[websvn-endtest]
<span class="changes">[websvn:revlink]</span> &#124;
<span class="log">[websvn:loglink]</span>
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div style="margin:0 2%">
<table>
<thead>
<tr>
<th scope="col" class="colrev">[lang:REV]</th>
<th scope="col" class="colauth">[lang:AUTHOR]</th>
<th scope="col" class="collno">[lang:LINENO]</th>
<th scope="col" class="colcode">[lang:LINE]</th>
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr valign="middle">
<td>[websvn:revision]</td>
<td>[websvn:author]</td>
<td><a name="l[websvn:lineno]" href="#l[websvn:lineno]">[websvn:lineno]</a></td>
<td class="code"><pre>[websvn:line]</pre></td>
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn:javascript]
</div>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/compare.tmpl
0,0 → 1,75
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<div id="info">
<h2>[lang:COMPAREREVS]</h2>
<ul><li><dl>
<dt>[lang:CONVFROM]</dt>
<dd><span style="visibility: hidden">&rarr;</span> <a href="[websvn:rev1url]">[websvn:safepath1] @ [websvn:rev1]</a></dd>
<dd>&rarr; <a href="[websvn:rev2url]">[websvn:safepath2] @ [websvn:rev2]</a></dd>
<dd>&harr; [websvn:reverselink]</dd>
</dl></li>
<li>
[websvn:compare_form]
<table>
<tbody>
<tr><th scope="col"><label>[lang:COMPPATH]</label></th><th scope="col"><label>Rev</label></th></tr>
<tr><td>[websvn:compare_path1input]</td><td class="revcomp">[websvn:compare_rev1input]</td></tr>
</tbody>
</table>
<table>
<tbody>
<tr><th scope="col"><label>[lang:WITHPATH]</label></th><th scope="col"><label>Rev</label></th></tr>
<tr><td>[websvn:compare_path2input]</td><td class="revcomp">[websvn:compare_rev2input]</td></tr>
</tbody>
</table>
<p class="submit">[websvn:compare_submit]</p>
[websvn:compare_endform]
</li></ul>
</div>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-endtest]
<div id="wrap">
<h2 class="regular">
<span class="links">
[websvn-test:ignorewhitespacelink]
<span class="ignorews">[websvn:ignorewhitespacelink]</span>
[websvn-endtest]
[websvn-test:regardwhitespacelink]
<span class="regardws">[websvn:regardwhitespacelink]</span>
[websvn-endtest]
</span>
[lang:REV] [websvn:rev1] &rarr; [lang:REV] [websvn:rev2]
</h2>
[websvn-startlisting]
[websvn-test:newpath]
<table class="diff collapsible">
<thead>
<tr><th class="open"><a href="[websvn:fileurl]">[websvn:newpath]</a></th></tr>
</thead>
<tbody>
[websvn-endtest]
[websvn-test:info]
<tr><th class="info">[websvn:info]</th></tr>
[websvn-endtest]
[websvn-test:difflines]
<tr><th>[websvn:rev1line],[websvn:rev1len] &rarr; [websvn:rev2line],[websvn:rev2len]</th></tr>
[websvn-endtest]
[websvn-test:diffclass]
<tr><td class="[websvn:diffclass]">[websvn:line]</td></tr>
[websvn-endtest]
[websvn-test:properties]
<tr><th>[lang:PROPCHANGES]</th></tr>
[websvn-endtest]
[websvn-test:endpath]
</tbody>
</table>
[websvn-endtest]
[websvn-endlisting]
</div>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
/WebSVN/templates/calm/diff.tmpl
0,0 → 1,75
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev2] &rarr; [websvn:rev1]</h2>
<div id="revjump">[websvn:revision_form][lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<p>
[websvn-test:prevrevurl]
<span class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:nextrevurl]
<span class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
[websvn-test:showalllink]
<span class="full">[websvn:showalllink]</span> &#124;
[websvn-endtest]
[websvn-test:showcompactlink]
<span class="compact">[websvn:showcompactlink]</span> &#124;
[websvn-endtest]
[websvn-test:ignorewhitespacelink]
<span class="ignorews">[websvn:ignorewhitespacelink]</span> &#124;
[websvn-endtest]
[websvn-test:regardwhitespacelink]
<span class="regardws">[websvn:regardwhitespacelink]</span> &#124;
[websvn-endtest]
<span class="detail">[websvn:filedetaillink]</span> &#124;
<span class="blame">[websvn:blamelink]</span> &#124;
<span class="changes">[websvn:revlink]</span> &#124;
<span class="log">[websvn:loglink]</span>
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
 
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div style="margin:0 2%">
[websvn-test:noprev]
<p>[lang:NOPREVREV]</p>
[websvn-else]
<table>
<thead>
<tr>
<th colspan="2"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:rev2]</a></th>
<th colspan="2"><a href="[websvn:revurl]">[lang:REV] [websvn:rev1]</a></th>
</tr>
</thead>
<tbody>
[websvn-startlisting]
[websvn-test:startblock]
<tr>
<th colspan="2">[lang:LINE] [websvn:rev1lineno]...</th>
<th colspan="2">[lang:LINE] [websvn:rev2lineno]...</th>
</tr>
[websvn-endtest]
<tr>
<td class="lineno">[websvn:rev1lineno]</td>
<td class="[websvn:rev1diffclass]"><pre>[websvn:rev1line]</pre></td>
<td class="lineno">[websvn:rev2lineno]</td>
<td class="[websvn:rev2diffclass]"><pre>[websvn:rev2line]</pre></td>
</tr>
[websvn-endlisting]
</tbody>
</table>
[websvn-endtest]
[websvn-endtest]
</div>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/directory.tmpl
0,0 → 1,152
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev]</h2>
<div id="revjump">[websvn:revision_form]<div>[lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span></div>[websvn:revision_endform]</div>
[websvn-test:search]
<div id="searchcss">[websvn:search_form]<div>[lang:SEARCH] [websvn:search_input]<span class="submit">[websvn:search_submit]</span></div>[websvn:search_endform]</div>
[websvn-endtest]
<p>
[websvn-test:prevrevurl]
<span class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:nextrevurl]
<span class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
<span class="changes">[websvn:revlink]</span> &#124;
[websvn-test:comparelink]
<span class="diff">[websvn:comparelink]</span> &#124;
[websvn-endtest]
<span class="log">[websvn:loglink]</span>
[websvn-test:downloadurl]
&#124; <span class="compress"><a href="[websvn:downloadurl]" rel="nofollow">[lang:DOWNLOAD]</a></span>
[websvn-endtest]
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
 
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div id="info">
<h2>[lang:LASTMOD]</h2>
<ul>
<li>[lang:REV] [websvn:lastchangedrev] [websvn:date]</li>
<li><strong>[lang:AUTHOR]:</strong> [websvn:author]</li>
<li><dl><dt><strong>[lang:LOGMSG]:</strong></dt><dd>[websvn:log]</dd></dl></li>
</ul>
</div>
 
[websvn-defineicons]
dir=<img src="[websvn:locwebsvnhttp]/templates/calm/images/directory.png" alt="[DIRECTORY]" class="icon" />
diropen=<img src="[websvn:locwebsvnhttp]/templates/calm/images/directory.png" alt="[DIRECTORY]" class="icon" />
*=<img src="[websvn:locwebsvnhttp]/templates/calm/images/file.png" alt="[FILE]" class="icon" />
.c=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filec.png" alt="[C-FILE]" class="icon" />
.h=<img src="[websvn:locwebsvnhttp]/templates/calm/images/fileh.png" alt="[H-FILE]" class="icon" />
.db=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filedb.png" alt="[DB-FILE]" class="icon" />
.png=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filepaint.png" alt="[DB-FILE]" class="icon" />
.gif=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filepaint.png" alt="[DB-FILE]" class="icon" />
.bmp=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filepaint.png" alt="[DB-FILE]" class="icon" />
.jpg=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filepaint.png" alt="[DB-FILE]" class="icon" />
.jpeg=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filepaint.png" alt="[DB-FILE]" class="icon" />
.js=<img src="[websvn:locwebsvnhttp]/templates/calm/images/script.png" alt="[DB-FILE]" class="icon" />
.css=<img src="[websvn:locwebsvnhttp]/templates/calm/images/css.png" alt="[DB-FILE]" class="icon" />
.htm=<img src="[websvn:locwebsvnhttp]/templates/calm/images/html.png" alt="[DB-FILE]" class="icon" />
.html=<img src="[websvn:locwebsvnhttp]/templates/calm/images/html.png" alt="[DB-FILE]" class="icon" />
.php=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filephp.png" alt="[DB-FILE]" class="icon" />
.txt=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filetxt.png" alt="[DB-FILE]" class="icon" />
.xml=<img src="[websvn:locwebsvnhttp]/templates/calm/images/filexml.png" alt="[DB-FILE]" class="icon" />
 
i-node=<img src="[websvn:locwebsvnhttp]/templates/calm/images/i-node.png" alt="[NODE]" class="icon" />
t-node=<img src="[websvn:locwebsvnhttp]/templates/calm/images/t-node.png" alt="[NODE]" class="icon" />
l-node=<img src="[websvn:locwebsvnhttp]/templates/calm/images/l-node.png" alt="[NODE]" class="icon" />
e-node=<img src="[websvn:locwebsvnhttp]/templates/calm/images/e-node.png" alt="[NODE]" class="icon" />
[websvn-enddefineicons]
 
 
<div id="wrap">
[websvn:compare_form]
<div class="table-responsive">
<table id="listing">
<thead>
<tr align="left" valign="middle">
<th scope="col" class="path">[lang:PATH]</th>
[websvn-test:showlastmod]
<th scope="col" colspan="3">[lang:LASTMOD]</th>
[websvn-endtest]
<th scope="col">[lang:LOG]</th>
[websvn-test:allowdownload]
<th scope="col">[lang:DOWNLOAD]</th>
[websvn-endtest]
[websvn-test:clientrooturl]
<th scope="col">SVN</th>
[websvn-endtest]
[websvn-test:rssurl]
<th scope="col">RSS</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr class="row[websvn:rowparity]" valign="middle"
[websvn-test:loadalldir]
title="[websvn:classname]"
[websvn-endtest]
>
<td class="path" valign="middle">
[websvn:compare_box]
[websvn-treenode]
<a href="[websvn:fileurl]">
[websvn-icon]
[websvn:filename]
</a>
</td>
[websvn-test:showlastmod]
<td class="rev"><a href="[websvn:revurl]">[websvn:revision]</a>&nbsp;</td>
[websvn-test:showageinsteadofdate]
<td class="age" title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td class="date" title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td class="author">[websvn:author]</td>
[websvn-endtest]
<td class="log"><a href="[websvn:logurl]">[lang:LOG]</a></td>
[websvn-test:allowdownload]
<td class="compress">
[websvn-test:downloadurl]
<a href="[websvn:downloadurl]" rel="nofollow">[lang:DOWNLOAD]</a>
[websvn-endtest]
[websvn-test:downloadplainurl]
<a href="[websvn:downloadplainurl]" rel="nofollow">[lang:DOWNLOAD]</a>
[websvn-endtest]
</td>
[websvn-endtest]
[websvn-test:clientrooturl]
<td class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></td>
[websvn-endtest]
[websvn-test:rssurl]
<td class="feed"><a href="[websvn:rssurl]">RSS</a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
</table>
</div>
<p class="submit">
[websvn:compare_submit]
</p>
[websvn:compare_endform]
</div>
[websvn-endtest]
[websvn-test:loadalldir]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/file.tmpl
0,0 → 1,46
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev]</h2>
<div id="revjump">[websvn:revision_form][lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<p>
[websvn-test:prevrevurl]
<span class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:nextrevurl]
<span class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
[websvn-test:mimelink]
<span class="mime">[websvn:mimelink]</span> &#124;
[websvn-endtest]
<span class="blame">[websvn:blamelink]</span> &#124;
[websvn-test:difflink]
<span class="diff">[websvn:difflink]</span> &#124;
[websvn-endtest]
<span class="changes">[websvn:revlink]</span> &#124;
<span class="log">[websvn:loglink]</span>
[websvn-test:downloadlink]
&#124; <span class="compress">[websvn:downloadlink]</span>
[websvn-endtest]
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div class="listing">
[websvn-getlisting]
</div>
[websvn-test:warning]
<!-- check for warnings generated by getlisting -->
<div id="warning">[websvn:warning]</div>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/footer.tmpl
0,0 → 1,6
</div>
<div id="footer">
<p style="padding:0; margin:0"><small>[lang:POWERED] [websvn:version] [lang:AND] <a href="http://subversion.apache.org">Apache Subversion</a> [websvn:svnversion] &nbsp; &nbsp; &#x2713; <a href="http://validator.w3.org/check?uri=[websvn:validationurl]">XHTML</a> &amp; <a href="http://jigsaw.w3.org/css-validator/validator?uri=[websvn:validationurl]">CSS</a></small></p>
</div>
</body>
</html>
/WebSVN/templates/calm/header.tmpl
0,0 → 1,63
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[websvn:language_code]" lang="[websvn:language_code]">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="generator" content="WebSVN [websvn:version]" /> <!-- leave this for stats -->
<meta name="viewport" content="width=device-width, initial-scale=1">
[websvn-test:blockrobots]
<meta name="robots" content="noindex,nofollow" />
[websvn-endtest]
<link rel="shortcut icon" type="image/x-icon" href="[websvn:locwebsvnhttp]/templates/calm/images/favicon.ico" />
<link type="text/css" href="[websvn:locwebsvnhttp]/templates/calm/styles.css" rel="stylesheet" media="screen" />
[websvn-test:rssurl]
<link rel='alternate' type='application/rss+xml' title='WebSVN RSS' href='[websvn:rssurl]' />
[websvn-endtest]
<!--[if gte IE 5.5000]>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/ie-png-transparency.js"></script>
<style type="text/css" media="screen">
tbody tr td { padding:1px 0 }
#wrap h2 { padding:10px 5px 0 5px; margin-bottom:-8px }
</style>
<![endif]-->
<title>
WebSVN
[websvn-test:repname]
&ndash; [websvn:repname]
[websvn-endtest]
[websvn-test:error]
&ndash; ERROR
[websvn-else]
[websvn-test:action]
&ndash; [websvn:action]
[websvn-endtest]
[websvn-test:safepath]
&ndash; [websvn:safepath]
[websvn-endtest]
[websvn-test:rev2]
[websvn-test:safepath2]
&ndash; [websvn:safepath1] [lang:REV] [websvn:rev1] [lang:AND] [websvn:safepath2] [lang:REV] [websvn:rev2]
[websvn-else]
&ndash; [lang:REV] [websvn:rev2] [lang:AND] [websvn:rev1]
[websvn-endtest]
[websvn-else]
[websvn-test:rev]
&ndash; [lang:REV] [websvn:rev]
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
</title>
</head>
<body id="[websvn:template]">
<div id="container">
<div id="select">
[websvn-test:projects_form]
[websvn:projects_form][websvn:projects_select][websvn:projects_submit][websvn:projects_endform]
[websvn-endtest]
[websvn:template_form][websvn:template_select][websvn:template_submit][websvn:template_endform]
[websvn:language_form][websvn:language_select][websvn:language_submit][websvn:language_endform]
</div>
<h1><a href="[websvn:indexurl]" title="[lang:PROJECTS]">[lang:PROJECTS]</a>
[websvn-test:repname]
<span><a href="[websvn:repurl]">[websvn:repname]</a></span>
[websvn-endtest]
</h1>
/WebSVN/templates/calm/images/add.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/arrow_in.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/arrow_out.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/blame.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/bullet_add.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/bullet_delete.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/bullet_yellow.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/compress.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/css.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/cube_green.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/delete.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/diff.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/directory.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/e-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/exclamation.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/eye.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/favicon.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/file.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filec.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filedb.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/fileh.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filepaint.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filephp.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filetxt.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/filexml.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/html.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/i-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/l-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/link.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/log.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/next.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/page_white_add.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/page_white_delete.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/page_white_edit.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/pilcrow.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/pilcrow_delete.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/previous.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/script.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/sitemap_color.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/submitbg.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/t-node.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/textbg.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/toggle-down.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/toggle-up.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/up.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/images/xml.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/WebSVN/templates/calm/index.tmpl
0,0 → 1,73
[websvn-include:user_greeting.tmpl]
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<div id="wrap">
<h2 class="regular">[lang:PROJECTS]</h2>
<table>
[websvn-test:flatview]
[websvn-startlisting]
[websvn-test:groupid]
[websvn-else]
<tr>
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-else]
[websvn-startlisting]
[websvn-test:groupid]
<tr><th onclick="toggleGroup('[websvn:groupname]'); this.className = (this.className == 'open') ? 'closed' : 'open';"
[websvn-test:opentree]
class="open"
[websvn-else]
class="closed"
[websvn-endtest]
[websvn-test:showlastmod]
colspan="4"
[websvn-endtest]
>[websvn:groupname]</th></tr>
[websvn-else]
<tr title="[websvn:groupname]">
[websvn-test:groupname]
<td class="project group"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-else]
<td class="project"><a href="[websvn:projecturl]">[websvn:projectname]</a></td>
[websvn-endtest]
[websvn-test:showlastmod]
<td>[lang:REV] [websvn:revision]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:date]">[websvn:age]</td>
[websvn-else]
<td title="[websvn:age]">[websvn:date]</td>
[websvn-endtest]
<td>[websvn:author]</td>
[websvn-endtest]
</tr>
[websvn-endtest]
[websvn-endlisting]
[websvn-endtest]
</table>
</div>
[websvn-test:treeview]
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/jquery.min.1.9.1.js"></script>
<script type="text/javascript" src="[websvn:locwebsvnhttp]/javascript/collapsible.js"></script>
[websvn-test:opentree]
[websvn-else]
<script type="text/javascript">
//<![CDATA[
collapseAllGroups();
//]]>
</script>
[websvn-endtest]
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/log.tmpl
0,0 → 1,124
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev]</h2>
<div id="revjump">[websvn:revision_form]<div>[lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span></div>[websvn:revision_endform]</div>
<p>
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
<span class="changes">[websvn:changeslink]</span> &#124;
[websvn-test:filedetaillink]
<span class="detail">[websvn:filedetaillink]</span> &#124;
<span class="diff">[websvn:difflink]</span> &#124;
<span class="blame">[websvn:blamelink]</span>
[websvn-else]
<span class="listing">[websvn:directorylink]</span>
[websvn-endtest]
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
 
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div id="info">
<h2>[lang:FILTER]</h2>
[websvn:logsearch_form]
<table>
<tbody>
<tr>
<th scope="col"><label>[lang:STARTLOG]</label></th>
<th scope="col"><label>[lang:ENDLOG]</label></th>
<th scope="col"><label>[lang:MAXLOG]</label></th>
</tr>
<tr>
<td class="revcomp">[websvn:logsearch_startbox]</td>
<td class="revcomp">[websvn:logsearch_endbox]</td>
<td class="revcomp">[websvn:logsearch_maxbox]</td>
</tr>
<tr><th scope="col" colspan="3"><label>[lang:SEARCHLOG]</label></th></tr>
<tr><td colspan="3">[websvn:logsearch_inputbox]</td></tr>
<tr><th scope="col" colspan="3"><label>[lang:SHOWALL]</label></th></tr>
<tr><td colspan="3" class="all">[websvn:logsearch_showall]</td></tr>
</tbody>
</table>
<p class="submit">[websvn:logsearch_submit]
[websvn-test:logsearch_clearloglink]
[websvn:logsearch_clearloglink]
[websvn-endtest]
</p>
[websvn:logsearch_endform]
</div>
 
<div id="wrap">
[websvn-test:logsearch_nomatches]
[lang:NORESULTS]
[websvn-endtest]
 
[websvn-test:logsearch_resultsfound]
[websvn:compare_form]
<table>
<thead>
<tr>
<th class="HdrClmn">[lang:REV]</th>
<th class="HdrClmn">[lang:AGE]</th>
<th class="HdrClmn">[lang:AUTHOR]</th>
<th class="HdrClmn">[lang:PATH]</th>
<th class="HdrClmnEnd">[lang:LOGMSG]</th>
<th class="HdrClmn">[lang:DIFF]</th>
[websvn-test:showchanges]
<th class="HdrClmnEnd">[lang:CHANGES]</th>
[websvn-endtest]
</tr>
</thead>
[websvn-startlisting]
<tr class="row[websvn:rowparity]">
<td class="rev">[websvn:compare_box][websvn:revlink]</td>
[websvn-test:showageinsteadofdate]
<td title="[websvn:revdate]">[websvn:revage]</td>
[websvn-else]
<td class="date" title="[websvn:revage]">[websvn:revdate]</td>
[websvn-endtest]
<td>[websvn:revauthor]</td>
<td>[websvn:revpathlink]</td>
<td valign="middle" class="logmsg">[websvn:revlog]</td>
<td><span class="diff"><a href="[websvn:compareurl]" title="[lang:DIFFPREV]">&nbsp;</a></span></td>
[websvn-test:showchanges]
<td class="changes">
[websvn-test:revadded]
<div class="add">[websvn:revadded]</div>
[websvn-endtest]
[websvn-test:revdeleted]
<div class="del">[websvn:revdeleted]</div>
[websvn-endtest]
[websvn-test:revmodified]
<div class="mod">[websvn:revmodified]</div>
[websvn-endtest]
</td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</table>
<p class="submit">
[websvn:compare_submit]
</p>
[websvn:compare_endform]
[websvn-endtest]
 
[websvn-test:logsearch_nomorematches]
<p>[lang:NOMORERESULTS]</p>
[websvn-endtest]
[websvn-test:logsearch_moreresultslink]
<p>[websvn:logsearch_moreresultslink]</p>
[websvn-endtest]
<p class="pagelinks">[websvn:pagelinks]</p>
<p>[websvn:showalllink]</p>
 
[websvn-endtest]
</div>
[websvn-endtest]
/WebSVN/templates/calm/revision.tmpl
0,0 → 1,96
[websvn-test:error]
<div id="error">[websvn:error]</div>
[websvn-else]
<h2 id="path_links">[websvn:path_links_root_config]/[websvn:path_links] &ndash; [lang:REV] [websvn:rev]</h2>
<div id="revjump">[websvn:revision_form][lang:REV] [websvn:revision_input]<span class="submit">[websvn:revision_submit]</span>[websvn:revision_endform]</div>
<p>
[websvn-test:prevrevurl]
<span class="prev"><a href="[websvn:prevrevurl]">[lang:REV] [websvn:prevrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:nextrevurl]
<span class="next"><a href="[websvn:nextrevurl]">[lang:REV] [websvn:nextrev]</a></span> &#124;
[websvn-endtest]
[websvn-test:goyoungestlink]
<span class="goyoungest">[websvn:goyoungestlink]</span> &#124;
[websvn-endtest]
[websvn-test:comparelink]
<span class="diff">[websvn:comparelink]</span> &#124;
[websvn-endtest]
<span class="listing">[websvn:directorylink]</span> &#124;
[websvn-test:filedetaillink]
<span class="detail">[websvn:filedetaillink]</span> &#124;
<span class="blame">[websvn:blamelink]</span> &#124;
[websvn-endtest]
<span class="log">[websvn:loglink]</span>
[websvn-test:clientrooturl]
&#124; <span class="svn"><a href="[websvn:clientrooturl][websvn:path]">SVN</a></span>
[websvn-endtest]
[websvn-test:rsslink]
&#124; <span class="feed">[websvn:rsslink]</span>
[websvn-endtest]
</p>
 
[websvn-test:warning]
<div id="warning">[websvn:warning]</div>
[websvn-else]
<div id="info">
<h2>[lang:LASTMOD]</h2>
<ul>
[websvn-test:showageinsteadofdate]
<li>[lang:REV] [websvn:rev] &ndash; <span title="[websvn:date]">[websvn:age]</span></li>
[websvn-else]
<li>[lang:REV] [websvn:rev] &ndash; <span title="[websvn:age]">[websvn:date]</span></li>
[websvn-endtest]
<li><strong>[lang:AUTHOR]:</strong> [websvn:author]</li>
<li><dl><dt><strong>[lang:LOGMSG]:</strong></dt><dd>[websvn:log]</dd></dl></li>
</ul>
</div>
 
<div id="wrap">
<table>
<thead>
<tr align="left" valign="middle">
<th scope="col" class="path">[lang:PATH]</th>
<th scope="col">[lang:BLAME]</th>
<th scope="col">[lang:DIFF]</th>
<th scope="col">[lang:LOG]</th>
[websvn-test:clientrooturl]
<th scope="col">SVN</th>
[websvn-endtest]
</tr>
</thead>
<tbody>
[websvn-startlisting]
<tr class="[websvn:action] row[websvn:rowparity]">
<td class="path">
[websvn-test:notinpath]
<a href="[websvn:detailurl]" class="notinpath">[websvn:safepath]</a>
[websvn-else]
<a href="[websvn:detailurl]">[websvn:safepath]</a>
[websvn-endtest]
[websvn-test:oldsafepath]
<br/><del>[websvn:oldsafepath] ([lang:PREV])</del>
[websvn-endtest]
</td>
<td>
[websvn-test:blameurl]
<a href="[websvn:blameurl]" title="[lang:BLAME]"><img src="[websvn:locwebsvnhttp]/templates/calm/images/blame.png" class="icon" alt="" /></a>
[websvn-endtest]
</td>
<td>
[websvn-test:diffurl]
<a href="[websvn:diffurl]" title="[lang:DIFFPREV]"><img src="[websvn:locwebsvnhttp]/templates/calm/images/diff.png" class="icon" alt="" /></a>
[websvn-endtest]
</td>
<td><a href="[websvn:logurl]" title="[lang:VIEWLOG]"><img src="[websvn:locwebsvnhttp]/templates/calm/images/log.png" class="icon" alt="" /></a></td>
[websvn-test:clientrooturl]
<td><a href="[websvn:clientrooturl][websvn:path]" title="SVN"><img src="[websvn:locwebsvnhttp]/templates/calm/images/link.png" class="icon" alt="" /></a></td>
[websvn-endtest]
</tr>
[websvn-endlisting]
</tbody>
 
</table>
</div>
[websvn-endtest]
[websvn-endtest]
/WebSVN/templates/calm/styles.css
0,0 → 1,938
html,body {
background:#FFF;
color:gray;
font-family: 'Trebuchet MS', Verdana, sans-serif;
font-size:13px;
line-height:1.3em;
margin:0; padding:0;
text-align:center;
height: 95%;
}
 
#container {
position: relative;
min-height: 100%;
padding-bottom:40px;
}
* html #container {
height: 95%;
}
#footer {
height:40px;
position: relative;
margin:0;padding:0;
margin-top: -40px;
}
 
a {
color:#000;
text-decoration:none;
outline: none !important;
}
a:hover {
background-color:#F0E68C;
}
a img {
border:0;
}
 
#select {
margin:1em 2% 0 2%;
text-align:right;
padding:10px 10px 0 10px;
min-height:2em;
}
#select form, #select div {
display: inline;
}
#revjump {
text-align:right;
height:2em;
padding: 10px 10px 0;
}
#wrap {
text-align:left;
background:#FFF;
padding:5px 0;
}
#index #wrap tr {
border-top:1px dotted lightgrey;
}
#index #wrap tr:first-child {
border-width:0;
}
#index #wrap td, #index #wrap th {
border-width:0;
padding:4px;
text-align:right;
white-space:pre;
}
#index #wrap td.project {
text-align:left;
width:100%;
}
#index #wrap td.project a {
background-image:url(images/cube_green.png);
background-repeat:no-repeat;
background-position:2px 50%;
}
#index #wrap td.project a, #index #wrap td.group {
padding-left:22px;
}
#index #wrap th {
background-color:white;
background-repeat:no-repeat;
background-position:6px 50%;
padding-left:26px;
text-align:left;
}
#index #wrap th.closed {
background-image:url(images/toggle-up.png);
}
#index #wrap th.open {
background-image:url(images/toggle-down.png);
}
#index #info dl {
margin:2px 0;
}
#index #info dl dd:first-child {
border-width: 0;
}
#info {
margin-left:2%;
text-align:left;
padding:5px 0;
}
h1, h2 {
color:gray;
text-align:left;
text-transform:uppercase;
line-height:1em;
font-weight:normal;
}
h1 {
line-height:1.7em;
font-size:1.7em;
border-bottom:1px solid gray;
padding:10px 5px 10px 5px;
text-align:left;
font-weight:normal;
letter-spacing: -0.018em;
}
h1 span {
padding-left:22px;
background:url(images/cube_green.png) no-repeat 0 50%;
}
h1 span a, h1 span a:link {
color:gray;
}
h2 a {
background:#FFF;
margin:0;
}
h2 a:link,
h2 a:visited {
font-weight:normal;
letter-spacing: -0.018em;
color: #b00
}
h2 a:hover {
background:#f2f2f2;
}
h2 {
font-weight:normal;
letter-spacing: -0.018em;
color:#666;
padding:0 .1em;
}
 
#info h2 {
border-bottom:1px solid gray;
padding:0 5px 10px;
margin:0;
text-align:left;
font-size:1.7em;
font-weight:normal;
letter-spacing: -0.018em;
}
 
#wrap h2 {
padding:0 0 10px 0;
margin:0;
text-align:left;
font-size:1.7em;
text-transform:none;
letter-spacing: -0.018em;
}
#wrap h2.regular {
padding:0 5px 10px 5px;
margin:0;
text-align:left;
font-size:1.7em;
text-transform:uppercase;
border-bottom:1px solid gray;
}
#wrap h2.regular .links {
float:right;
padding:0 5px 10px 5px;
margin:0;
text-align:right;
font-size:13px;
text-transform:none;
}
#wrap h2.regular .links a {
color: #000000;
font-weight: normal;
letter-spacing: 0;
}
/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms
*/
 
input, select {
padding:1px;
margin:1px;
font-family:'Trebuchet MS', 'Lucida Grande', Verdana, Arial, sans-serif;
border-right:1px solid #000;
border-bottom:1px solid #000;
border-left:1px solid #b2b2b2;
border-top:1px solid #b2b2b2;
background-color:#FFF8DC;
}
 
input {
padding:2px 5px;
font-size:1.1em;
background-color:#FFF;
background-image:url(images/textbg.png);
background-repeat:repeat-x;
background-position:0 100%;
border:1px solid #b2b2b2;
}
input:hover,
input:active,
input:focus {
border:1px solid #666;
background-color:#FFF;
}
#info ul li input {
background-color:#FFF;
background-image:url(images/textbg.png);
background-repeat:repeat-x;
background-position:0 100%;
border:1px solid #b2b2b2;
}
span.submit input,
#info span.submit input,
#info p.submit input,
#wrap p.submit input {
background-image:url(images/submitbg.png);
}
#info table tr td input {
font-size:1em;
width:92%;
background:#FFF url(images/textbg.png) repeat-x 0 0;
}
#info table tr td.revcomp input {
width:50px;
}
#info table tr td.all input {
width:auto;
}
select {
padding:2px 2px 2px 21px;
border:1px solid #cccccc;
background-color:#FFF;
background-image:url(images/cube_green.png);
background-repeat:no-repeat;
background-position:2px 50%;
}
 
select:hover,
select:active,
select:focus {
border:1px solid #666;
background-color:#F5F5DC;
background-repeat:no-repeat;
background-position:2px 50%;
background-image:url(images/cube_green.png);
}
option,
option:hover,
option:focus,
option:active {
padding-left:25px;
background-image:url(images/cube_green.png);
background-repeat:no-repeat;
background-position:2px 50%;
}
 
#index #projectform {
display: none;
}
 
/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Left Column
*/
 
/* index elements */
#info dl {
margin-left:0;
}
#info dt, #wrap dt {
margin:0;
padding:0 0 5px 0;
}
#info dd, #wrap dd {
margin:0;
padding:3px 0 5px 10px;
border-top:1px dotted #D3D3D3;
}
#info ul {
list-style-type:none;
padding:0 0;
margin:0;
}
#info ul li {
padding:5px;
margin:3px 0;
border-bottom:1px dotted #D3D3D3;
overflow:hidden;
}
 
li.mod a, li.new a, #info li.del {
padding:5px 5px 5px 26px;
margin:2px 0 2px -2px;
background-position:5px 50%;
background-repeat:no-repeat;
}
li.mod a {
display:block;
color:#545400;
border:1px solid #f2f2c7;
background-color:#FFFFE0;
background-image:url(images/page_white_edit.png);
}
li.mod a:hover {
color:#000;
border:1px solid #BDB76B;
background-color:#F0E68C;
}
li.new a {
display:block;
color:#545400;
border:1px solid #d5f2c7;
background-color:#f2ffd9;
background-image:url(images/page_white_add.png);
}
li.new a:hover {
color:#000;
border:1px solid #669900;
background-color:#9ACD32;
}
 
#info ul li.del {
display:block;
color:#BC8F8F;
border:1px solid #BC8F8F;
padding:5px 5px 5px 26px;
margin:5px;
background-color:#FFEFD5;
background-image:url(images/page_white_delete.png);
background-position:5px 5px;
text-align:left;
}
#info ul li a {
overflow:hidden;
}
/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++ main content: Directories
*/
 
table {
border-collapse:collapse;
width:100%;
}
td {
padding:0;
text-align:left;
}
th {
text-align:center;
}
td, th {
border: 1px solid #eeeeee;
}
#info th, #info td {
border: none;
text-align: left;
}
#diff td, #blame td, table.diff td {
vertical-align:top;
}
thead th a {
color:white;
}
thead th a:hover {
text-decoration:underline;
color:white;
background:none;
}
thead tr {
background:#4d4d4d;
}
thead th {
background:#4d4d4d;
border-bottom:2px solid #000;
border-top:2px solid #808080;
border-right:1px solid #808080;
color:#FFF;
margin:3px 2px;
padding:3px 5px;
}
thead th.open {
background-image:url(images/toggle-down.png);
background-repeat:no-repeat;
}
thead th.closed {
background-image:url(images/toggle-up.png);
background-repeat:no-repeat;
}
thead th.path {
text-align:left;
width:50%;
}
thead th.collno, thead th.colrev, thead th.colauth {
width:6%;
}
thead th.colcode {
width:73%;
}
tbody th {
background-color: #ddd;
}
tbody th.info {
background-color: #d0dfea;
}
tr td.code {
text-align:left;
}
td.code, td td.diff {
border: 1px solid #eee;
}
tr td.code pre {
padding: 1px 2px 0;
background-color:#f8f8f8;
}
tr:hover td.code pre {
background-color:#e8e8e8;
}
tr:hover td.code {
background-color:#FFF;
}
tr td.path, tr th.path {
text-align:left;
width: 100%;
}
tr td.path {
padding:0;
}
tr.row0 td {
background-color:#f0f0f0;
}
tr.row1 td {
background-color:#f8f8f8;
}
tr.row0:hover td, tr.row1:hover td {
background-color:#e8e8e8;
}
span.listing a, a.listing {
padding-left:22px;
background-image:url(images/sitemap_color.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.detail a {
padding-left:22px;
background-image:url(images/file.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.changes a {
padding-left:22px;
background-image:url(images/page_white_edit.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.compact a {
padding-left:22px;
background-image:url(images/arrow_in.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.full a {
padding-left:22px;
background-image:url(images/arrow_out.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.ignorews a {
padding-left:22px;
background-image:url(images/pilcrow_delete.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.regardws a {
padding-left:22px;
background-image:url(images/pilcrow.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.log a,
td.log a {
padding-left:22px;
background-image:url(images/log.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.blame a,
td.blame a {
padding-left:22px;
background-image:url(images/blame.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.mime a,
td.mime a {
padding-left:22px;
background-image:url(images/eye.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.svn a,
td.svn a {
padding-left:22px;
background-image:url(images/link.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
span.next a,
td.next a {
padding-left:15px;
background-image:url(images/next.png);
background-repeat:no-repeat;
background-position:0px 50%;
}
span.prev a,
td.prev a {
padding-left:15px;
background-image:url(images/previous.png);
background-repeat:no-repeat;
background-position:0px 50%;
}
 
li.compress a,
span.compress a,
tr td.compress a:link,
tr td.compress a:visited,
tr td.compress a:link {
padding-left:22px;
background-image:url(images/compress.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
li.feed a,
span.feed a,
tr td.feed a,
tr td.feed a:link,
tr td.feed a:visited,
tr td.feed a:link {
padding-left:22px;
background-image:url(images/xml.gif);
background-repeat:no-repeat;
background-position:3px 50%;
}
.goyoungest a {
color:#e25f53;
padding-left:22px;
background-image:url(images/exclamation.png);
background-repeat:no-repeat;
background-position:3px 50%;
}
.goyoungest a:hover {
background-color:#fad4c8;
color:#000;
}
.icon {
vertical-align: middle;
}
 
/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ File, Blame, Diff
*/
h2#path_links {
text-transform:none;
margin:0 2% 15px;
}
div.listing {
overflow:auto;
border:1px solid #D3D3D3;
text-align:left;
margin:0 2%;
padding:3px;
background:#f8f8f8;
}
pre a, td.code pre a {
color:blue;
font-style:italic;
}
pre {
margin: 0;
white-space: pre-wrap;
}
code, pre, table.diff td, #file div.listing {
font-family:Consolas, monospace;
}
.new a {color:green}
.del a {color:red}
.toggleup a:link,
.toggleup a:visited,
.toggleup a:focus {
padding-left:22px;
background:url(images/toggle-up.png) no-repeat 2px 50%;
}
.toggleup a:hover {
background:#F0E68C url(images/toggle-up.png) no-repeat 2px 50%;
}
.toggledown a:link,
.toggledown a:visited,
.toggledown a:focus {
padding-left:22px;
background:url(images/toggle-down.png) no-repeat 2px 50%;
}
.toggledown a:hover {
background:#F0E68C url(images/toggle-down.png) no-repeat 2px 50%;
}
span.diff a:link,
span.diff a:visited,
span.diff a:focus {
padding-left:22px;
background:url(images/diff.png) no-repeat 2px 50%;
}
span.diff a:hover {
background:#F0E68C url(images/diff.png) no-repeat 2px 50%;
}
.geshi a:link,
.geshi a:visited,
.geshi a:focus,
.geshi a:hover {
padding-left:0;
background: none;
}
.geshi a:hover {
text-decoration: underline;
}
tr td.lineno {
text-align: right;
vertical-align: top;
padding: 0 2px;
}
tr td.row1 {
padding: 3px;
border: none;
}
tr td code, tr td pre {
display:block;
height:100%;
}
/* compare table */
table.diff {
margin:10px 0 20px;
border-spacing:0;
border-collapse:separate;
}
table.diff td {
color:black;
padding:0;
margin:0;
border-color:#f0f0f0;
}
table.diff td, table td pre {
padding-left:16px;
background-position: 0 0;
background-repeat:no-repeat;
white-space:pre-wrap;
}
table td pre {
border:1px solid white;
}
table tr:hover {
background:white;
}
td.diffempty {
background-color:#f8f8f8;
}
table tr:hover td.diff, table tr:hover td.diffempty {
background-color:#e8e8e8;
}
table td.diff pre {
background-position:2px 50%;
background-repeat:no-repeat;
}
table.diff td.diffdeleted,
table td.diffdeleted pre {
background-color:#f8e4cc;
background-image:url(images/bullet_delete.png);
border:1px solid #e8d4bc;
}
table.diff tr:hover td.diffdeleted,
table tr:hover td.diffdeleted pre {
background-color:#ffccaa;
border-color:#bb9977;
}
table.diff td.diffadded,
table td.diffadded pre {
border:1px solid #cdf0cd;
background-color:#ddffdd;
background-image:url(images/bullet_add.png);
}
table.diff tr:hover td.diffadded,
table tr:hover td.diffadded pre {
background-color:#bbffbb;
border-color:#88bb88;
}
table td.diffchanged pre {
border:1px solid #f0f0bc;
background-color:#ffffcc;
background-image:url(images/bullet_yellow.png);
}
table tr:hover td.diffchanged pre {
background-color:#ffff99;
border-color:#bbbb55;
}
 
ins {
background-color: #bbffbb;
text-decoration: none;
}
tr:hover ins {
background-color: #99ff99;
}
del {
background-color: #ffccaa;
text-decoration: none;
}
tr:hover del {
background-color: #ffaa88;
}
 
code {
white-space: pre-wrap;
}
 
/* Whitespace hacks for IE 4-7 */
 
* html code, *:first-child+html code {
white-space: pre;
}
 
* html table.diff td, *:first-child+html table.diff td {
white-space: pre;
}
 
/* Log View */
 
table tr td.logmsg {
text-align:left;
padding: 3px 0 3px 3px;
}
 
/* sidebar form without css-bg-colors */
#info table tr td,
#info table tr th {
background:#FFF;
padding:0;
margin:0;
font-weight:normal;
}
#info table tr:hover td,
#info table tr:hover th {
background:#FFF;
padding:0;
margin:0;
}
/* inputs see -> forms */
 
div.blame-popup {
position: absolute;
text-align: left;
background-color: white;
padding: 5px;
border:1px solid #BDB76B;
background-color: #F0E68C;
max-width: 600px;
}
 
div.blame-popup .date {
font-weight: bold;
}
 
#wrap td.log, #wrap td.feed {
white-space: nowrap;
}
 
#wrap td.age, #wrap td.date {
padding-left: 3px;
padding-right: 8px;
}
 
#wrap td.age, #wrap td.date, #wrap td.rev {
text-align: right;
white-space: nowrap;
}
 
#wrap p.pagelinks > * {
padding: 0 3px;
}
 
div#error, div#warning {
font-weight: bold;
display: table;
padding: 5px;
margin: 0 auto;
border: 1px solid;
}
 
div#error {
border-color: #cb6565;
background-color: #ffe2e2;
}
 
div#warning {
border-color: #d5ce00;
background-color: #ffd;
}
 
table td {
vertical-align: top;
padding: 2px;
}
 
div#wrap table td.changes div {
background-repeat: no-repeat;
padding-left: 18px;
}
 
td.changes .add {
background-image: url(images/add.png);
}
 
td.changes .del {
background-image: url(images/delete.png);
}
 
td.changes .mod {
background-image: url(images/page_white_edit.png);
}
 
#blame table td {
text-align: right;
padding-right: 4px;
border-color: white;
}
 
#blame table td.code {
text-align: left;
padding: 0;
border-color: #eeeeee;
}
 
#blame table td.code pre {
border: none;
}
 
#revision td.path a {
background-position:5px 50%;
background-repeat:no-repeat;
padding-left: 26px;
top: 2px;
position: relative;
}
 
#revision td.path a.notinpath {
color: #b00;
}
 
#revision tr.M td.path a {
background-image:url(images/page_white_edit.png);
}
 
#revision tr.A td.path a {
background-image:url(images/page_white_add.png);
}
 
#revision tr.D td.path a {
background-image:url(images/page_white_delete.png);
}
 
#revision del {
padding-left: 26px;
background: none;
}
 
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
 
/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Media Queries (responsivity)
*/
 
/* every screens excepts small ones */
@media only screen and (min-width: 800px) {
#info {
float:left;
width:28%;
}
 
#wrap {
margin:0 2% 0 32%;
width:65%;
}
h1 {
margin:-1.7em 2% 1em 2%;
}
#revjump {
margin:-3.7em 2% 0;
}
}
 
/* small screens only */
@media only screen and (max-width: 799px) {
tr td.path {
white-space: nowrap;
}
h2#path_links {
overflow-x: auto;
overflow-y: hidden;
}
#wrap {
margin:1em 2% 0 2%;
}
h1 {
margin:0 2% 1em 2%;
}
/*** Always show scrollbar on webkit mobiles */
::-webkit-scrollbar {
-webkit-appearance: none;
width: .5rem;
height: .5rem;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0, 0, 0, .25);
}
}
/WebSVN/templates/calm/user_greeting.tmpl
0,0 → 1,16
<div id="info">
<h2>About</h2>
<dl>
<dd>
You can customize this message in 'templates/calm/user_greeting.tmpl' to tell your
visitors what they'll find in your repositories.
</dd>
<dd>
Visit <a href="https://websvnphp.github.io">websvnphp.github.io</a> for more information
about WebSVN.
</dd>
<dd>
Learn more about Apache Subversion at <a href="https://subversion.apache.org">subversion.apache.org</a>.
</dd>
</dl>
</div>
/rector.php
14,7 → 14,7
]);
 
// Uncomment and set this to your target PHP version
$rectorConfig->phpVersion(PHP_VERSION_ID); // for PHP 8, this might be 80000 for 8.0
$rectorConfig->phpVersion(80100); // for PHP 8, this might be 80000 for 8.0
 
// Include sets of rules for PHP version upgrades
// For upgrading to PHP 8.0