]>
Commit | Line | Data |
---|---|---|
818a4490 | 1 | #!/usr/bin/python |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2007 Michael Tremer & Christian Schmidt # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
22 | import os | |
23 | import cgi | |
516a72ab MT |
24 | import sys |
25 | import sha | |
26 | from pysqlite2 import dbapi2 as sqlite | |
27 | ||
28 | sys.path.append(".") | |
29 | ||
818a4490 | 30 | from git import * |
31 | ||
6a170c4e MT |
32 | def give_403(): |
33 | print "Status: 403 Forbidden" | |
34 | print "Pragma: no-cache" | |
35 | print "Cache-control: no-cache" | |
36 | print "Connection: close" | |
37 | ||
38 | ||
516a72ab | 39 | sys.exit() |
6a170c4e | 40 | |
818a4490 | 41 | def give_404(): |
42 | print "Status: 404 Not found" | |
43 | print "Pragma: no-cache" | |
44 | print "Cache-control: no-cache" | |
45 | print "Connection: close" | |
46 | ||
6a170c4e | 47 | |
516a72ab | 48 | sys.exit() |
818a4490 | 49 | |
50 | def give_302(): | |
51 | print "Status: 302 Moved" | |
52 | print "Location: /" | |
53 | print "Pragma: no-cache" | |
54 | print "Cache-control: no-cache" | |
55 | print "Connection: close" | |
56 | ||
57 | ||
516a72ab | 58 | sys.exit() |
818a4490 | 59 | |
60 | class NotFoundError(Exception): | |
61 | pass | |
62 | ||
63 | class SourceObject: | |
516a72ab MT |
64 | def __init__(self, file): |
65 | self.file = file | |
66 | ||
67 | self.db = sqlite.connect("hashes.db") | |
68 | c = self.db.cursor() | |
69 | c.execute("CREATE TABLE IF NOT EXISTS hashes(file, sha1)") | |
70 | c.close() | |
71 | ||
72 | def getHash(self, type="sha1"): | |
73 | hash = None | |
74 | c = self.db.cursor() | |
75 | c.execute("SELECT %s FROM hashes WHERE file = '%s'" % (type, self.file,)) | |
76 | try: | |
77 | hash = c.fetchone()[0] | |
78 | except TypeError: | |
79 | pass | |
80 | c.close() | |
81 | ||
82 | if not hash: | |
83 | hash = sha.new(self.filedata).hexdigest() | |
84 | c = self.db.cursor() | |
85 | c.execute("INSERT INTO hashes(file, sha1) VALUES('%s', '%s')" % \ | |
86 | (self.file, hash,)) | |
87 | c.close() | |
88 | self.db.commit() | |
89 | return hash | |
90 | ||
91 | def __call__(self): | |
92 | print "Status: 200 - OK" | |
818a4490 | 93 | print "Pragma: no-cache" |
94 | print "Cache-control: no-cache" | |
95 | print "Connection: close" | |
516a72ab MT |
96 | print "Content-type: " + self.getMimetype() |
97 | print "Content-length: %s" % len(self.filedata) | |
98 | print "X-SHA1: " + self.getHash("sha1") | |
99 | print "X-Object: %s" % str(self.__class__).split(".")[1] | |
100 | print # An empty line ends the header | |
101 | print self.filedata | |
102 | ||
818a4490 | 103 | |
104 | class FileObject(SourceObject): | |
516a72ab MT |
105 | def __init__(self, path, file): |
106 | SourceObject.__init__(self, file) | |
107 | self.path = path | |
108 | self.filepath = "/%s/%s/%s" % (os.getcwd(), path, file,) | |
109 | ||
818a4490 | 110 | try: |
111 | f = open(self.filepath, "rb") | |
112 | except: | |
113 | raise NotFoundError | |
114 | ||
115 | self.filedata = f.read() | |
116 | f.close() | |
117 | ||
516a72ab | 118 | def getMimetype(self): |
818a4490 | 119 | default_mimetype = "text/plain" |
120 | from mimetypes import guess_type | |
121 | return guess_type(self.filepath)[0] or default_mimetype | |
122 | ||
818a4490 | 123 | |
516a72ab MT |
124 | class PatchObject(SourceObject): |
125 | def __init__(self, file, url="/srv/git/patches.git"): | |
126 | SourceObject.__init__(self, file) | |
818a4490 | 127 | self.url = url |
818a4490 | 128 | |
818a4490 | 129 | self.repo = Repository(self.url) |
516a72ab | 130 | tree = self.repo.head.tree |
818a4490 | 131 | blob = None |
516a72ab MT |
132 | |
133 | for directory in tree.keys(): | |
134 | if isinstance(tree[directory], Blob): | |
818a4490 | 135 | continue |
136 | try: | |
516a72ab | 137 | blob = tree[directory][self.file] |
818a4490 | 138 | if blob: |
139 | break | |
140 | except KeyError: | |
141 | pass | |
516a72ab | 142 | |
818a4490 | 143 | if not blob: |
144 | raise NotFoundError | |
145 | ||
146 | blob._load() | |
147 | self.filedata = blob._contents | |
520933d9 | 148 | self.filedata += '\n' |
818a4490 | 149 | |
516a72ab MT |
150 | def getMimetype(self): |
151 | return "text/plain" | |
818a4490 | 152 | |
728dfc54 | 153 | |
516a72ab MT |
154 | def main(): |
155 | os.environ["QUERY_STRING"] = \ | |
156 | os.environ["QUERY_STRING"].replace("+", "%2b") | |
818a4490 | 157 | |
516a72ab MT |
158 | file = cgi.FieldStorage().getfirst("file") |
159 | path = cgi.FieldStorage().getfirst("path") | |
6a170c4e | 160 | |
516a72ab MT |
161 | if not os.environ["HTTP_USER_AGENT"].startswith("IPFireSourceGrabber"): |
162 | give_403() | |
818a4490 | 163 | |
516a72ab MT |
164 | if not file: |
165 | give_302() | |
818a4490 | 166 | |
516a72ab MT |
167 | if not path: |
168 | path = "source-3.x" | |
169 | ||
170 | # At first, we assume that the requested object is a plain file: | |
818a4490 | 171 | try: |
516a72ab | 172 | object = FileObject(path=path, file=file) |
818a4490 | 173 | except NotFoundError: |
516a72ab MT |
174 | # Second, we assume that the requestet object is in the patch repo: |
175 | try: | |
176 | object = PatchObject(file=file) | |
177 | except NotFoundError: | |
178 | give_404() | |
179 | else: | |
180 | object() | |
818a4490 | 181 | else: |
516a72ab MT |
182 | object() |
183 | ||
184 | try: | |
185 | main() | |
186 | except SystemExit: | |
187 | pass |