##// END OF EJS Templates
hgweb: Quote filenames when downloading raw files.
Thomas Arendsen Hein -
r6137:1c0e7afe default
parent child Browse files
Show More
@@ -1,100 +1,102
1 1 # hgweb/request.py - An http request from either CGI or the standalone server.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 9 import socket, cgi, errno
10 10 from mercurial.i18n import gettext as _
11 11 from common import ErrorResponse, statusmessage
12 12
13 13 class wsgirequest(object):
14 14 def __init__(self, wsgienv, start_response):
15 15 version = wsgienv['wsgi.version']
16 16 if (version < (1, 0)) or (version >= (2, 0)):
17 17 raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
18 18 % version)
19 19 self.inp = wsgienv['wsgi.input']
20 20 self.err = wsgienv['wsgi.errors']
21 21 self.threaded = wsgienv['wsgi.multithread']
22 22 self.multiprocess = wsgienv['wsgi.multiprocess']
23 23 self.run_once = wsgienv['wsgi.run_once']
24 24 self.env = wsgienv
25 25 self.form = cgi.parse(self.inp, self.env, keep_blank_values=1)
26 26 self._start_response = start_response
27 27 self.server_write = None
28 28 self.headers = []
29 29
30 30 def __iter__(self):
31 31 return iter([])
32 32
33 33 def read(self, count=-1):
34 34 return self.inp.read(count)
35 35
36 36 def respond(self, status, type=None, filename=None, length=0):
37 37 if self._start_response is not None:
38 38
39 39 self.httphdr(type, filename, length)
40 40 if not self.headers:
41 41 raise RuntimeError("request.write called before headers sent")
42 42
43 43 for k, v in self.headers:
44 44 if not isinstance(v, str):
45 45 raise TypeError('header value must be string: %r' % v)
46 46
47 47 if isinstance(status, ErrorResponse):
48 48 status = statusmessage(status.code)
49 49 elif status == 200:
50 50 status = '200 Script output follows'
51 51 elif isinstance(status, int):
52 52 status = statusmessage(status)
53 53
54 54 self.server_write = self._start_response(status, self.headers)
55 55 self._start_response = None
56 56 self.headers = []
57 57
58 58 def write(self, thing):
59 59 if hasattr(thing, "__iter__"):
60 60 for part in thing:
61 61 self.write(part)
62 62 else:
63 63 thing = str(thing)
64 64 try:
65 65 self.server_write(thing)
66 66 except socket.error, inst:
67 67 if inst[0] != errno.ECONNRESET:
68 68 raise
69 69
70 70 def writelines(self, lines):
71 71 for line in lines:
72 72 self.write(line)
73 73
74 74 def flush(self):
75 75 return None
76 76
77 77 def close(self):
78 78 return None
79 79
80 80 def header(self, headers=[('Content-Type','text/html')]):
81 81 self.headers.extend(headers)
82 82
83 83 def httphdr(self, type=None, filename=None, length=0, headers={}):
84 84 headers = headers.items()
85 85 if type is not None:
86 86 headers.append(('Content-Type', type))
87 87 if filename:
88 filename = (filename.split('/')[-1]
89 .replace('\\', '\\\\').replace('"', '\\"'))
88 90 headers.append(('Content-Disposition',
89 'inline; filename=%s' % filename.split('/')[-1]))
91 'inline; filename="%s"' % filename))
90 92 if length:
91 93 headers.append(('Content-Length', str(length)))
92 94 self.header(headers)
93 95
94 96 def wsgiapplication(app_maker):
95 97 '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
96 98 can and should now be used as a WSGI application.'''
97 99 application = app_maker()
98 100 def run_wsgi(env, respond):
99 101 return application(env, respond)
100 102 return run_wsgi
@@ -1,23 +1,23
1 1 #!/bin/sh
2 2
3 3 hg init test
4 4 cd test
5 5 mkdir sub
6 cat >sub/sometext.txt <<ENDSOME
6 cat >'sub/some "text".txt' <<ENDSOME
7 7 This is just some random text
8 8 that will go inside the file and take a few lines.
9 9 It is very boring to read, but computers don't
10 10 care about things like that.
11 11 ENDSOME
12 hg add sub/sometext.txt
12 hg add 'sub/some "text".txt'
13 13 hg commit -d "1 0" -m "Just some text"
14 14 hg serve -p $HGPORT -A access.log -E error.log -d --pid-file=hg.pid
15 15 cat hg.pid >> $DAEMON_PIDS
16 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/?f=37afcac6d393;file=sub/sometext.txt;style=raw' content-type content-length content-disposition) >getoutput.txt &
16 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/?f=a23bf1310f6e;file=sub/some%20%22text%22.txt;style=raw' content-type content-length content-disposition) >getoutput.txt &
17 17
18 18 sleep 5
19 19 kill `cat hg.pid`
20 20 sleep 1 # wait for server to scream and die
21 21 cat getoutput.txt
22 22 cat access.log error.log | \
23 23 sed 's/^[^ ]*\( [^[]*\[\)[^]]*\(\].*\)$/host\1date\2/'
@@ -1,10 +1,10
1 1 200 Script output follows
2 2 content-type: text/plain
3 3 content-length: 157
4 content-disposition: inline; filename=sometext.txt
4 content-disposition: inline; filename="some \"text\".txt"
5 5
6 6 This is just some random text
7 7 that will go inside the file and take a few lines.
8 8 It is very boring to read, but computers don't
9 9 care about things like that.
10 host - - [date] "GET /?f=37afcac6d393;file=sub/sometext.txt;style=raw HTTP/1.1" 200 -
10 host - - [date] "GET /?f=a23bf1310f6e;file=sub/some%20%22text%22.txt;style=raw HTTP/1.1" 200 -
General Comments 0
You need to be logged in to leave comments. Login now