mirror of
https://github.com/vitalif/viewvc-4intranet
synced 2019-04-16 04:14:59 +03:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1103993aac | ||
![]() |
deeab1a01f |
13
CHANGES
13
CHANGES
@@ -1,16 +1,3 @@
|
||||
Version 1.0.7 (released 14-Oct-2008)
|
||||
|
||||
* fix regression in the 'as text' download view (issue #373)
|
||||
|
||||
Version 1.0.6 (released 16-Sep-2008)
|
||||
|
||||
* security fix: ignore arbitrary user-provided MIME types (issue #354)
|
||||
* fix bug in regexp search filter when used with sticky tag (issue #346)
|
||||
* fix bug in handling of certain 'co' output (issue #348)
|
||||
* fix regexp search filter template bug
|
||||
* fix annotate code syntax error
|
||||
* fix mod_python import cycle (issue #369)
|
||||
|
||||
Version 1.0.5 (released 28-Feb-2008)
|
||||
|
||||
* security fix: omit commits of all-forbidden files from query results
|
||||
|
@@ -42,23 +42,9 @@ if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
|
||||
import sapi
|
||||
import imp
|
||||
|
||||
# Import real ViewVC module
|
||||
fp, pathname, description = imp.find_module('viewvc', [LIBRARY_DIR])
|
||||
try:
|
||||
viewvc = imp.load_module('viewvc', fp, pathname, description)
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
|
||||
# Import real ViewVC Query modules
|
||||
fp, pathname, description = imp.find_module('query', [LIBRARY_DIR])
|
||||
try:
|
||||
query = imp.load_module('query', fp, pathname, description)
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
import viewvc
|
||||
import query
|
||||
reload(query) # need reload because initial import loads this stub file
|
||||
|
||||
cfg = viewvc.load_config(CONF_PATHNAME)
|
||||
|
||||
|
@@ -42,15 +42,9 @@ if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
|
||||
import sapi
|
||||
import imp
|
||||
import viewvc
|
||||
reload(viewvc) # need reload because initial import loads this stub file
|
||||
|
||||
# Import real ViewVC module
|
||||
fp, pathname, description = imp.find_module('viewvc', [LIBRARY_DIR])
|
||||
try:
|
||||
viewvc = imp.load_module('viewvc', fp, pathname, description)
|
||||
finally:
|
||||
if fp:
|
||||
fp.close()
|
||||
|
||||
def index(req):
|
||||
server = sapi.ModPythonServer(req)
|
||||
|
@@ -89,7 +89,7 @@ th.caption {
|
||||
<li><a href="#compat-tarball">'<code>tarball=1</code>' Parameter ⇒ '<code>view=tar</code>'</a></li>
|
||||
<li><a href="#compat-graph">'<code>graph=1</code>' Parameter ⇒ '<code>view=graph</code>'</a></li>
|
||||
<li><a href="#compat-makeimage">'<code>graph=1&makeimage=1</code>' Parameters ⇒ '<code>view=graphimg</code>'</a></li>
|
||||
<li><a href="#compat-content_type">'<code>content-type=text/vnd.viewcvs-markup</code>' and '<code>content-type=text/x-cvsweb-markup</code>' Parameters⇒ '<code>view=markup</code>'
|
||||
<li><a href="#compat-content_type">'<code>content_type=text/vnd.viewcvs-markup</code>' and '<code>content_type=text/x-cvsweb-markup</code>' Parameters⇒ '<code>view=markup</code>'
|
||||
<li><a href="#compat-attic">'<code>Attic/FILE</code>' Paths ⇒ '<code>FILE</code>'</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -284,6 +284,11 @@ th.caption {
|
||||
<td>depends</td>
|
||||
<td><a href="#view-param"><code>view</code> parameter</a>, not needed if the <code>default_file_view</code> configuration variable is set to <code>co</code>, since that makes the checkout view the default view for file paths. Also not needed if the <code>/*checkout*</code> magic prefix or the <code>revision</code> parameter is present.
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>content-type=<var>TYPE</var></code></td>
|
||||
<td>optional</td>
|
||||
<td>MIME type to send with checked out file, default is a guess based on file extension</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>revision=<var>REVISION</var></code></td>
|
||||
<td>optional</td>
|
||||
@@ -1228,8 +1233,8 @@ th.caption {
|
||||
<h3 id="compat-makeimage">'<code>graph=1&makeimage=1</code>' Parameters ⇒ '<code>view=graphimg</code>'</h3>
|
||||
<p>A <code>graph=1&makeimage=1</code> parameter is treated like a <code>view=graph</code> parameter. There is currently no redirect when it is encountered, but there could be one in the future.</p>
|
||||
|
||||
<h3 id="compat-content_type">'<code>content-type=text/vnd.viewcvs-markup</code>' and '<code>content-type=text/x-cvsweb-markup</code>' Parameters⇒ '<code>view=markup</code>'; other values ignored</h3>
|
||||
<p><code>content-type=text/vnd.viewcvs-markup</code> and <code>content-type=text/x-cvsweb-markup</code> parameters are treated like a <code>view=markup</code> parameter. There is currently no redirect when it is encountered, but there could be one in the future. Other values of the <code>content-type</code> parameter, which were used to dictate the MIME type of files displayed in the checkout/download view prior to ViewVC 1.0.6, are ignored.</p>
|
||||
<h3 id="compat-content_type">'<code>content_type=text/vnd.viewcvs-markup</code>' and '<code>content_type=text/x-cvsweb-markup</code>' Parameters⇒ '<code>view=markup</code>'</h3>
|
||||
<p><code>content_type=text/vnd.viewcvs-markup</code> and <code>content_type=text/x-cvsweb-markup</code> parameters are treated like a <code>view=markup</code> parameter. There is currently no redirect when it is encountered, but there could be one in the future.</p>
|
||||
|
||||
<h3 id="compat-attic">'<code>Attic/FILE</code>' Paths ⇒ '<code>FILE</code>'</h3>
|
||||
<p>When ViewVC encounters an invalid repository path whose last or second-to-last component is named <code>Attic</code>, and stripping the component yields a valid path, it will redirect to a URL with that path.</p>
|
||||
|
@@ -33,6 +33,7 @@ import time
|
||||
import math
|
||||
import cgi
|
||||
import vclib
|
||||
import vclib.ccvs.blame
|
||||
|
||||
|
||||
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
|
||||
@@ -99,7 +100,6 @@ class _item:
|
||||
|
||||
|
||||
def make_html(root, rcs_path):
|
||||
import vclib.ccvs.blame
|
||||
bs = vclib.ccvs.blame.BlameSource(os.path.join(root, rcs_path))
|
||||
|
||||
count = bs.num_lines
|
||||
@@ -161,9 +161,9 @@ def make_html(root, rcs_path):
|
||||
|
||||
# Close the highlighted section
|
||||
#if (defined $mark_cmd and mark_cmd != 'begin'):
|
||||
# chop($output)
|
||||
# output = output + endOfRow + (startOfRow % row_color)
|
||||
# inMark = 0
|
||||
# chop($output)
|
||||
# output = output + endOfRow + (startOfRow % row_color)
|
||||
# inMark = 0
|
||||
|
||||
print output
|
||||
print endOfRow + '</table>'
|
||||
|
@@ -364,11 +364,11 @@ class _pipe:
|
||||
else:
|
||||
if self.thread:
|
||||
self.thread.join()
|
||||
if type(self.child_pid) == type([]):
|
||||
if type(self.child_pid) == type([]):
|
||||
for pid in self.child_pid:
|
||||
exit = os.waitpid(pid, 0)[1]
|
||||
return exit
|
||||
else:
|
||||
else:
|
||||
return os.waitpid(self.child_pid, 0)[1]
|
||||
return None
|
||||
|
||||
|
@@ -25,7 +25,6 @@ import time
|
||||
|
||||
import cvsdb
|
||||
import viewvc
|
||||
import vclib
|
||||
import ezt
|
||||
import debug
|
||||
import urllib
|
||||
|
@@ -534,25 +534,31 @@ def _parse_co_header(fp):
|
||||
raise COMalformedOutput, "Unable to find filename in co output stream"
|
||||
filename = match.group(1)
|
||||
|
||||
# look through subsequent lines for a revision. we might encounter
|
||||
# some ignorable or problematic lines along the way.
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
# look for a revision.
|
||||
match = _re_co_revision.match(line)
|
||||
if match:
|
||||
return filename, match.group(1)
|
||||
elif _re_co_missing_rev.match(line) or _re_co_side_branches.match(line):
|
||||
raise COMissingRevision, "Got missing revision error from co output stream"
|
||||
elif _re_co_warning.match(line):
|
||||
pass
|
||||
else:
|
||||
break
|
||||
# look for a revision in the second line.
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
raise COMalformedOutput, "Missing second line from co output stream"
|
||||
match = _re_co_revision.match(line)
|
||||
if match:
|
||||
return filename, match.group(1)
|
||||
elif _re_co_missing_rev.match(line) or _re_co_side_branches.match(line):
|
||||
raise COMissingRevision, "Got missing revision error from co output stream"
|
||||
elif _re_co_warning.match(line):
|
||||
pass
|
||||
else:
|
||||
raise COMalformedOutput, "Unable to find revision in co output stream"
|
||||
|
||||
# if we get here, the second line wasn't a revision, but it was a
|
||||
# warning we can ignore. look for a revision in the third line.
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
raise COMalformedOutput, "Missing third line from co output stream"
|
||||
match = _re_co_revision.match(line)
|
||||
if match:
|
||||
return filename, match.group(1)
|
||||
raise COMalformedOutput, "Unable to find revision in co output stream"
|
||||
|
||||
|
||||
# if your rlog doesn't use 77 '=' characters, then this must change
|
||||
LOG_END_MARKER = '=' * 77 + '\n'
|
||||
ENTRY_END_MARKER = '-' * 28 + '\n'
|
||||
|
@@ -346,7 +346,7 @@ class CVSParser(rcsparse.Sink):
|
||||
is_trunk_revision = self.trunk_rev.match(revision) is not None
|
||||
|
||||
if is_trunk_revision:
|
||||
diffs = self.deltatext_split(last_revision)
|
||||
diffs = self.deltatext_split(last_revision)
|
||||
|
||||
# Revisions on the trunk specify deltas that transform a
|
||||
# revision into an earlier revision, so invert the translation
|
||||
@@ -379,7 +379,7 @@ class CVSParser(rcsparse.Sink):
|
||||
# the trunk. They specify deltas that transform a revision
|
||||
# into a later revision.
|
||||
adjust = 0
|
||||
diffs = self.deltatext_split(revision)
|
||||
diffs = self.deltatext_split(revision)
|
||||
for command in diffs:
|
||||
if skip > 0:
|
||||
skip = skip - 1
|
||||
|
@@ -78,7 +78,7 @@ class RCSStopParser(Exception):
|
||||
#
|
||||
|
||||
class _Parser:
|
||||
stream_class = None # subclasses need to define this
|
||||
stream_class = None # subclasses need to define this
|
||||
|
||||
def parse_rcs_admin(self):
|
||||
while 1:
|
||||
@@ -196,7 +196,7 @@ class _Parser:
|
||||
if token == ';':
|
||||
break
|
||||
author = author + token + ' '
|
||||
author = author[:-1] # toss the trailing space
|
||||
author = author[:-1] # toss the trailing space
|
||||
|
||||
# Parse state
|
||||
self.ts.match('state')
|
||||
@@ -206,7 +206,7 @@ class _Parser:
|
||||
if token == ';':
|
||||
break
|
||||
state = state + token + ' '
|
||||
state = state[:-1] # toss the trailing space
|
||||
state = state[:-1] # toss the trailing space
|
||||
|
||||
# Parse branches
|
||||
self.ts.match('branches')
|
||||
|
@@ -26,7 +26,7 @@ class _TokenStream:
|
||||
# note: we use a multiple of a standard block size
|
||||
CHUNK_SIZE = 192 * 512 # about 100k
|
||||
|
||||
# CHUNK_SIZE = 5 # for debugging, make the function grind...
|
||||
# CHUNK_SIZE = 5 # for debugging, make the function grind...
|
||||
|
||||
def __init__(self, file):
|
||||
self.rcsfile = file
|
||||
@@ -51,7 +51,7 @@ class _TokenStream:
|
||||
buf = self.rcsfile.read(self.CHUNK_SIZE)
|
||||
if buf == '':
|
||||
# signal EOF by returning None as the token
|
||||
del self.buf # so we fail if get() is called again
|
||||
del self.buf # so we fail if get() is called again
|
||||
return None
|
||||
idx = 0
|
||||
|
||||
|
@@ -25,7 +25,7 @@ _tt = TextTools
|
||||
_idchar_list = map(chr, range(33, 127)) + map(chr, range(160, 256))
|
||||
_idchar_list.remove('$')
|
||||
_idchar_list.remove(',')
|
||||
#_idchar_list.remove('.') # leave as part of 'num' symbol
|
||||
#_idchar_list.remove('.') leave as part of 'num' symbol
|
||||
_idchar_list.remove(':')
|
||||
_idchar_list.remove(';')
|
||||
_idchar_list.remove('@')
|
||||
@@ -41,10 +41,10 @@ _T_STRING_START = 40
|
||||
_T_STRING_SPAN = 60
|
||||
_T_STRING_END = 70
|
||||
|
||||
_E_COMPLETE = 100 # ended on a complete token
|
||||
_E_TOKEN = 110 # ended mid-token
|
||||
_E_STRING_SPAN = 130 # ended within a string
|
||||
_E_STRING_END = 140 # ended with string-end ('@') (could be mid-@@)
|
||||
_E_COMPLETE = 100 # ended on a complete token
|
||||
_E_TOKEN = 110 # ended mid-token
|
||||
_E_STRING_SPAN = 130 # ended within a string
|
||||
_E_STRING_END = 140 # ended with string-end ('@') (could be mid-@@)
|
||||
|
||||
_SUCCESS = +100
|
||||
|
||||
@@ -65,7 +65,7 @@ class _mxTokenStream:
|
||||
# note: we use a multiple of a standard block size
|
||||
CHUNK_SIZE = 192 * 512 # about 100k
|
||||
|
||||
# CHUNK_SIZE = 5 # for debugging, make the function grind...
|
||||
# CHUNK_SIZE = 5 # for debugging, make the function grind...
|
||||
|
||||
def __init__(self, file):
|
||||
self.rcsfile = file
|
||||
|
110
lib/viewvc.py
110
lib/viewvc.py
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
__version__ = '1.0.7'
|
||||
__version__ = '1.0.5'
|
||||
|
||||
# this comes from our library; measure the startup time
|
||||
import debug
|
||||
@@ -160,15 +160,6 @@ class Request:
|
||||
# validate the parameter
|
||||
_validate_param(name, values[0])
|
||||
|
||||
# Only allow the magic ViewVC MIME types (the ones used for
|
||||
# requesting the markup as as-text views) to be declared via CGI
|
||||
# params. Ignore disallowed values.
|
||||
if (name == 'content-type') and \
|
||||
(not values[0] in (viewcvs_mime_type,
|
||||
alt_mime_type,
|
||||
'text/plain')):
|
||||
continue
|
||||
|
||||
# if we're here, then the parameter is okay
|
||||
self.query_dict[name] = values[0]
|
||||
|
||||
@@ -200,7 +191,7 @@ class Request:
|
||||
# handle tarball magic suffixes
|
||||
if self.view_func is download_tarball:
|
||||
if (self.query_dict.get('parent')):
|
||||
del path_parts[-1]
|
||||
del path_parts[-1]
|
||||
elif path_parts[-1][-7:] == ".tar.gz":
|
||||
path_parts[-1] = path_parts[-1][:-7]
|
||||
|
||||
@@ -304,7 +295,7 @@ class Request:
|
||||
|
||||
if self.pathtype is None:
|
||||
# Path doesn't exist, see if it could be an old-style ViewVC URL
|
||||
# with a fake suffix.
|
||||
# with a fake suffix.
|
||||
result = _strip_suffix('.diff', path_parts, pathrev, vclib.FILE, \
|
||||
self.repos, view_diff) or \
|
||||
_strip_suffix('.tar.gz', path_parts, pathrev, vclib.DIR, \
|
||||
@@ -323,7 +314,7 @@ class Request:
|
||||
if result:
|
||||
self.path_parts, self.pathtype, self.view_func = result
|
||||
self.where = _path_join(self.path_parts)
|
||||
needs_redirect = 1
|
||||
needs_redirect = 1
|
||||
else:
|
||||
raise debug.ViewVCException('%s: unknown location'
|
||||
% self.where, '404 Not Found')
|
||||
@@ -355,7 +346,7 @@ class Request:
|
||||
self.view_func = view_roots
|
||||
elif self.pathtype == vclib.DIR:
|
||||
# ViewCVS 0.9.2 used to put ?tarball=1 at the end of tarball urls
|
||||
if self.query_dict.has_key('tarball'):
|
||||
if self.query_dict.has_key('tarball'):
|
||||
self.view_func = download_tarball
|
||||
else:
|
||||
self.view_func = view_directory
|
||||
@@ -514,7 +505,7 @@ class Request:
|
||||
if view_func is download_tarball:
|
||||
if not where and not cfg.options.root_as_url_component:
|
||||
url = url + '/' + rootname + '-root'
|
||||
params['parent'] = '1'
|
||||
params['parent'] = '1'
|
||||
url = url + '.tar.gz'
|
||||
|
||||
# add trailing slash for a directory
|
||||
@@ -1560,9 +1551,16 @@ def view_directory(request):
|
||||
cfg.options.hide_attic))
|
||||
options["cvs_subdirs"] = (cfg.options.show_subdir_lastmod and
|
||||
cfg.options.show_logs)
|
||||
|
||||
file_data = request.repos.listdir(request.path_parts, request.pathrev,
|
||||
options)
|
||||
|
||||
# Filter file list if a regex is specified
|
||||
search_re = request.query_dict.get('search', '')
|
||||
if cfg.options.use_re_search and search_re:
|
||||
file_data = search_files(request.repos, request.path_parts, request.pathrev,
|
||||
file_data, search_re)
|
||||
|
||||
# Retrieve log messages, authors, revision numbers, timestamps
|
||||
request.repos.dirlogs(request.path_parts, request.pathrev, file_data, options)
|
||||
|
||||
@@ -1572,12 +1570,6 @@ def view_directory(request):
|
||||
sort_file_data(file_data, request.roottype, sortdir, sortby,
|
||||
cfg.options.sort_group_dirs)
|
||||
|
||||
# If a regex is specified, build a compiled form thereof for filtering
|
||||
searchstr = None
|
||||
search_re = request.query_dict.get('search', '')
|
||||
if cfg.options.use_re_search and search_re:
|
||||
searchstr = re.compile(search_re)
|
||||
|
||||
# loop through entries creating rows and changing these values
|
||||
rows = [ ]
|
||||
num_displayed = 0
|
||||
@@ -1644,17 +1636,10 @@ def view_directory(request):
|
||||
escape=1)
|
||||
|
||||
elif file.kind == vclib.FILE:
|
||||
if searchstr is not None:
|
||||
if request.roottype == 'cvs' and (file.errors or file.dead):
|
||||
continue
|
||||
if not search_file(request.repos, request.path_parts + [file.name],
|
||||
request.pathrev, searchstr):
|
||||
continue
|
||||
if request.roottype == 'cvs' and file.dead:
|
||||
num_dead = num_dead + 1
|
||||
if hideattic:
|
||||
continue
|
||||
|
||||
num_displayed = num_displayed + 1
|
||||
|
||||
file_where = where_prefix + file.name
|
||||
@@ -2205,7 +2190,7 @@ def view_annotate(request):
|
||||
|
||||
diff_url = request.get_url(view_func=view_diff,
|
||||
params={'r1': None, 'r2': None},
|
||||
escape=1, partial=1)
|
||||
escape=1, partial=1)
|
||||
|
||||
include_url = request.get_url(view_func=view_log, where='/WHERE/',
|
||||
pathtype=vclib.FILE, params={}, escape=1)
|
||||
@@ -2287,23 +2272,58 @@ def view_cvsgraph(request):
|
||||
request.server.header()
|
||||
generate_page(request, "graph", data)
|
||||
|
||||
def search_file(repos, path_parts, rev, search_re):
|
||||
"""Return 1 iff the contents of the file at PATH_PARTS in REPOS as
|
||||
of revision REV matches regular expression SEARCH_RE."""
|
||||
def search_files(repos, path_parts, rev, files, search_re):
|
||||
""" Search files in a directory for a regular expression.
|
||||
|
||||
Does a check-out of each file in the directory. Only checks for
|
||||
the first match.
|
||||
"""
|
||||
|
||||
# Pass in search regular expression. We check out
|
||||
# each file and look for the regular expression. We then return the data
|
||||
# for all files that match the regex.
|
||||
|
||||
# Compile to make sure we do this as fast as possible.
|
||||
searchstr = re.compile(search_re)
|
||||
|
||||
# Will become list of files that have at least one match.
|
||||
# new_file_list also includes directories.
|
||||
new_file_list = [ ]
|
||||
|
||||
# Loop on every file (and directory)
|
||||
for file in files:
|
||||
# Is this a directory? If so, append name to new_file_list
|
||||
# and move to next file.
|
||||
if file.kind != vclib.FILE:
|
||||
new_file_list.append(file)
|
||||
continue
|
||||
|
||||
# Only files at this point
|
||||
|
||||
# Shouldn't search binary files, or should we?
|
||||
# Should allow all text mime types to pass.
|
||||
if not is_text(guess_mime(file.name)):
|
||||
continue
|
||||
|
||||
# Only text files at this point
|
||||
|
||||
# Assign contents of checked out file to fp.
|
||||
fp = repos.openfile(path_parts + [file.name], rev)[0]
|
||||
|
||||
# Read in each line, use re.search to search line.
|
||||
# If successful, add file to new_file_list and break.
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
if searchstr.search(line):
|
||||
new_file_list.append(file)
|
||||
# close down the pipe (and wait for the child to terminate)
|
||||
fp.close()
|
||||
break
|
||||
|
||||
return new_file_list
|
||||
|
||||
# Read in each line of a checked-out file, and then use re.search to
|
||||
# search line.
|
||||
fp = repos.openfile(path_parts, rev)[0]
|
||||
matches = 0
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
if search_re.search(line):
|
||||
matches = 1
|
||||
fp.close()
|
||||
break
|
||||
return matches
|
||||
|
||||
def view_doc(request):
|
||||
"""Serve ViewVC static content locally.
|
||||
|
@@ -1,24 +1,34 @@
|
||||
[if-any search_re_form]
|
||||
<hr />
|
||||
<div>
|
||||
Show files containing the regular expression:
|
||||
<form method="get" action="[search_re_action]" style="display: inline;">
|
||||
<div style="display: inline;">
|
||||
[search_re_hidden_values]
|
||||
<input type="text" name="search" value="[search_re]" />
|
||||
<input type="submit" value="Show" />
|
||||
</div>
|
||||
</form>
|
||||
[if-any search_re]
|
||||
<form method="get" action="[search_re_action]" style="display: inline;">
|
||||
<div style="display: inline;">
|
||||
[search_re_hidden_values]
|
||||
<input type="submit" value="Show all files" />
|
||||
</div>
|
||||
</form>
|
||||
<hr />
|
||||
[# this table holds the selectors on the left, and reset on the right ]
|
||||
<table class="auto">
|
||||
<tr>
|
||||
<td>Show files containing the regular expression:</td>
|
||||
<td>
|
||||
<form method="get" action="[search_re_action]">
|
||||
<div>
|
||||
[search_re_hidden_values]
|
||||
<input type="text" name="search" value="[search_re]" />
|
||||
<input type="submit" value="Show" />
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
[if-any search_re]
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
<form method="get" action="[search_tag_action]">
|
||||
<div>
|
||||
[search_tag_hidden_values]
|
||||
<input type="submit" value="Show all files" />
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
</table>
|
||||
[end]
|
||||
[end]
|
||||
</div>
|
||||
|
||||
[# if you want to disable tarball generation remove the following: ]
|
||||
[if-any tarball_href]
|
||||
|
Reference in New Issue
Block a user