]> git.ipfire.org Git - ipfire.org.git/blame - source/dlhandler.py
Some parts of dlhandler.py were rewritten.
[ipfire.org.git] / source / dlhandler.py
CommitLineData
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
22import os
23import cgi
516a72ab
MT
24import sys
25import sha
26from pysqlite2 import dbapi2 as sqlite
27
28sys.path.append(".")
29
818a4490 30from git import *
31
6a170c4e
MT
32def give_403():
33 print "Status: 403 Forbidden"
34 print "Pragma: no-cache"
35 print "Cache-control: no-cache"
36 print "Connection: close"
37 print
38 print
516a72ab 39 sys.exit()
6a170c4e 40
818a4490 41def give_404():
42 print "Status: 404 Not found"
43 print "Pragma: no-cache"
44 print "Cache-control: no-cache"
45 print "Connection: close"
46 print
6a170c4e 47 print
516a72ab 48 sys.exit()
818a4490 49
50def 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 print
57 print
516a72ab 58 sys.exit()
818a4490 59
60class NotFoundError(Exception):
61 pass
62
63class 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
104class 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
124class 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
154def 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
184try:
185 main()
186except SystemExit:
187 pass