10 | | diff -r -u mod_python-2.7.11.orig/lib/python/mod_python/util.py mod_python-2.7.11/lib/python/mod_python/util.py |
11 | | --- mod_python-2.7.11.orig/lib/python/mod_python/util.py 2000-12-13 23:45:48.000000000 +0000 |
12 | | +++ mod_python-2.7.11/lib/python/mod_python/util.py 2005-09-16 12:58:07.000000000 +0100 |
13 | | @@ -47,6 +47,9 @@ |
14 | | import string |
15 | | import StringIO |
16 | | |
17 | | +from types import * |
18 | | +from exceptions import * |
19 | | + |
20 | | parse_qs = apache.parse_qs |
21 | | parse_qsl = apache.parse_qsl |
22 | | |
23 | | @@ -95,6 +98,14 @@ |
24 | | def __del__(self): |
25 | | self.file.close() |
26 | | |
27 | | +class StringField(str): |
28 | | + """ This class is basically a string with |
29 | | + a value attribute for compatibility with std lib cgi.py |
30 | | + """ |
31 | | + |
32 | | + def __init__(self, str=""): |
33 | | + str.__init__(self, str) |
34 | | + self.value = self.__str__() |
35 | | |
36 | | class FieldStorage: |
37 | | |
38 | | @@ -239,10 +250,10 @@ |
39 | | found = [] |
40 | | for item in self.list: |
41 | | if item.name == key: |
42 | | - if isinstance(item.file, StringIO.StringIO): |
43 | | - found.append(item.value) |
44 | | - else: |
45 | | - found.append(item) |
46 | | + if isinstance(item.file, FileType): |
47 | | + found.append(item) |
48 | | + else: |
49 | | + found.append(StringField(item.value)) |
50 | | if not found: |
51 | | raise KeyError, key |
52 | | if len(found) == 1: |
53 | | @@ -250,6 +261,12 @@ |
54 | | else: |
55 | | return found |
56 | | |
57 | | + def get(self, key, default): |
58 | | + try: |
59 | | + return self.__getitem__(key) |
60 | | + except KeyError: |
61 | | + return default |
62 | | + |
63 | | def keys(self): |
64 | | """Dictionary style keys() method.""" |
65 | | if self.list is None: |
66 | | @@ -271,23 +288,121 @@ |
67 | | """Dictionary style len(x) support.""" |
68 | | return len(self.keys()) |
69 | | |
70 | | - |
71 | | + def getfirst(self, key, default=None): |
72 | | + """ return the first value received """ |
73 | | + for item in self.list: |
74 | | + if item.name == key: |
75 | | + if isinstance(item.file, FileType): |
76 | | + return item |
77 | | + else: |
78 | | + return StringField(item.value) |
79 | | + return default |
80 | | + |
81 | | + def getlist(self, key): |
82 | | + """ return a list of received values """ |
83 | | + if self.list is None: |
84 | | + raise TypeError, "not indexable" |
85 | | + found = [] |
86 | | + for item in self.list: |
87 | | + if item.name == key: |
88 | | + if isinstance(item.file, FileType): |
89 | | + found.append(item) |
90 | | + else: |
91 | | + found.append(StringField(item.value)) |
92 | | + return found |
93 | | + |
94 | | def parse_header(line): |
95 | | """Parse a Content-type like header. |
96 | | |
97 | | Return the main content-type and a dictionary of options. |
98 | | |
99 | | """ |
100 | | - plist = map(string.strip, string.splitfields(line, ';')) |
101 | | - key = string.lower(plist[0]) |
102 | | + |
103 | | + plist = map(lambda a: a.strip(), line.split(';')) |
104 | | + key = plist[0].lower() |
105 | | del plist[0] |
106 | | pdict = {} |
107 | | for p in plist: |
108 | | - i = string.find(p, '=') |
109 | | + i = p.find('=') |
110 | | if i >= 0: |
111 | | - name = string.lower(string.strip(p[:i])) |
112 | | - value = string.strip(p[i+1:]) |
113 | | + name = p[:i].strip().lower() |
114 | | + value = p[i+1:].strip() |
115 | | if len(value) >= 2 and value[0] == value[-1] == '"': |
116 | | value = value[1:-1] |
117 | | pdict[name] = value |
118 | | return key, pdict |
119 | | + |
120 | | +def apply_fs_data(object, fs, **args): |
121 | | + """ |
122 | | + Apply FieldStorage data to an object - the object must be |
123 | | + callable. Examine the args, and match then with fs data, |
124 | | + then call the object, return the result. |
125 | | + """ |
126 | | + |
127 | | + # add form data to args |
128 | | + for field in fs.list: |
129 | | + if field.filename: |
130 | | + val = field |
131 | | + else: |
132 | | + val = field.value |
133 | | + args.setdefault(field.name, []).append(val) |
134 | | + |
135 | | + # replace lists with single values |
136 | | + for arg in args: |
137 | | + if ((type(args[arg]) is ListType) and |
138 | | + (len(args[arg]) == 1)): |
139 | | + args[arg] = args[arg][0] |
140 | | + |
141 | | + # we need to weed out unexpected keyword arguments |
142 | | + # and for that we need to get a list of them. There |
143 | | + # are a few options for callable objects here: |
144 | | + |
145 | | + if type(object) is InstanceType: |
146 | | + # instances are callable when they have __call__() |
147 | | + object = object.__call__ |
148 | | + |
149 | | + expected = [] |
150 | | + if hasattr(object, "func_code"): |
151 | | + # function |
152 | | + fc = object.func_code |
153 | | + expected = fc.co_varnames[0:fc.co_argcount] |
154 | | + elif hasattr(object, 'im_func'): |
155 | | + # method |
156 | | + fc = object.im_func.func_code |
157 | | + expected = fc.co_varnames[1:fc.co_argcount] |
158 | | + elif type(object) is ClassType: |
159 | | + # class |
160 | | + fc = object.__init__.im_func.func_code |
161 | | + expected = fc.co_varnames[1:fc.co_argcount] |
162 | | + |
163 | | + # remove unexpected args unless co_flags & 0x08, |
164 | | + # meaning function accepts **kw syntax |
165 | | + if not (fc.co_flags & 0x08): |
166 | | + for name in args.keys(): |
167 | | + if name not in expected: |
168 | | + del args[name] |
169 | | + |
170 | | + return object(**args) |
171 | | + |
172 | | +def redirect(req, location, permanent=0, text=None): |
173 | | + """ |
174 | | + A convenience function to provide redirection |
175 | | + """ |
176 | | + |
177 | | + if req.sent_bodyct: |
178 | | + raise IOError, "Cannot redirect after headers have already been sent." |
179 | | + |
180 | | + req.err_headers_out["Location"] = location |
181 | | + if permanent: |
182 | | + req.status = apache.HTTP_MOVED_PERMANENTLY |
183 | | + else: |
184 | | + req.status = apache.HTTP_MOVED_TEMPORARILY |
185 | | + |
186 | | + if text is None: |
187 | | + req.write('<p>The document has moved' |
188 | | + ' <a href="%s">here</a></p>\n' |
189 | | + % location) |
190 | | + else: |
191 | | + req.write(text) |
192 | | + |
193 | | + raise apache.SERVER_RETURN, apache.OK |
194 | | diff -r -u mod_python-2.7.11.orig/src/include/mod_python.h mod_python-2.7.11/src/include/mod_python.h |
195 | | --- mod_python-2.7.11.orig/src/include/mod_python.h 2003-12-08 04:36:10.000000000 +0000 |
196 | | +++ mod_python-2.7.11/src/include/mod_python.h 2005-09-16 01:01:47.000000000 +0100 |
197 | | @@ -67,7 +67,7 @@ |
198 | | #include "http_protocol.h" |
199 | | #include "util_script.h" |
200 | | #include "http_log.h" |
201 | | - |
202 | | +#include "multithread.h" |
203 | | |
204 | | /* Python headers */ |
205 | | /* this gets rid of some comile warnings */ |
206 | | diff -r -u mod_python-2.7.11.orig/src/mod_python.c mod_python-2.7.11/src/mod_python.c |
207 | | --- mod_python-2.7.11.orig/src/mod_python.c 2001-05-28 21:00:41.000000000 +0100 |
208 | | +++ mod_python-2.7.11/src/mod_python.c 2005-09-16 01:38:05.000000000 +0100 |
209 | | @@ -264,6 +264,9 @@ |
210 | | server.register_cleanup() */ |
211 | | pool *child_init_pool = NULL; |
212 | | |
213 | | + /* Fudge for OS X */ |
214 | | + static int initialized = 0; |
215 | | + |
216 | | /* mod_python version */ |
217 | | ap_add_version_component(VERSION_COMPONENT); |
218 | | |
219 | | @@ -272,8 +275,9 @@ |
220 | | ap_add_version_component(buff); |
221 | | |
222 | | /* initialize global Python interpreter if necessary */ |
223 | | - if (! Py_IsInitialized()) |
224 | | + if (!initialized || !Py_IsInitialized()) |
225 | | { |
226 | | + initialized = 1; |
227 | | |
228 | | /* initialze the interpreter */ |
229 | | Py_Initialize(); |
230 | | diff -r -u mod_python-2.7.11.orig/src/requestobject.c mod_python-2.7.11/src/requestobject.c |
231 | | --- mod_python-2.7.11.orig/src/requestobject.c 2001-05-23 03:49:43.000000000 +0100 |
232 | | +++ mod_python-2.7.11/src/requestobject.c 2005-09-16 02:18:33.000000000 +0100 |
233 | | @@ -849,6 +849,7 @@ |
234 | | {"filename", T_STRING, OFF(filename), }, |
235 | | {"path_info", T_STRING, OFF(path_info), RO}, |
236 | | {"args", T_STRING, OFF(args), RO}, |
237 | | + {"user", T_STRING, }, |
238 | | /* XXX - test an array header */ |
239 | | /* XXX finfo */ |
240 | | /* XXX parsed_uri */ |
241 | | @@ -1015,6 +1016,15 @@ |
242 | | else if (strcmp(name, "hstack") == 0) { |
243 | | return PyString_FromString(self->hstack); |
244 | | } |
245 | | + else if (strcmp(name, "user") == 0) { |
246 | | + if (!self->request_rec->connection |
247 | | + || !self->request_rec->connection->user) { |
248 | | + Py_INCREF(Py_None); |
249 | | + return Py_None; |
250 | | + } |
251 | | + |
252 | | + return PyString_FromString(self->request_rec->connection->user); |
253 | | + } |
254 | | else if (strcmp(name, "_content_type_set") == 0) { |
255 | | return PyInt_FromLong(self->content_type_set); |
256 | | } |
257 | | @@ -1058,6 +1068,16 @@ |
258 | | ap_pstrdup(self->request_rec->pool, PyString_AsString(value)); |
259 | | return 0; |
260 | | } |
261 | | + else if (strcmp(name, "user") == 0) { |
262 | | + if (!self->request_rec->connection) { |
263 | | + PyErr_SetString(PyExc_AttributeError, "no connection"); |
264 | | + return -1; |
265 | | + } |
266 | | + |
267 | | + self->request_rec->connection->user = |
268 | | + ap_pstrdup(self->request_rec->pool, PyString_AsString(value)); |
269 | | + return 0; |
270 | | + } |
271 | | else if (strcmp(name, "hstack") == 0) { |
272 | | self->hstack = ap_pstrdup(self->request_rec->pool, PyString_AsString(value)); |
273 | | return 0; |
| 31 | CFLAGS=$(OPT) $(INCLUDES) |
| 32 | }}} |
| 33 | into: |
| 34 | {{{ |
| 35 | CFLAGS=$(OPT) $(INCLUDES) -DEAPI |