--- a/mercurial/hgweb.py Fri Feb 17 17:41:23 2006 -0600
+++ b/mercurial/hgweb.py Sat Feb 18 22:24:42 2006 -0500
@@ -7,6 +7,7 @@
# of the GNU General Public License, incorporated herein by reference.
import os, cgi, sys, urllib
+import mimetypes
from demandload import demandload
demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser")
demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util")
@@ -843,6 +844,7 @@
'ca': [('cmd', ['archive']), ('node', None)],
'tags': [('cmd', ['tags'])],
'tip': [('cmd', ['changeset']), ('node', ['tip'])],
+ 'static': [('cmd', ['static']), ('file', None)]
}
for k in shortcuts.iterkeys():
@@ -858,6 +860,7 @@
expand_form(req.form)
t = self.repo.ui.config("web", "templates", templatepath())
+ static = self.repo.ui.config("web", "static", os.path.join(t,"static"))
m = os.path.join(t, "map")
style = self.repo.ui.config("web", "style", "")
if req.form.has_key('style'):
@@ -981,6 +984,38 @@
req.write(self.t("error"))
+ elif req.form['cmd'][0] == 'static':
+ fname = req.form['file'][0]
+
+ fname = os.path.realpath(os.path.join(static, fname))
+
+ try:
+ # the static dir should be a substring in the real
+ # file path, if it is not, we have something strange
+ # going on => security breach attempt?
+ #
+ # This will either:
+ # 1) find the `static' path at index 0 = success
+ # 2) find the `static' path at other index = error
+ # 3) not find the `static' path = ValueError generated
+ if fname.index(static) != 0:
+ # generate ValueError manually
+ raise ValueError()
+
+ os.stat(fname)
+
+ ct = mimetypes.guess_type(fname)[0]
+ if ct == None:
+ ct = "text/plain"
+
+ req.write("Content-type: " + ct + "\n\n" + file(fname).read())
+ except ValueError:
+ # security breach attempt
+ req.write(self.t("error"))
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ req.write(self.t("error"))
+
else:
req.write(self.t("error"))
--- a/setup.py Fri Feb 17 17:41:23 2006 -0600
+++ b/setup.py Sat Feb 18 22:24:42 2006 -0500
@@ -89,7 +89,9 @@
data_files=[('mercurial/templates',
['templates/map'] +
glob.glob('templates/map-*') +
- glob.glob('templates/*.tmpl'))],
+ glob.glob('templates/*.tmpl')),
+ ('mercurial/templates/static',
+ glob.glob('templates/static/*'))],
cmdclass=cmdclass,
scripts=['hg', 'hgmerge'],
options=dict(bdist_mpkg=dict(zipdist=True,
--- a/templates/error-gitweb.tmpl Fri Feb 17 17:41:23 2006 -0600
+++ b/templates/error-gitweb.tmpl Sat Feb 18 22:24:42 2006 -0500
@@ -1,11 +1,21 @@
#header#
+<title>#repo|escape#: Error</title>
+<link rel="alternate" type="application/rss+xml"
+ href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
+</head>
+<body>
+
+<div class="page_header">
+<a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / error
+</div>
+
<div class="page_nav">
-<a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=changelog;style=gitweb">log</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?cmd=manifest;manifest=#manifest#;path=/;style=gitweb">manifest</a><br/>
+<a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?cmd=manifest;manifest=#manifest#;path=/;style=gitweb">manifest</a><br/>
</div>
<div>
<br/>
-<i>Error parsing query string</i><br/>
+<i>An error occured while processing your request</i><br/>
<br/>
</div>
--- a/templates/header-gitweb.tmpl Fri Feb 17 17:41:23 2006 -0600
+++ b/templates/header-gitweb.tmpl Sat Feb 18 22:24:42 2006 -0500
@@ -6,54 +6,5 @@
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="robots" content="index, nofollow"/>
-<style type="text/css">
-body { font-family: sans-serif; font-size: 12px; margin:0px; border:solid #d9d8d1; border-width:1px; margin:10px; }
-a { color:#0000cc; }
-a:hover, a:visited, a:active { color:#880000; }
-div.page_header { height:25px; padding:8px; font-size:18px; font-weight:bold; background-color:#d9d8d1; }
-div.page_header a:visited { color:#0000cc; }
-div.page_header a:hover { color:#880000; }
-div.page_nav { padding:8px; }
-div.page_nav a:visited { color:#0000cc; }
-div.page_path { padding:8px; border:solid #d9d8d1; border-width:0px 0px 1px}
-div.page_footer { height:17px; padding:4px 8px; background-color: #d9d8d1; }
-div.page_footer_text { float:left; color:#555555; font-style:italic; }
-div.page_body { padding:8px; }
-div.title, a.title {
- display:block; padding:6px 8px;
- font-weight:bold; background-color:#edece6; text-decoration:none; color:#000000;
-}
-a.title:hover { background-color: #d9d8d1; }
-div.title_text { padding:6px 0px; border: solid #d9d8d1; border-width:0px 0px 1px; }
-div.log_body { padding:8px 8px 8px 150px; }
-span.age { position:relative; float:left; width:142px; font-style:italic; }
-div.log_link {
- padding:0px 8px;
- font-size:10px; font-family:sans-serif; font-style:normal;
- position:relative; float:left; width:136px;
-}
-div.list_head { padding:6px 8px 4px; border:solid #d9d8d1; border-width:1px 0px 0px; font-style:italic; }
-a.list { text-decoration:none; color:#000000; }
-a.list:hover { text-decoration:underline; color:#880000; }
-table { padding:8px 4px; }
-th { padding:2px 5px; font-size:12px; text-align:left; }
-tr.light:hover, .parity0:hover { background-color:#edece6; }
-tr.dark, .parity1 { background-color:#f6f6f0; }
-tr.dark:hover, .parity1:hover { background-color:#edece6; }
-td { padding:2px 5px; font-size:12px; vertical-align:top; }
-td.link { padding:2px 5px; font-family:sans-serif; font-size:10px; }
-div.pre { font-family:monospace; font-size:12px; white-space:pre; }
-div.diff_info { font-family:monospace; color:#000099; background-color:#edece6; font-style:italic; }
-div.index_include { border:solid #d9d8d1; border-width:0px 0px 1px; padding:12px 8px; }
-div.search { margin:4px 8px; position:absolute; top:56px; right:12px }
-.linenr { color:#999999; text-decoration:none }
-a.rss_logo {
- float:right; padding:3px 0px; width:35px; line-height:10px;
- border:1px solid; border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
- color:#ffffff; background-color:#ff6600;
- font-weight:bold; font-family:sans-serif; font-size:10px;
- text-align:center; text-decoration:none;
-}
-a.rss_logo:hover { background-color:#ee5500; }
-</style>
+<style type="text/css">/*<![CDATA[*/ @import "?static=style-gitweb.css"; /*]]>*/</style>
--- a/templates/header.tmpl Fri Feb 17 17:41:23 2006 -0600
+++ b/templates/header.tmpl Sat Feb 18 22:24:42 2006 -0500
@@ -4,77 +4,4 @@
<html>
<head>
<meta name="robots" content="index, nofollow" />
-<style type="text/css">
-<!--
-a { text-decoration:none; }
-.parity0 { background-color: #dddddd; }
-.parity1 { background-color: #eeeeee; }
-.lineno { width: 60px; color: #aaaaaa; font-size: smaller;
- text-align: right; padding-right:1em; }
-.plusline { color: green; }
-.minusline { color: red; }
-.atline { color: purple; }
-.annotate { font-size: smaller; text-align: right; padding-right: 1em; }
-.buttons a {
- background-color: #666666;
- padding: 2pt;
- color: white;
- font-family: sans;
- font-weight: bold;
-}
-.navigate a {
- background-color: #ccc;
- padding: 2pt;
- font-family: sans;
- color: black;
-}
-
-.metatag {
- background-color: #888888;
- color: white;
- text-align: right;
-}
-
-/* Common */
-pre { margin: 0; }
-
-.logo {
- background-color: #333;
- padding: 4pt;
- margin: 8pt 0 8pt 8pt;
- font-family: sans;
- font-size: 60%;
- color: white;
- float: right;
- clear: right;
- text-align: left;
-}
-
-.logo a {
- font-weight: bold;
- font-size: 150%;
- color: #999;
-}
-
-/* Changelog entries */
-.changelogEntry { width: 100%; }
-.changelogEntry th { font-weight: normal; text-align: right; vertical-align: top; }
-.changelogEntry th.age, .changelogEntry th.firstline { font-weight: bold; }
-.changelogEntry th.firstline { text-align: left; width: inherit; }
-
-/* Tag entries */
-#tagEntries { list-style: none; margin: 0; padding: 0; }
-#tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
-#tagEntries .tagEntry span.node { font-family: monospace; }
-
-/* Changeset entry */
-#changesetEntry { }
-#changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
-#changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
-
-/* File diff view */
-#filediffEntry { }
-#filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
-
--->
-</style>
+<style type="text/css">/*<![CDATA[*/ @import "?static=style.css"; /*]]>*/</style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/static/style-gitweb.css Sat Feb 18 22:24:42 2006 -0500
@@ -0,0 +1,48 @@
+body { font-family: sans-serif; font-size: 12px; margin:0px; border:solid #d9d8d1; border-width:1px; margin:10px; }
+a { color:#0000cc; }
+a:hover, a:visited, a:active { color:#880000; }
+div.page_header { height:25px; padding:8px; font-size:18px; font-weight:bold; background-color:#d9d8d1; }
+div.page_header a:visited { color:#0000cc; }
+div.page_header a:hover { color:#880000; }
+div.page_nav { padding:8px; }
+div.page_nav a:visited { color:#0000cc; }
+div.page_path { padding:8px; border:solid #d9d8d1; border-width:0px 0px 1px}
+div.page_footer { height:17px; padding:4px 8px; background-color: #d9d8d1; }
+div.page_footer_text { float:left; color:#555555; font-style:italic; }
+div.page_body { padding:8px; }
+div.title, a.title {
+ display:block; padding:6px 8px;
+ font-weight:bold; background-color:#edece6; text-decoration:none; color:#000000;
+}
+a.title:hover { background-color: #d9d8d1; }
+div.title_text { padding:6px 0px; border: solid #d9d8d1; border-width:0px 0px 1px; }
+div.log_body { padding:8px 8px 8px 150px; }
+span.age { position:relative; float:left; width:142px; font-style:italic; }
+div.log_link {
+ padding:0px 8px;
+ font-size:10px; font-family:sans-serif; font-style:normal;
+ position:relative; float:left; width:136px;
+}
+div.list_head { padding:6px 8px 4px; border:solid #d9d8d1; border-width:1px 0px 0px; font-style:italic; }
+a.list { text-decoration:none; color:#000000; }
+a.list:hover { text-decoration:underline; color:#880000; }
+table { padding:8px 4px; }
+th { padding:2px 5px; font-size:12px; text-align:left; }
+tr.light:hover, .parity0:hover { background-color:#edece6; }
+tr.dark, .parity1 { background-color:#f6f6f0; }
+tr.dark:hover, .parity1:hover { background-color:#edece6; }
+td { padding:2px 5px; font-size:12px; vertical-align:top; }
+td.link { padding:2px 5px; font-family:sans-serif; font-size:10px; }
+div.pre { font-family:monospace; font-size:12px; white-space:pre; }
+div.diff_info { font-family:monospace; color:#000099; background-color:#edece6; font-style:italic; }
+div.index_include { border:solid #d9d8d1; border-width:0px 0px 1px; padding:12px 8px; }
+div.search { margin:4px 8px; position:absolute; top:56px; right:12px }
+.linenr { color:#999999; text-decoration:none }
+a.rss_logo {
+ float:right; padding:3px 0px; width:35px; line-height:10px;
+ border:1px solid; border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
+ color:#ffffff; background-color:#ff6600;
+ font-weight:bold; font-family:sans-serif; font-size:10px;
+ text-align:center; text-decoration:none;
+}
+a.rss_logo:hover { background-color:#ee5500; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/static/style.css Sat Feb 18 22:24:42 2006 -0500
@@ -0,0 +1,70 @@
+a { text-decoration:none; }
+.parity0 { background-color: #dddddd; }
+.parity1 { background-color: #eeeeee; }
+.lineno { width: 60px; color: #aaaaaa; font-size: smaller;
+ text-align: right; padding-right:1em; }
+.plusline { color: green; }
+.minusline { color: red; }
+.atline { color: purple; }
+.annotate { font-size: smaller; text-align: right; padding-right: 1em; }
+.buttons a {
+ background-color: #666666;
+ padding: 2pt;
+ color: white;
+ font-family: sans;
+ font-weight: bold;
+}
+.navigate a {
+ background-color: #ccc;
+ padding: 2pt;
+ font-family: sans;
+ color: black;
+}
+
+.metatag {
+ background-color: #888888;
+ color: white;
+ text-align: right;
+}
+
+/* Common */
+pre { margin: 0; }
+
+.logo {
+ background-color: #333;
+ padding: 4pt;
+ margin: 8pt 0 8pt 8pt;
+ font-family: sans;
+ font-size: 60%;
+ color: white;
+ float: right;
+ clear: right;
+ text-align: left;
+}
+
+.logo a {
+ font-weight: bold;
+ font-size: 150%;
+ color: #999;
+}
+
+/* Changelog entries */
+.changelogEntry { width: 100%; }
+.changelogEntry th { font-weight: normal; text-align: right; vertical-align: top; }
+.changelogEntry th.age, .changelogEntry th.firstline { font-weight: bold; }
+.changelogEntry th.firstline { text-align: left; width: inherit; }
+
+/* Tag entries */
+#tagEntries { list-style: none; margin: 0; padding: 0; }
+#tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
+#tagEntries .tagEntry span.node { font-family: monospace; }
+
+/* Changeset entry */
+#changesetEntry { }
+#changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
+#changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
+
+/* File diff view */
+#filediffEntry { }
+#filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
+