blob: 519d575ae17d21624bca6540a790a5b3633183cd [file] [log] [blame]
Just van Rossum52e14d62002-12-30 22:08:05 +00001#include "Python.h"
2#include "structmember.h"
3#include "osdefs.h"
4#include "marshal.h"
Just van Rossum52e14d62002-12-30 22:08:05 +00005#include <time.h>
6
7
8#define IS_SOURCE 0x0
9#define IS_BYTECODE 0x1
10#define IS_PACKAGE 0x2
11
12struct st_zip_searchorder {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 char suffix[14];
14 int type;
Just van Rossum52e14d62002-12-30 22:08:05 +000015};
16
17/* zip_searchorder defines how we search for a module in the Zip
18 archive: we first search for a package __init__, then for
19 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
20 are swapped by initzipimport() if we run in optimized mode. Also,
21 '/' is replaced by SEP there. */
Neal Norwitz29fd2ba2003-03-23 13:21:03 +000022static struct st_zip_searchorder zip_searchorder[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
24 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
25 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
26 {".pyc", IS_BYTECODE},
27 {".pyo", IS_BYTECODE},
28 {".py", IS_SOURCE},
29 {"", 0}
Just van Rossum52e14d62002-12-30 22:08:05 +000030};
31
32/* zipimporter object definition and support */
33
34typedef struct _zipimporter ZipImporter;
35
36struct _zipimporter {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 PyObject_HEAD
38 PyObject *archive; /* pathname of the Zip archive */
39 PyObject *prefix; /* file prefix: "a/sub/directory/" */
40 PyObject *files; /* dict with file info {path: toc_entry} */
Just van Rossum52e14d62002-12-30 22:08:05 +000041};
42
Just van Rossum52e14d62002-12-30 22:08:05 +000043static PyObject *ZipImportError;
44static PyObject *zip_directory_cache = NULL;
45
46/* forward decls */
47static PyObject *read_directory(char *archive);
48static PyObject *get_data(char *archive, PyObject *toc_entry);
49static PyObject *get_module_code(ZipImporter *self, char *fullname,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 int *p_ispackage, char **p_modpath);
Just van Rossum52e14d62002-12-30 22:08:05 +000051
52
53#define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
54
55
56/* zipimporter.__init__
57 Split the "subdirectory" from the Zip archive path, lookup a matching
58 entry in sys.path_importer_cache, fetch the file directory from there
59 if found, or else read it from the archive. */
60static int
61zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
62{
Victor Stinner2b8dab72010-08-14 14:54:10 +000063 PyObject *pathobj, *path_bytes, *files;
64 Py_UNICODE *path, *p, *prefix, buf[MAXPATHLEN+2];
65 Py_ssize_t len;
Just van Rossum52e14d62002-12-30 22:08:05 +000066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 if (!_PyArg_NoKeywords("zipimporter()", kwds))
68 return -1;
Georg Brandl02c42872005-08-26 06:42:30 +000069
Victor Stinner2b8dab72010-08-14 14:54:10 +000070 if (!PyArg_ParseTuple(args, "O&:zipimporter",
71 PyUnicode_FSDecoder, &pathobj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 return -1;
Just van Rossum52e14d62002-12-30 22:08:05 +000073
Victor Stinner2b8dab72010-08-14 14:54:10 +000074 /* copy path to buf */
75 len = PyUnicode_GET_SIZE(pathobj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 if (len == 0) {
77 PyErr_SetString(ZipImportError, "archive path is empty");
Victor Stinner2b8dab72010-08-14 14:54:10 +000078 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 }
80 if (len >= MAXPATHLEN) {
81 PyErr_SetString(ZipImportError,
82 "archive path too long");
Victor Stinner2b8dab72010-08-14 14:54:10 +000083 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 }
Victor Stinner2b8dab72010-08-14 14:54:10 +000085 Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(pathobj));
Just van Rossum52e14d62002-12-30 22:08:05 +000086
87#ifdef ALTSEP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 for (p = buf; *p; p++) {
89 if (*p == ALTSEP)
90 *p = SEP;
91 }
Just van Rossum52e14d62002-12-30 22:08:05 +000092#endif
93
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 path = NULL;
95 prefix = NULL;
96 for (;;) {
97 struct stat statbuf;
98 int rv;
Just van Rossum52e14d62002-12-30 22:08:05 +000099
Victor Stinner2b8dab72010-08-14 14:54:10 +0000100 if (pathobj == NULL) {
101 pathobj = PyUnicode_FromUnicode(buf, len);
102 if (pathobj == NULL)
103 goto error;
104 }
105 rv = _Py_stat(pathobj, &statbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 if (rv == 0) {
107 /* it exists */
108 if (S_ISREG(statbuf.st_mode))
109 /* it's a file */
110 path = buf;
111 break;
112 }
Victor Stinner2b8dab72010-08-14 14:54:10 +0000113 else if (PyErr_Occurred())
114 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 /* back up one path element */
Victor Stinner2b8dab72010-08-14 14:54:10 +0000116 p = Py_UNICODE_strrchr(buf, SEP);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000117 if (prefix != NULL)
118 *prefix = SEP;
119 if (p == NULL)
120 break;
121 *p = '\0';
Victor Stinner2b8dab72010-08-14 14:54:10 +0000122 len = p - buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 prefix = p;
Victor Stinner2b8dab72010-08-14 14:54:10 +0000124 Py_CLEAR(pathobj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000125 }
Victor Stinner2b8dab72010-08-14 14:54:10 +0000126 if (path == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 PyErr_SetString(ZipImportError, "not a Zip file");
Victor Stinner2b8dab72010-08-14 14:54:10 +0000128 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000130
Victor Stinner2b8dab72010-08-14 14:54:10 +0000131 files = PyDict_GetItem(zip_directory_cache, pathobj);
132 if (files == NULL) {
133 path_bytes = PyUnicode_EncodeFSDefault(pathobj);
134 if (path_bytes == NULL)
135 goto error;
136 files = read_directory(PyBytes_AS_STRING(path_bytes));
137 Py_DECREF(path_bytes);
138 if (files == NULL)
139 goto error;
140 if (PyDict_SetItem(zip_directory_cache, pathobj, files) != 0)
141 goto error;
142 }
143 else
144 Py_INCREF(files);
145 self->files = files;
146
147 self->archive = pathobj;
148 pathobj = NULL;
149
150 if (prefix != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 prefix++;
Victor Stinner2b8dab72010-08-14 14:54:10 +0000152 len = Py_UNICODE_strlen(prefix);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 if (prefix[len-1] != SEP) {
154 /* add trailing SEP */
155 prefix[len] = SEP;
156 prefix[len + 1] = '\0';
Victor Stinner2b8dab72010-08-14 14:54:10 +0000157 len++;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000158 }
159 }
Victor Stinner2b8dab72010-08-14 14:54:10 +0000160 else
161 len = 0;
162 self->prefix = PyUnicode_FromUnicode(prefix, len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 if (self->prefix == NULL)
Victor Stinner2b8dab72010-08-14 14:54:10 +0000164 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 return 0;
Victor Stinner2b8dab72010-08-14 14:54:10 +0000167
168error:
169 Py_XDECREF(pathobj);
170 return -1;
Just van Rossum52e14d62002-12-30 22:08:05 +0000171}
172
173/* GC support. */
174static int
175zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
176{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 ZipImporter *self = (ZipImporter *)obj;
178 Py_VISIT(self->files);
179 return 0;
Just van Rossum52e14d62002-12-30 22:08:05 +0000180}
181
182static void
183zipimporter_dealloc(ZipImporter *self)
184{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 PyObject_GC_UnTrack(self);
186 Py_XDECREF(self->archive);
187 Py_XDECREF(self->prefix);
188 Py_XDECREF(self->files);
189 Py_TYPE(self)->tp_free((PyObject *)self);
Just van Rossum52e14d62002-12-30 22:08:05 +0000190}
191
192static PyObject *
193zipimporter_repr(ZipImporter *self)
194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 char *archive = "???";
196 char *prefix = "";
Just van Rossum52e14d62002-12-30 22:08:05 +0000197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 if (self->archive != NULL && PyUnicode_Check(self->archive))
199 archive = _PyUnicode_AsString(self->archive);
200 if (self->prefix != NULL && PyUnicode_Check(self->prefix))
201 prefix = _PyUnicode_AsString(self->prefix);
202 if (prefix != NULL && *prefix)
203 return PyUnicode_FromFormat("<zipimporter object \"%.300s%c%.150s\">",
204 archive, SEP, prefix);
205 else
206 return PyUnicode_FromFormat("<zipimporter object \"%.300s\">",
207 archive);
Just van Rossum52e14d62002-12-30 22:08:05 +0000208}
209
210/* return fullname.split(".")[-1] */
211static char *
212get_subname(char *fullname)
213{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 char *subname = strrchr(fullname, '.');
215 if (subname == NULL)
216 subname = fullname;
217 else
218 subname++;
219 return subname;
Just van Rossum52e14d62002-12-30 22:08:05 +0000220}
221
222/* Given a (sub)modulename, write the potential file path in the
223 archive (without extension) to the path buffer. Return the
224 length of the resulting string. */
225static int
226make_filename(char *prefix, char *name, char *path)
227{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 size_t len;
229 char *p;
Just van Rossum52e14d62002-12-30 22:08:05 +0000230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000231 len = strlen(prefix);
Just van Rossum52e14d62002-12-30 22:08:05 +0000232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */
234 if (len + strlen(name) + 13 >= MAXPATHLEN) {
235 PyErr_SetString(ZipImportError, "path too long");
236 return -1;
237 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 strcpy(path, prefix);
240 strcpy(path + len, name);
241 for (p = path + len; *p; p++) {
242 if (*p == '.')
243 *p = SEP;
244 }
245 len += strlen(name);
246 assert(len < INT_MAX);
247 return (int)len;
Just van Rossum52e14d62002-12-30 22:08:05 +0000248}
249
Raymond Hettinger2c45c9a2004-11-10 13:08:35 +0000250enum zi_module_info {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 MI_ERROR,
252 MI_NOT_FOUND,
253 MI_MODULE,
254 MI_PACKAGE
Just van Rossum52e14d62002-12-30 22:08:05 +0000255};
256
257/* Return some information about a module. */
Raymond Hettinger2c45c9a2004-11-10 13:08:35 +0000258static enum zi_module_info
Just van Rossum52e14d62002-12-30 22:08:05 +0000259get_module_info(ZipImporter *self, char *fullname)
260{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261 char *subname, path[MAXPATHLEN + 1];
262 int len;
263 struct st_zip_searchorder *zso;
Just van Rossum52e14d62002-12-30 22:08:05 +0000264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +0000266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 len = make_filename(_PyUnicode_AsString(self->prefix), subname, path);
268 if (len < 0)
269 return MI_ERROR;
Just van Rossum52e14d62002-12-30 22:08:05 +0000270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000271 for (zso = zip_searchorder; *zso->suffix; zso++) {
272 strcpy(path + len, zso->suffix);
273 if (PyDict_GetItemString(self->files, path) != NULL) {
274 if (zso->type & IS_PACKAGE)
275 return MI_PACKAGE;
276 else
277 return MI_MODULE;
278 }
279 }
280 return MI_NOT_FOUND;
Just van Rossum52e14d62002-12-30 22:08:05 +0000281}
282
283/* Check whether we can satisfy the import of the module named by
284 'fullname'. Return self if we can, None if we can't. */
285static PyObject *
286zipimporter_find_module(PyObject *obj, PyObject *args)
287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 ZipImporter *self = (ZipImporter *)obj;
289 PyObject *path = NULL;
290 char *fullname;
291 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module",
294 &fullname, &path))
295 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 mi = get_module_info(self, fullname);
298 if (mi == MI_ERROR)
299 return NULL;
300 if (mi == MI_NOT_FOUND) {
301 Py_INCREF(Py_None);
302 return Py_None;
303 }
304 Py_INCREF(self);
305 return (PyObject *)self;
Just van Rossum52e14d62002-12-30 22:08:05 +0000306}
307
308/* Load and return the module named by 'fullname'. */
309static PyObject *
310zipimporter_load_module(PyObject *obj, PyObject *args)
311{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312 ZipImporter *self = (ZipImporter *)obj;
313 PyObject *code, *mod, *dict;
314 char *fullname, *modpath;
315 int ispackage;
Just van Rossum52e14d62002-12-30 22:08:05 +0000316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 if (!PyArg_ParseTuple(args, "s:zipimporter.load_module",
318 &fullname))
319 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 code = get_module_code(self, fullname, &ispackage, &modpath);
322 if (code == NULL)
323 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 mod = PyImport_AddModule(fullname);
326 if (mod == NULL) {
327 Py_DECREF(code);
328 return NULL;
329 }
330 dict = PyModule_GetDict(mod);
Just van Rossum52e14d62002-12-30 22:08:05 +0000331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 /* mod.__loader__ = self */
333 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
334 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 if (ispackage) {
337 /* add __path__ to the module *before* the code gets
338 executed */
339 PyObject *pkgpath, *fullpath;
340 char *subname = get_subname(fullname);
341 int err;
Just van Rossum52e14d62002-12-30 22:08:05 +0000342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 fullpath = PyUnicode_FromFormat("%U%c%U%s",
344 self->archive, SEP,
345 self->prefix, subname);
346 if (fullpath == NULL)
347 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 pkgpath = Py_BuildValue("[O]", fullpath);
350 Py_DECREF(fullpath);
351 if (pkgpath == NULL)
352 goto error;
353 err = PyDict_SetItemString(dict, "__path__", pkgpath);
354 Py_DECREF(pkgpath);
355 if (err != 0)
356 goto error;
357 }
358 mod = PyImport_ExecCodeModuleEx(fullname, code, modpath);
359 Py_DECREF(code);
360 if (Py_VerboseFlag)
361 PySys_WriteStderr("import %s # loaded from Zip %s\n",
362 fullname, modpath);
363 return mod;
Just van Rossum52e14d62002-12-30 22:08:05 +0000364error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000365 Py_DECREF(code);
366 Py_DECREF(mod);
367 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000368}
369
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000370/* Return a string matching __file__ for the named module */
371static PyObject *
372zipimporter_get_filename(PyObject *obj, PyObject *args)
373{
374 ZipImporter *self = (ZipImporter *)obj;
375 PyObject *code;
376 char *fullname, *modpath;
377 int ispackage;
378
Nick Coghlan9a1d6e32009-02-08 03:37:27 +0000379 if (!PyArg_ParseTuple(args, "s:zipimporter.get_filename",
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000380 &fullname))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 return NULL;
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000382
383 /* Deciding the filename requires working out where the code
384 would come from if the module was actually loaded */
385 code = get_module_code(self, fullname, &ispackage, &modpath);
386 if (code == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 return NULL;
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000388 Py_DECREF(code); /* Only need the path info */
389
390 return PyUnicode_FromString(modpath);
391}
392
Just van Rossum52e14d62002-12-30 22:08:05 +0000393/* Return a bool signifying whether the module is a package or not. */
394static PyObject *
395zipimporter_is_package(PyObject *obj, PyObject *args)
396{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 ZipImporter *self = (ZipImporter *)obj;
398 char *fullname;
399 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 if (!PyArg_ParseTuple(args, "s:zipimporter.is_package",
402 &fullname))
403 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 mi = get_module_info(self, fullname);
406 if (mi == MI_ERROR)
407 return NULL;
408 if (mi == MI_NOT_FOUND) {
409 PyErr_Format(ZipImportError, "can't find module '%.200s'",
410 fullname);
411 return NULL;
412 }
413 return PyBool_FromLong(mi == MI_PACKAGE);
Just van Rossum52e14d62002-12-30 22:08:05 +0000414}
415
416static PyObject *
417zipimporter_get_data(PyObject *obj, PyObject *args)
418{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 ZipImporter *self = (ZipImporter *)obj;
420 char *path;
Just van Rossum52e14d62002-12-30 22:08:05 +0000421#ifdef ALTSEP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 char *p, buf[MAXPATHLEN + 1];
Just van Rossum52e14d62002-12-30 22:08:05 +0000423#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 PyObject *toc_entry;
425 Py_ssize_t len;
426 char *archive_str;
Just van Rossum52e14d62002-12-30 22:08:05 +0000427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000428 if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path))
429 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000430
431#ifdef ALTSEP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 if (strlen(path) >= MAXPATHLEN) {
433 PyErr_SetString(ZipImportError, "path too long");
434 return NULL;
435 }
436 strcpy(buf, path);
437 for (p = buf; *p; p++) {
438 if (*p == ALTSEP)
439 *p = SEP;
440 }
441 path = buf;
Just van Rossum52e14d62002-12-30 22:08:05 +0000442#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 archive_str = _PyUnicode_AsStringAndSize(self->archive, &len);
444 if ((size_t)len < strlen(path) &&
445 strncmp(path, archive_str, len) == 0 &&
446 path[len] == SEP) {
447 path = path + len + 1;
448 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 toc_entry = PyDict_GetItemString(self->files, path);
451 if (toc_entry == NULL) {
452 PyErr_SetFromErrnoWithFilename(PyExc_IOError, path);
453 return NULL;
454 }
455 return get_data(archive_str, toc_entry);
Just van Rossum52e14d62002-12-30 22:08:05 +0000456}
457
458static PyObject *
459zipimporter_get_code(PyObject *obj, PyObject *args)
460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 ZipImporter *self = (ZipImporter *)obj;
462 char *fullname;
Just van Rossum52e14d62002-12-30 22:08:05 +0000463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname))
465 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000467 return get_module_code(self, fullname, NULL, NULL);
Just van Rossum52e14d62002-12-30 22:08:05 +0000468}
469
470static PyObject *
471zipimporter_get_source(PyObject *obj, PyObject *args)
472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 ZipImporter *self = (ZipImporter *)obj;
474 PyObject *toc_entry;
475 char *fullname, *subname, path[MAXPATHLEN+1];
476 int len;
477 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname))
480 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 mi = get_module_info(self, fullname);
483 if (mi == MI_ERROR)
484 return NULL;
485 if (mi == MI_NOT_FOUND) {
486 PyErr_Format(ZipImportError, "can't find module '%.200s'",
487 fullname);
488 return NULL;
489 }
490 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +0000491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 len = make_filename(_PyUnicode_AsString(self->prefix), subname, path);
493 if (len < 0)
494 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 if (mi == MI_PACKAGE) {
497 path[len] = SEP;
498 strcpy(path + len + 1, "__init__.py");
499 }
500 else
501 strcpy(path + len, ".py");
Just van Rossum52e14d62002-12-30 22:08:05 +0000502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 toc_entry = PyDict_GetItemString(self->files, path);
504 if (toc_entry != NULL) {
505 PyObject *bytes = get_data(_PyUnicode_AsString(self->archive), toc_entry);
506 PyObject *res = PyUnicode_FromString(PyBytes_AsString(bytes));
507 Py_XDECREF(bytes);
508 return res;
509 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 /* we have the module, but no source */
512 Py_INCREF(Py_None);
513 return Py_None;
Just van Rossum52e14d62002-12-30 22:08:05 +0000514}
515
516PyDoc_STRVAR(doc_find_module,
517"find_module(fullname, path=None) -> self or None.\n\
518\n\
519Search for a module specified by 'fullname'. 'fullname' must be the\n\
520fully qualified (dotted) module name. It returns the zipimporter\n\
521instance itself if the module was found, or None if it wasn't.\n\
522The optional 'path' argument is ignored -- it's there for compatibility\n\
523with the importer protocol.");
524
525PyDoc_STRVAR(doc_load_module,
526"load_module(fullname) -> module.\n\
527\n\
528Load the module specified by 'fullname'. 'fullname' must be the\n\
529fully qualified (dotted) module name. It returns the imported\n\
530module, or raises ZipImportError if it wasn't found.");
531
532PyDoc_STRVAR(doc_get_data,
533"get_data(pathname) -> string with file data.\n\
534\n\
535Return the data associated with 'pathname'. Raise IOError if\n\
536the file wasn't found.");
537
538PyDoc_STRVAR(doc_is_package,
539"is_package(fullname) -> bool.\n\
540\n\
541Return True if the module specified by fullname is a package.\n\
Brian Curtin32839732010-07-21 01:44:19 +0000542Raise ZipImportError if the module couldn't be found.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000543
544PyDoc_STRVAR(doc_get_code,
545"get_code(fullname) -> code object.\n\
546\n\
547Return the code object for the specified module. Raise ZipImportError\n\
Brian Curtin32839732010-07-21 01:44:19 +0000548if the module couldn't be found.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000549
550PyDoc_STRVAR(doc_get_source,
551"get_source(fullname) -> source string.\n\
552\n\
553Return the source code for the specified module. Raise ZipImportError\n\
Brian Curtin32839732010-07-21 01:44:19 +0000554if the module couldn't be found, return None if the archive does\n\
Just van Rossum52e14d62002-12-30 22:08:05 +0000555contain the module, but has no source for it.");
556
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000557
558PyDoc_STRVAR(doc_get_filename,
Nick Coghlan9a1d6e32009-02-08 03:37:27 +0000559"get_filename(fullname) -> filename string.\n\
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000560\n\
561Return the filename for the specified module.");
562
Just van Rossum52e14d62002-12-30 22:08:05 +0000563static PyMethodDef zipimporter_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 {"find_module", zipimporter_find_module, METH_VARARGS,
565 doc_find_module},
566 {"load_module", zipimporter_load_module, METH_VARARGS,
567 doc_load_module},
568 {"get_data", zipimporter_get_data, METH_VARARGS,
569 doc_get_data},
570 {"get_code", zipimporter_get_code, METH_VARARGS,
571 doc_get_code},
572 {"get_source", zipimporter_get_source, METH_VARARGS,
573 doc_get_source},
574 {"get_filename", zipimporter_get_filename, METH_VARARGS,
575 doc_get_filename},
576 {"is_package", zipimporter_is_package, METH_VARARGS,
577 doc_is_package},
578 {NULL, NULL} /* sentinel */
Just van Rossum52e14d62002-12-30 22:08:05 +0000579};
580
581static PyMemberDef zipimporter_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},
583 {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},
584 {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},
585 {NULL}
Just van Rossum52e14d62002-12-30 22:08:05 +0000586};
587
588PyDoc_STRVAR(zipimporter_doc,
589"zipimporter(archivepath) -> zipimporter object\n\
590\n\
591Create a new zipimporter instance. 'archivepath' must be a path to\n\
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000592a zipfile, or to a specific path inside a zipfile. For example, it can be\n\
593'/tmp/myimport.zip', or '/tmp/myimport.zip/mydirectory', if mydirectory is a\n\
594valid directory inside the archive.\n\
595\n\
596'ZipImportError is raised if 'archivepath' doesn't point to a valid Zip\n\
597archive.\n\
598\n\
599The 'archive' attribute of zipimporter objects contains the name of the\n\
600zipfile targeted.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000601
602#define DEFERRED_ADDRESS(ADDR) 0
603
604static PyTypeObject ZipImporter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
606 "zipimport.zipimporter",
607 sizeof(ZipImporter),
608 0, /* tp_itemsize */
609 (destructor)zipimporter_dealloc, /* tp_dealloc */
610 0, /* tp_print */
611 0, /* tp_getattr */
612 0, /* tp_setattr */
613 0, /* tp_reserved */
614 (reprfunc)zipimporter_repr, /* tp_repr */
615 0, /* tp_as_number */
616 0, /* tp_as_sequence */
617 0, /* tp_as_mapping */
618 0, /* tp_hash */
619 0, /* tp_call */
620 0, /* tp_str */
621 PyObject_GenericGetAttr, /* tp_getattro */
622 0, /* tp_setattro */
623 0, /* tp_as_buffer */
624 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
625 Py_TPFLAGS_HAVE_GC, /* tp_flags */
626 zipimporter_doc, /* tp_doc */
627 zipimporter_traverse, /* tp_traverse */
628 0, /* tp_clear */
629 0, /* tp_richcompare */
630 0, /* tp_weaklistoffset */
631 0, /* tp_iter */
632 0, /* tp_iternext */
633 zipimporter_methods, /* tp_methods */
634 zipimporter_members, /* tp_members */
635 0, /* tp_getset */
636 0, /* tp_base */
637 0, /* tp_dict */
638 0, /* tp_descr_get */
639 0, /* tp_descr_set */
640 0, /* tp_dictoffset */
641 (initproc)zipimporter_init, /* tp_init */
642 PyType_GenericAlloc, /* tp_alloc */
643 PyType_GenericNew, /* tp_new */
644 PyObject_GC_Del, /* tp_free */
Just van Rossum52e14d62002-12-30 22:08:05 +0000645};
646
647
648/* implementation */
649
Just van Rossum52e14d62002-12-30 22:08:05 +0000650/* Given a buffer, return the long that is represented by the first
651 4 bytes, encoded as little endian. This partially reimplements
652 marshal.c:r_long() */
653static long
654get_long(unsigned char *buf) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 long x;
656 x = buf[0];
657 x |= (long)buf[1] << 8;
658 x |= (long)buf[2] << 16;
659 x |= (long)buf[3] << 24;
Just van Rossum52e14d62002-12-30 22:08:05 +0000660#if SIZEOF_LONG > 4
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 /* Sign extension for 64-bit machines */
662 x |= -(x & 0x80000000L);
Just van Rossum52e14d62002-12-30 22:08:05 +0000663#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 return x;
Just van Rossum52e14d62002-12-30 22:08:05 +0000665}
666
667/*
668 read_directory(archive) -> files dict (new reference)
669
670 Given a path to a Zip archive, build a dict, mapping file names
671 (local to the archive, using SEP as a separator) to toc entries.
672
673 A toc_entry is a tuple:
674
Fred Drakef5b7fd22005-11-11 19:34:56 +0000675 (__file__, # value to use for __file__, available for all files
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 compress, # compression kind; 0 for uncompressed
677 data_size, # size of compressed data on disk
678 file_size, # size of decompressed data
679 file_offset, # offset of file header from start of archive
680 time, # mod time of file (in dos format)
681 date, # mod data of file (in dos format)
682 crc, # crc checksum of the data
Just van Rossum52e14d62002-12-30 22:08:05 +0000683 )
684
685 Directories can be recognized by the trailing SEP in the name,
686 data_size and file_offset are 0.
687*/
688static PyObject *
689read_directory(char *archive)
690{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 PyObject *files = NULL;
692 FILE *fp;
693 long compress, crc, data_size, file_size, file_offset, date, time;
694 long header_offset, name_size, header_size, header_position;
695 long i, l, count;
696 size_t length;
697 char path[MAXPATHLEN + 5];
698 char name[MAXPATHLEN + 5];
699 char *p, endof_central_dir[22];
700 long arc_offset; /* offset from beginning of file to start of zip-archive */
Just van Rossum52e14d62002-12-30 22:08:05 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 if (strlen(archive) > MAXPATHLEN) {
703 PyErr_SetString(PyExc_OverflowError,
704 "Zip path name is too long");
705 return NULL;
706 }
707 strcpy(path, archive);
Just van Rossum52e14d62002-12-30 22:08:05 +0000708
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 fp = fopen(archive, "rb");
710 if (fp == NULL) {
711 PyErr_Format(ZipImportError, "can't open Zip file: "
712 "'%.200s'", archive);
713 return NULL;
714 }
715 fseek(fp, -22, SEEK_END);
716 header_position = ftell(fp);
717 if (fread(endof_central_dir, 1, 22, fp) != 22) {
718 fclose(fp);
719 PyErr_Format(ZipImportError, "can't read Zip file: "
720 "'%.200s'", archive);
721 return NULL;
722 }
723 if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
724 /* Bad: End of Central Dir signature */
725 fclose(fp);
726 PyErr_Format(ZipImportError, "not a Zip file: "
727 "'%.200s'", archive);
728 return NULL;
729 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 header_size = get_long((unsigned char *)endof_central_dir + 12);
732 header_offset = get_long((unsigned char *)endof_central_dir + 16);
733 arc_offset = header_position - header_offset - header_size;
734 header_offset += arc_offset;
Just van Rossum52e14d62002-12-30 22:08:05 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 files = PyDict_New();
737 if (files == NULL)
738 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 length = (long)strlen(path);
741 path[length] = SEP;
Just van Rossum52e14d62002-12-30 22:08:05 +0000742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 /* Start of Central Directory */
744 count = 0;
745 for (;;) {
746 PyObject *t;
747 int err;
Just van Rossum52e14d62002-12-30 22:08:05 +0000748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 fseek(fp, header_offset, 0); /* Start of file header */
750 l = PyMarshal_ReadLongFromFile(fp);
751 if (l != 0x02014B50)
752 break; /* Bad: Central Dir File Header */
753 fseek(fp, header_offset + 10, 0);
754 compress = PyMarshal_ReadShortFromFile(fp);
755 time = PyMarshal_ReadShortFromFile(fp);
756 date = PyMarshal_ReadShortFromFile(fp);
757 crc = PyMarshal_ReadLongFromFile(fp);
758 data_size = PyMarshal_ReadLongFromFile(fp);
759 file_size = PyMarshal_ReadLongFromFile(fp);
760 name_size = PyMarshal_ReadShortFromFile(fp);
761 header_size = 46 + name_size +
762 PyMarshal_ReadShortFromFile(fp) +
763 PyMarshal_ReadShortFromFile(fp);
764 fseek(fp, header_offset + 42, 0);
765 file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
766 if (name_size > MAXPATHLEN)
767 name_size = MAXPATHLEN;
Just van Rossum52e14d62002-12-30 22:08:05 +0000768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 p = name;
770 for (i = 0; i < name_size; i++) {
771 *p = (char)getc(fp);
772 if (*p == '/')
773 *p = SEP;
774 p++;
775 }
776 *p = 0; /* Add terminating null byte */
777 header_offset += header_size;
Just van Rossum52e14d62002-12-30 22:08:05 +0000778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 strncpy(path + length + 1, name, MAXPATHLEN - length - 1);
Just van Rossum52e14d62002-12-30 22:08:05 +0000780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 t = Py_BuildValue("siiiiiii", path, compress, data_size,
782 file_size, file_offset, time, date, crc);
783 if (t == NULL)
784 goto error;
785 err = PyDict_SetItemString(files, name, t);
786 Py_DECREF(t);
787 if (err != 0)
788 goto error;
789 count++;
790 }
791 fclose(fp);
792 if (Py_VerboseFlag)
793 PySys_WriteStderr("# zipimport: found %ld names in %s\n",
794 count, archive);
795 return files;
Just van Rossum52e14d62002-12-30 22:08:05 +0000796error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 fclose(fp);
798 Py_XDECREF(files);
799 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000800}
801
802/* Return the zlib.decompress function object, or NULL if zlib couldn't
803 be imported. The function is cached when found, so subsequent calls
804 don't import zlib again. Returns a *borrowed* reference.
805 XXX This makes zlib.decompress immortal. */
806static PyObject *
807get_decompress_func(void)
808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 static PyObject *decompress = NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 if (decompress == NULL) {
812 PyObject *zlib;
813 static int importing_zlib = 0;
Just van Rossum52e14d62002-12-30 22:08:05 +0000814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 if (importing_zlib != 0)
816 /* Someone has a zlib.py[co] in their Zip file;
817 let's avoid a stack overflow. */
818 return NULL;
819 importing_zlib = 1;
820 zlib = PyImport_ImportModuleNoBlock("zlib");
821 importing_zlib = 0;
822 if (zlib != NULL) {
823 decompress = PyObject_GetAttrString(zlib,
824 "decompress");
825 Py_DECREF(zlib);
826 }
827 else
828 PyErr_Clear();
829 if (Py_VerboseFlag)
830 PySys_WriteStderr("# zipimport: zlib %s\n",
831 zlib != NULL ? "available": "UNAVAILABLE");
832 }
833 return decompress;
Just van Rossum52e14d62002-12-30 22:08:05 +0000834}
835
836/* Given a path to a Zip file and a toc_entry, return the (uncompressed)
837 data as a new reference. */
838static PyObject *
839get_data(char *archive, PyObject *toc_entry)
840{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 PyObject *raw_data, *data = NULL, *decompress;
842 char *buf;
843 FILE *fp;
844 int err;
845 Py_ssize_t bytes_read = 0;
846 long l;
847 char *datapath;
848 long compress, data_size, file_size, file_offset, bytes_size;
849 long time, date, crc;
Just van Rossum52e14d62002-12-30 22:08:05 +0000850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,
852 &data_size, &file_size, &file_offset, &time,
853 &date, &crc)) {
854 return NULL;
855 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000857 fp = fopen(archive, "rb");
858 if (!fp) {
859 PyErr_Format(PyExc_IOError,
860 "zipimport: can not open file %s", archive);
861 return NULL;
862 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 /* Check to make sure the local file header is correct */
865 fseek(fp, file_offset, 0);
866 l = PyMarshal_ReadLongFromFile(fp);
867 if (l != 0x04034B50) {
868 /* Bad: Local File Header */
869 PyErr_Format(ZipImportError,
870 "bad local file header in %s",
871 archive);
872 fclose(fp);
873 return NULL;
874 }
875 fseek(fp, file_offset + 26, 0);
876 l = 30 + PyMarshal_ReadShortFromFile(fp) +
877 PyMarshal_ReadShortFromFile(fp); /* local header size */
878 file_offset += l; /* Start of file data */
Just van Rossum52e14d62002-12-30 22:08:05 +0000879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 bytes_size = compress == 0 ? data_size : data_size + 1;
881 if (bytes_size == 0)
882 bytes_size++;
883 raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);
Just van Rossum52e14d62002-12-30 22:08:05 +0000884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 if (raw_data == NULL) {
886 fclose(fp);
887 return NULL;
888 }
889 buf = PyBytes_AsString(raw_data);
Just van Rossum52e14d62002-12-30 22:08:05 +0000890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000891 err = fseek(fp, file_offset, 0);
892 if (err == 0)
893 bytes_read = fread(buf, 1, data_size, fp);
894 fclose(fp);
895 if (err || bytes_read != data_size) {
896 PyErr_SetString(PyExc_IOError,
897 "zipimport: can't read data");
898 Py_DECREF(raw_data);
899 return NULL;
900 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000901
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000902 if (compress != 0) {
903 buf[data_size] = 'Z'; /* saw this in zipfile.py */
904 data_size++;
905 }
906 buf[data_size] = '\0';
Just van Rossum52e14d62002-12-30 22:08:05 +0000907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 if (compress == 0) { /* data is not compressed */
909 data = PyBytes_FromStringAndSize(buf, data_size);
910 Py_DECREF(raw_data);
911 return data;
912 }
913
914 /* Decompress with zlib */
915 decompress = get_decompress_func();
916 if (decompress == NULL) {
917 PyErr_SetString(ZipImportError,
918 "can't decompress data; "
919 "zlib not available");
920 goto error;
921 }
922 data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
Just van Rossum52e14d62002-12-30 22:08:05 +0000923error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000924 Py_DECREF(raw_data);
925 return data;
Just van Rossum52e14d62002-12-30 22:08:05 +0000926}
927
928/* Lenient date/time comparison function. The precision of the mtime
929 in the archive is lower than the mtime stored in a .pyc: we
930 must allow a difference of at most one second. */
931static int
932eq_mtime(time_t t1, time_t t2)
933{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000934 time_t d = t1 - t2;
935 if (d < 0)
936 d = -d;
937 /* dostime only stores even seconds, so be lenient */
938 return d <= 1;
Just van Rossum52e14d62002-12-30 22:08:05 +0000939}
940
941/* Given the contents of a .py[co] file in a buffer, unmarshal the data
942 and return the code object. Return None if it the magic word doesn't
943 match (we do this instead of raising an exception as we fall back
944 to .py if available and we don't want to mask other errors).
945 Returns a new reference. */
946static PyObject *
947unmarshal_code(char *pathname, PyObject *data, time_t mtime)
948{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 PyObject *code;
950 char *buf = PyBytes_AsString(data);
951 Py_ssize_t size = PyBytes_Size(data);
Just van Rossum52e14d62002-12-30 22:08:05 +0000952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000953 if (size <= 9) {
954 PyErr_SetString(ZipImportError,
955 "bad pyc data");
956 return NULL;
957 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000959 if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
960 if (Py_VerboseFlag)
961 PySys_WriteStderr("# %s has bad magic\n",
962 pathname);
963 Py_INCREF(Py_None);
964 return Py_None; /* signal caller to try alternative */
965 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000967 if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
968 mtime)) {
969 if (Py_VerboseFlag)
970 PySys_WriteStderr("# %s has bad mtime\n",
971 pathname);
972 Py_INCREF(Py_None);
973 return Py_None; /* signal caller to try alternative */
974 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
977 if (code == NULL)
978 return NULL;
979 if (!PyCode_Check(code)) {
980 Py_DECREF(code);
981 PyErr_Format(PyExc_TypeError,
982 "compiled module %.200s is not a code object",
983 pathname);
984 return NULL;
985 }
986 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +0000987}
988
989/* Replace any occurances of "\r\n?" in the input string with "\n".
990 This converts DOS and Mac line endings to Unix line endings.
991 Also append a trailing "\n" to be compatible with
992 PyParser_SimpleParseFile(). Returns a new reference. */
993static PyObject *
994normalize_line_endings(PyObject *source)
995{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 char *buf, *q, *p = PyBytes_AsString(source);
997 PyObject *fixed_source;
998 int len = 0;
Just van Rossum52e14d62002-12-30 22:08:05 +0000999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 if (!p) {
1001 return PyBytes_FromStringAndSize("\n\0", 2);
1002 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 /* one char extra for trailing \n and one for terminating \0 */
1005 buf = (char *)PyMem_Malloc(PyBytes_Size(source) + 2);
1006 if (buf == NULL) {
1007 PyErr_SetString(PyExc_MemoryError,
1008 "zipimport: no memory to allocate "
1009 "source buffer");
1010 return NULL;
1011 }
1012 /* replace "\r\n?" by "\n" */
1013 for (q = buf; *p != '\0'; p++) {
1014 if (*p == '\r') {
1015 *q++ = '\n';
1016 if (*(p + 1) == '\n')
1017 p++;
1018 }
1019 else
1020 *q++ = *p;
1021 len++;
1022 }
1023 *q++ = '\n'; /* add trailing \n */
1024 *q = '\0';
1025 fixed_source = PyBytes_FromStringAndSize(buf, len + 2);
1026 PyMem_Free(buf);
1027 return fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001028}
1029
1030/* Given a string buffer containing Python source code, compile it
1031 return and return a code object as a new reference. */
1032static PyObject *
1033compile_source(char *pathname, PyObject *source)
1034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 PyObject *code, *fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 fixed_source = normalize_line_endings(source);
1038 if (fixed_source == NULL)
1039 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001041 code = Py_CompileString(PyBytes_AsString(fixed_source), pathname,
1042 Py_file_input);
1043 Py_DECREF(fixed_source);
1044 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001045}
1046
1047/* Convert the date/time values found in the Zip archive to a value
1048 that's compatible with the time stamp stored in .pyc files. */
Neal Norwitz29fd2ba2003-03-23 13:21:03 +00001049static time_t
1050parse_dostime(int dostime, int dosdate)
Just van Rossum52e14d62002-12-30 22:08:05 +00001051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 struct tm stm;
Just van Rossum52e14d62002-12-30 22:08:05 +00001053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 memset((void *) &stm, '\0', sizeof(stm));
Christian Heimes679db4a2008-01-18 09:56:22 +00001055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 stm.tm_sec = (dostime & 0x1f) * 2;
1057 stm.tm_min = (dostime >> 5) & 0x3f;
1058 stm.tm_hour = (dostime >> 11) & 0x1f;
1059 stm.tm_mday = dosdate & 0x1f;
1060 stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1061 stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1062 stm.tm_isdst = -1; /* wday/yday is ignored */
Just van Rossum52e14d62002-12-30 22:08:05 +00001063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 return mktime(&stm);
Just van Rossum52e14d62002-12-30 22:08:05 +00001065}
1066
1067/* Given a path to a .pyc or .pyo file in the archive, return the
1068 modifictaion time of the matching .py file, or 0 if no source
1069 is available. */
1070static time_t
1071get_mtime_of_source(ZipImporter *self, char *path)
1072{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 PyObject *toc_entry;
1074 time_t mtime = 0;
1075 Py_ssize_t lastchar = strlen(path) - 1;
1076 char savechar = path[lastchar];
1077 path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */
1078 toc_entry = PyDict_GetItemString(self->files, path);
1079 if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1080 PyTuple_Size(toc_entry) == 8) {
1081 /* fetch the time stamp of the .py file for comparison
1082 with an embedded pyc time stamp */
1083 int time, date;
1084 time = PyLong_AsLong(PyTuple_GetItem(toc_entry, 5));
1085 date = PyLong_AsLong(PyTuple_GetItem(toc_entry, 6));
1086 mtime = parse_dostime(time, date);
1087 }
1088 path[lastchar] = savechar;
1089 return mtime;
Just van Rossum52e14d62002-12-30 22:08:05 +00001090}
1091
1092/* Return the code object for the module named by 'fullname' from the
1093 Zip archive as a new reference. */
1094static PyObject *
1095get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 time_t mtime, PyObject *toc_entry)
Just van Rossum52e14d62002-12-30 22:08:05 +00001097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 PyObject *data, *code;
1099 char *modpath;
1100 char *archive = _PyUnicode_AsString(self->archive);
Just van Rossum52e14d62002-12-30 22:08:05 +00001101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 if (archive == NULL)
1103 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 data = get_data(archive, toc_entry);
1106 if (data == NULL)
1107 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 modpath = _PyUnicode_AsString(PyTuple_GetItem(toc_entry, 0));
Just van Rossum52e14d62002-12-30 22:08:05 +00001110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001111 if (isbytecode) {
1112 code = unmarshal_code(modpath, data, mtime);
1113 }
1114 else {
1115 code = compile_source(modpath, data);
1116 }
1117 Py_DECREF(data);
1118 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001119}
1120
1121/* Get the code object assoiciated with the module specified by
1122 'fullname'. */
1123static PyObject *
1124get_module_code(ZipImporter *self, char *fullname,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001125 int *p_ispackage, char **p_modpath)
Just van Rossum52e14d62002-12-30 22:08:05 +00001126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 PyObject *toc_entry;
1128 char *subname, path[MAXPATHLEN + 1];
1129 int len;
1130 struct st_zip_searchorder *zso;
Just van Rossum52e14d62002-12-30 22:08:05 +00001131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +00001133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 len = make_filename(_PyUnicode_AsString(self->prefix), subname, path);
1135 if (len < 0)
1136 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 for (zso = zip_searchorder; *zso->suffix; zso++) {
1139 PyObject *code = NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 strcpy(path + len, zso->suffix);
1142 if (Py_VerboseFlag > 1)
1143 PySys_WriteStderr("# trying %s%c%s\n",
1144 _PyUnicode_AsString(self->archive),
1145 (int)SEP, path);
1146 toc_entry = PyDict_GetItemString(self->files, path);
1147 if (toc_entry != NULL) {
1148 time_t mtime = 0;
1149 int ispackage = zso->type & IS_PACKAGE;
1150 int isbytecode = zso->type & IS_BYTECODE;
Just van Rossum52e14d62002-12-30 22:08:05 +00001151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 if (isbytecode)
1153 mtime = get_mtime_of_source(self, path);
1154 if (p_ispackage != NULL)
1155 *p_ispackage = ispackage;
1156 code = get_code_from_data(self, ispackage,
1157 isbytecode, mtime,
1158 toc_entry);
1159 if (code == Py_None) {
1160 /* bad magic number or non-matching mtime
1161 in byte code, try next */
1162 Py_DECREF(code);
1163 continue;
1164 }
1165 if (code != NULL && p_modpath != NULL)
1166 *p_modpath = _PyUnicode_AsString(
1167 PyTuple_GetItem(toc_entry, 0));
1168 return code;
1169 }
1170 }
1171 PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);
1172 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001173}
1174
1175
1176/* Module init */
1177
1178PyDoc_STRVAR(zipimport_doc,
1179"zipimport provides support for importing Python modules from Zip archives.\n\
1180\n\
1181This module exports three objects:\n\
1182- zipimporter: a class; its constructor takes a path to a Zip archive.\n\
Fredrik Lundhb84b35f2006-01-15 15:00:40 +00001183- ZipImportError: exception raised by zipimporter objects. It's a\n\
Just van Rossum52e14d62002-12-30 22:08:05 +00001184 subclass of ImportError, so it can be caught as ImportError, too.\n\
1185- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1186 info dicts, as used in zipimporter._files.\n\
1187\n\
1188It is usually not needed to use the zipimport module explicitly; it is\n\
1189used by the builtin import mechanism for sys.path items that are paths\n\
1190to Zip archives.");
1191
Martin v. Löwis1a214512008-06-11 05:26:20 +00001192static struct PyModuleDef zipimportmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 PyModuleDef_HEAD_INIT,
1194 "zipimport",
1195 zipimport_doc,
1196 -1,
1197 NULL,
1198 NULL,
1199 NULL,
1200 NULL,
1201 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001202};
1203
Just van Rossum52e14d62002-12-30 22:08:05 +00001204PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001205PyInit_zipimport(void)
Just van Rossum52e14d62002-12-30 22:08:05 +00001206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001207 PyObject *mod;
Just van Rossum52e14d62002-12-30 22:08:05 +00001208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 if (PyType_Ready(&ZipImporter_Type) < 0)
1210 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 /* Correct directory separator */
1213 zip_searchorder[0].suffix[0] = SEP;
1214 zip_searchorder[1].suffix[0] = SEP;
1215 zip_searchorder[2].suffix[0] = SEP;
1216 if (Py_OptimizeFlag) {
1217 /* Reverse *.pyc and *.pyo */
1218 struct st_zip_searchorder tmp;
1219 tmp = zip_searchorder[0];
1220 zip_searchorder[0] = zip_searchorder[1];
1221 zip_searchorder[1] = tmp;
1222 tmp = zip_searchorder[3];
1223 zip_searchorder[3] = zip_searchorder[4];
1224 zip_searchorder[4] = tmp;
1225 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 mod = PyModule_Create(&zipimportmodule);
1228 if (mod == NULL)
1229 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1232 PyExc_ImportError, NULL);
1233 if (ZipImportError == NULL)
1234 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 Py_INCREF(ZipImportError);
1237 if (PyModule_AddObject(mod, "ZipImportError",
1238 ZipImportError) < 0)
1239 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 Py_INCREF(&ZipImporter_Type);
1242 if (PyModule_AddObject(mod, "zipimporter",
1243 (PyObject *)&ZipImporter_Type) < 0)
1244 return NULL;
Just van Rossumf8b6de12002-12-31 09:51:59 +00001245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 zip_directory_cache = PyDict_New();
1247 if (zip_directory_cache == NULL)
1248 return NULL;
1249 Py_INCREF(zip_directory_cache);
1250 if (PyModule_AddObject(mod, "_zip_directory_cache",
1251 zip_directory_cache) < 0)
1252 return NULL;
1253 return mod;
Just van Rossum52e14d62002-12-30 22:08:05 +00001254}