5 # |
5 # |
6 # This software may be used and distributed according to the terms |
6 # This software may be used and distributed according to the terms |
7 # of the GNU General Public License, incorporated herein by reference. |
7 # of the GNU General Public License, incorporated herein by reference. |
8 |
8 |
9 import os, cgi, sys, urllib |
9 import os, cgi, sys, urllib |
|
10 import mimetypes |
10 from demandload import demandload |
11 from demandload import demandload |
11 demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") |
12 demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") |
12 demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") |
13 demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") |
13 demandload(globals(), "mimetypes") |
14 demandload(globals(), "mimetypes") |
14 from node import * |
15 from node import * |
843 'fa': [('cmd', ['annotate']), ('filenode', None)], |
844 'fa': [('cmd', ['annotate']), ('filenode', None)], |
844 'mf': [('cmd', ['manifest']), ('manifest', None)], |
845 'mf': [('cmd', ['manifest']), ('manifest', None)], |
845 'ca': [('cmd', ['archive']), ('node', None)], |
846 'ca': [('cmd', ['archive']), ('node', None)], |
846 'tags': [('cmd', ['tags'])], |
847 'tags': [('cmd', ['tags'])], |
847 'tip': [('cmd', ['changeset']), ('node', ['tip'])], |
848 'tip': [('cmd', ['changeset']), ('node', ['tip'])], |
|
849 'static': [('cmd', ['static']), ('file', None)] |
848 } |
850 } |
849 |
851 |
850 for k in shortcuts.iterkeys(): |
852 for k in shortcuts.iterkeys(): |
851 if form.has_key(k): |
853 if form.has_key(k): |
852 for name, value in shortcuts[k]: |
854 for name, value in shortcuts[k]: |
858 self.refresh() |
860 self.refresh() |
859 |
861 |
860 expand_form(req.form) |
862 expand_form(req.form) |
861 |
863 |
862 t = self.repo.ui.config("web", "templates", templatepath()) |
864 t = self.repo.ui.config("web", "templates", templatepath()) |
|
865 static = self.repo.ui.config("web", "static", os.path.join(t,"static")) |
863 m = os.path.join(t, "map") |
866 m = os.path.join(t, "map") |
864 style = self.repo.ui.config("web", "style", "") |
867 style = self.repo.ui.config("web", "style", "") |
865 if req.form.has_key('style'): |
868 if req.form.has_key('style'): |
866 style = req.form['style'][0] |
869 style = req.form['style'][0] |
867 if style: |
870 if style: |
980 self.repo.ui.configbool("web", "allow" + type, False)): |
983 self.repo.ui.configbool("web", "allow" + type, False)): |
981 self.archive(req, changeset, type) |
984 self.archive(req, changeset, type) |
982 return |
985 return |
983 |
986 |
984 req.write(self.t("error")) |
987 req.write(self.t("error")) |
|
988 |
|
989 elif req.form['cmd'][0] == 'static': |
|
990 fname = req.form['file'][0] |
|
991 |
|
992 fname = os.path.realpath(os.path.join(static, fname)) |
|
993 |
|
994 try: |
|
995 # the static dir should be a substring in the real |
|
996 # file path, if it is not, we have something strange |
|
997 # going on => security breach attempt? |
|
998 # |
|
999 # This will either: |
|
1000 # 1) find the `static' path at index 0 = success |
|
1001 # 2) find the `static' path at other index = error |
|
1002 # 3) not find the `static' path = ValueError generated |
|
1003 if fname.index(static) != 0: |
|
1004 # generate ValueError manually |
|
1005 raise ValueError() |
|
1006 |
|
1007 os.stat(fname) |
|
1008 |
|
1009 ct = mimetypes.guess_type(fname)[0] |
|
1010 if ct == None: |
|
1011 ct = "text/plain" |
|
1012 |
|
1013 req.write("Content-type: " + ct + "\n\n" + file(fname).read()) |
|
1014 except ValueError: |
|
1015 # security breach attempt |
|
1016 req.write(self.t("error")) |
|
1017 except OSError, e: |
|
1018 if e.errno == errno.ENOENT: |
|
1019 req.write(self.t("error")) |
985 |
1020 |
986 else: |
1021 else: |
987 req.write(self.t("error")) |
1022 req.write(self.t("error")) |
988 |
1023 |
989 def create_server(repo): |
1024 def create_server(repo): |