Added section on passing contextual information to logging and documentation for...
[python.git] / Modules / zipimport.c
bloba57812d6a4815606424927149591d89c2a9ba9e6
1 #include "Python.h"
2 #include "structmember.h"
3 #include "osdefs.h"
4 #include "marshal.h"
5 #include <time.h>
8 #define IS_SOURCE 0x0
9 #define IS_BYTECODE 0x1
10 #define IS_PACKAGE 0x2
12 struct st_zip_searchorder {
13 char suffix[14];
14 int type;
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. */
22 static struct st_zip_searchorder zip_searchorder[] = {
23 {"/__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}
32 /* zipimporter object definition and support */
34 typedef struct _zipimporter ZipImporter;
36 struct _zipimporter {
37 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} */
43 static PyObject *ZipImportError;
44 static PyObject *zip_directory_cache = NULL;
46 /* forward decls */
47 static PyObject *read_directory(char *archive);
48 static PyObject *get_data(char *archive, PyObject *toc_entry);
49 static PyObject *get_module_code(ZipImporter *self, char *fullname,
50 int *p_ispackage, char **p_modpath);
53 #define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
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. */
60 static int
61 zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
63 char *path, *p, *prefix, buf[MAXPATHLEN+2];
64 size_t len;
66 if (!_PyArg_NoKeywords("zipimporter()", kwds))
67 return -1;
69 if (!PyArg_ParseTuple(args, "s:zipimporter",
70 &path))
71 return -1;
73 len = strlen(path);
74 if (len == 0) {
75 PyErr_SetString(ZipImportError, "archive path is empty");
76 return -1;
78 if (len >= MAXPATHLEN) {
79 PyErr_SetString(ZipImportError,
80 "archive path too long");
81 return -1;
83 strcpy(buf, path);
85 #ifdef ALTSEP
86 for (p = buf; *p; p++) {
87 if (*p == ALTSEP)
88 *p = SEP;
90 #endif
92 path = NULL;
93 prefix = NULL;
94 for (;;) {
95 #ifndef RISCOS
96 struct stat statbuf;
97 int rv;
99 rv = stat(buf, &statbuf);
100 if (rv == 0) {
101 /* it exists */
102 if (S_ISREG(statbuf.st_mode))
103 /* it's a file */
104 path = buf;
105 break;
107 #else
108 if (object_exists(buf)) {
109 /* it exists */
110 if (isfile(buf))
111 /* it's a file */
112 path = buf;
113 break;
115 #endif
116 /* back up one path element */
117 p = strrchr(buf, SEP);
118 if (prefix != NULL)
119 *prefix = SEP;
120 if (p == NULL)
121 break;
122 *p = '\0';
123 prefix = p;
125 if (path != NULL) {
126 PyObject *files;
127 files = PyDict_GetItemString(zip_directory_cache, path);
128 if (files == NULL) {
129 files = read_directory(buf);
130 if (files == NULL)
131 return -1;
132 if (PyDict_SetItemString(zip_directory_cache, path,
133 files) != 0)
134 return -1;
136 else
137 Py_INCREF(files);
138 self->files = files;
140 else {
141 PyErr_SetString(ZipImportError, "not a Zip file");
142 return -1;
145 if (prefix == NULL)
146 prefix = "";
147 else {
148 prefix++;
149 len = strlen(prefix);
150 if (prefix[len-1] != SEP) {
151 /* add trailing SEP */
152 prefix[len] = SEP;
153 prefix[len + 1] = '\0';
157 self->archive = PyString_FromString(buf);
158 if (self->archive == NULL)
159 return -1;
161 self->prefix = PyString_FromString(prefix);
162 if (self->prefix == NULL)
163 return -1;
165 return 0;
168 /* GC support. */
169 static int
170 zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
172 ZipImporter *self = (ZipImporter *)obj;
173 Py_VISIT(self->files);
174 return 0;
177 static void
178 zipimporter_dealloc(ZipImporter *self)
180 PyObject_GC_UnTrack(self);
181 Py_XDECREF(self->archive);
182 Py_XDECREF(self->prefix);
183 Py_XDECREF(self->files);
184 Py_TYPE(self)->tp_free((PyObject *)self);
187 static PyObject *
188 zipimporter_repr(ZipImporter *self)
190 char buf[500];
191 char *archive = "???";
192 char *prefix = "";
194 if (self->archive != NULL && PyString_Check(self->archive))
195 archive = PyString_AsString(self->archive);
196 if (self->prefix != NULL && PyString_Check(self->prefix))
197 prefix = PyString_AsString(self->prefix);
198 if (prefix != NULL && *prefix)
199 PyOS_snprintf(buf, sizeof(buf),
200 "<zipimporter object \"%.300s%c%.150s\">",
201 archive, SEP, prefix);
202 else
203 PyOS_snprintf(buf, sizeof(buf),
204 "<zipimporter object \"%.300s\">",
205 archive);
206 return PyString_FromString(buf);
209 /* return fullname.split(".")[-1] */
210 static char *
211 get_subname(char *fullname)
213 char *subname = strrchr(fullname, '.');
214 if (subname == NULL)
215 subname = fullname;
216 else
217 subname++;
218 return subname;
221 /* Given a (sub)modulename, write the potential file path in the
222 archive (without extension) to the path buffer. Return the
223 length of the resulting string. */
224 static int
225 make_filename(char *prefix, char *name, char *path)
227 size_t len;
228 char *p;
230 len = strlen(prefix);
232 /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */
233 if (len + strlen(name) + 13 >= MAXPATHLEN) {
234 PyErr_SetString(ZipImportError, "path too long");
235 return -1;
238 strcpy(path, prefix);
239 strcpy(path + len, name);
240 for (p = path + len; *p; p++) {
241 if (*p == '.')
242 *p = SEP;
244 len += strlen(name);
245 assert(len < INT_MAX);
246 return (int)len;
249 enum zi_module_info {
250 MI_ERROR,
251 MI_NOT_FOUND,
252 MI_MODULE,
253 MI_PACKAGE
256 /* Return some information about a module. */
257 static enum zi_module_info
258 get_module_info(ZipImporter *self, char *fullname)
260 char *subname, path[MAXPATHLEN + 1];
261 int len;
262 struct st_zip_searchorder *zso;
264 subname = get_subname(fullname);
266 len = make_filename(PyString_AsString(self->prefix), subname, path);
267 if (len < 0)
268 return MI_ERROR;
270 for (zso = zip_searchorder; *zso->suffix; zso++) {
271 strcpy(path + len, zso->suffix);
272 if (PyDict_GetItemString(self->files, path) != NULL) {
273 if (zso->type & IS_PACKAGE)
274 return MI_PACKAGE;
275 else
276 return MI_MODULE;
279 return MI_NOT_FOUND;
282 /* Check whether we can satisfy the import of the module named by
283 'fullname'. Return self if we can, None if we can't. */
284 static PyObject *
285 zipimporter_find_module(PyObject *obj, PyObject *args)
287 ZipImporter *self = (ZipImporter *)obj;
288 PyObject *path = NULL;
289 char *fullname;
290 enum zi_module_info mi;
292 if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module",
293 &fullname, &path))
294 return NULL;
296 mi = get_module_info(self, fullname);
297 if (mi == MI_ERROR)
298 return NULL;
299 if (mi == MI_NOT_FOUND) {
300 Py_INCREF(Py_None);
301 return Py_None;
303 Py_INCREF(self);
304 return (PyObject *)self;
307 /* Load and return the module named by 'fullname'. */
308 static PyObject *
309 zipimporter_load_module(PyObject *obj, PyObject *args)
311 ZipImporter *self = (ZipImporter *)obj;
312 PyObject *code, *mod, *dict;
313 char *fullname, *modpath;
314 int ispackage;
316 if (!PyArg_ParseTuple(args, "s:zipimporter.load_module",
317 &fullname))
318 return NULL;
320 code = get_module_code(self, fullname, &ispackage, &modpath);
321 if (code == NULL)
322 return NULL;
324 mod = PyImport_AddModule(fullname);
325 if (mod == NULL) {
326 Py_DECREF(code);
327 return NULL;
329 dict = PyModule_GetDict(mod);
331 /* mod.__loader__ = self */
332 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
333 goto error;
335 if (ispackage) {
336 /* add __path__ to the module *before* the code gets
337 executed */
338 PyObject *pkgpath, *fullpath;
339 char *prefix = PyString_AsString(self->prefix);
340 char *subname = get_subname(fullname);
341 int err;
343 fullpath = PyString_FromFormat("%s%c%s%s",
344 PyString_AsString(self->archive),
345 SEP,
346 *prefix ? prefix : "",
347 subname);
348 if (fullpath == NULL)
349 goto error;
351 pkgpath = Py_BuildValue("[O]", fullpath);
352 Py_DECREF(fullpath);
353 if (pkgpath == NULL)
354 goto error;
355 err = PyDict_SetItemString(dict, "__path__", pkgpath);
356 Py_DECREF(pkgpath);
357 if (err != 0)
358 goto error;
360 mod = PyImport_ExecCodeModuleEx(fullname, code, modpath);
361 Py_DECREF(code);
362 if (Py_VerboseFlag)
363 PySys_WriteStderr("import %s # loaded from Zip %s\n",
364 fullname, modpath);
365 return mod;
366 error:
367 Py_DECREF(code);
368 Py_DECREF(mod);
369 return NULL;
372 /* Return a bool signifying whether the module is a package or not. */
373 static PyObject *
374 zipimporter_is_package(PyObject *obj, PyObject *args)
376 ZipImporter *self = (ZipImporter *)obj;
377 char *fullname;
378 enum zi_module_info mi;
380 if (!PyArg_ParseTuple(args, "s:zipimporter.is_package",
381 &fullname))
382 return NULL;
384 mi = get_module_info(self, fullname);
385 if (mi == MI_ERROR)
386 return NULL;
387 if (mi == MI_NOT_FOUND) {
388 PyErr_Format(ZipImportError, "can't find module '%.200s'",
389 fullname);
390 return NULL;
392 return PyBool_FromLong(mi == MI_PACKAGE);
395 static PyObject *
396 zipimporter_get_data(PyObject *obj, PyObject *args)
398 ZipImporter *self = (ZipImporter *)obj;
399 char *path;
400 #ifdef ALTSEP
401 char *p, buf[MAXPATHLEN + 1];
402 #endif
403 PyObject *toc_entry;
404 Py_ssize_t len;
406 if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path))
407 return NULL;
409 #ifdef ALTSEP
410 if (strlen(path) >= MAXPATHLEN) {
411 PyErr_SetString(ZipImportError, "path too long");
412 return NULL;
414 strcpy(buf, path);
415 for (p = buf; *p; p++) {
416 if (*p == ALTSEP)
417 *p = SEP;
419 path = buf;
420 #endif
421 len = PyString_Size(self->archive);
422 if ((size_t)len < strlen(path) &&
423 strncmp(path, PyString_AsString(self->archive), len) == 0 &&
424 path[len] == SEP) {
425 path = path + len + 1;
428 toc_entry = PyDict_GetItemString(self->files, path);
429 if (toc_entry == NULL) {
430 PyErr_SetFromErrnoWithFilename(PyExc_IOError, path);
431 return NULL;
433 return get_data(PyString_AsString(self->archive), toc_entry);
436 static PyObject *
437 zipimporter_get_code(PyObject *obj, PyObject *args)
439 ZipImporter *self = (ZipImporter *)obj;
440 char *fullname;
442 if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname))
443 return NULL;
445 return get_module_code(self, fullname, NULL, NULL);
448 static PyObject *
449 zipimporter_get_source(PyObject *obj, PyObject *args)
451 ZipImporter *self = (ZipImporter *)obj;
452 PyObject *toc_entry;
453 char *fullname, *subname, path[MAXPATHLEN+1];
454 int len;
455 enum zi_module_info mi;
457 if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname))
458 return NULL;
460 mi = get_module_info(self, fullname);
461 if (mi == MI_ERROR)
462 return NULL;
463 if (mi == MI_NOT_FOUND) {
464 PyErr_Format(ZipImportError, "can't find module '%.200s'",
465 fullname);
466 return NULL;
468 subname = get_subname(fullname);
470 len = make_filename(PyString_AsString(self->prefix), subname, path);
471 if (len < 0)
472 return NULL;
474 if (mi == MI_PACKAGE) {
475 path[len] = SEP;
476 strcpy(path + len + 1, "__init__.py");
478 else
479 strcpy(path + len, ".py");
481 toc_entry = PyDict_GetItemString(self->files, path);
482 if (toc_entry != NULL)
483 return get_data(PyString_AsString(self->archive), toc_entry);
485 /* we have the module, but no source */
486 Py_INCREF(Py_None);
487 return Py_None;
490 PyDoc_STRVAR(doc_find_module,
491 "find_module(fullname, path=None) -> self or None.\n\
493 Search for a module specified by 'fullname'. 'fullname' must be the\n\
494 fully qualified (dotted) module name. It returns the zipimporter\n\
495 instance itself if the module was found, or None if it wasn't.\n\
496 The optional 'path' argument is ignored -- it's there for compatibility\n\
497 with the importer protocol.");
499 PyDoc_STRVAR(doc_load_module,
500 "load_module(fullname) -> module.\n\
502 Load the module specified by 'fullname'. 'fullname' must be the\n\
503 fully qualified (dotted) module name. It returns the imported\n\
504 module, or raises ZipImportError if it wasn't found.");
506 PyDoc_STRVAR(doc_get_data,
507 "get_data(pathname) -> string with file data.\n\
509 Return the data associated with 'pathname'. Raise IOError if\n\
510 the file wasn't found.");
512 PyDoc_STRVAR(doc_is_package,
513 "is_package(fullname) -> bool.\n\
515 Return True if the module specified by fullname is a package.\n\
516 Raise ZipImportError is the module couldn't be found.");
518 PyDoc_STRVAR(doc_get_code,
519 "get_code(fullname) -> code object.\n\
521 Return the code object for the specified module. Raise ZipImportError\n\
522 is the module couldn't be found.");
524 PyDoc_STRVAR(doc_get_source,
525 "get_source(fullname) -> source string.\n\
527 Return the source code for the specified module. Raise ZipImportError\n\
528 is the module couldn't be found, return None if the archive does\n\
529 contain the module, but has no source for it.");
531 static PyMethodDef zipimporter_methods[] = {
532 {"find_module", zipimporter_find_module, METH_VARARGS,
533 doc_find_module},
534 {"load_module", zipimporter_load_module, METH_VARARGS,
535 doc_load_module},
536 {"get_data", zipimporter_get_data, METH_VARARGS,
537 doc_get_data},
538 {"get_code", zipimporter_get_code, METH_VARARGS,
539 doc_get_code},
540 {"get_source", zipimporter_get_source, METH_VARARGS,
541 doc_get_source},
542 {"is_package", zipimporter_is_package, METH_VARARGS,
543 doc_is_package},
544 {NULL, NULL} /* sentinel */
547 static PyMemberDef zipimporter_members[] = {
548 {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},
549 {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},
550 {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},
551 {NULL}
554 PyDoc_STRVAR(zipimporter_doc,
555 "zipimporter(archivepath) -> zipimporter object\n\
557 Create a new zipimporter instance. 'archivepath' must be a path to\n\
558 a zipfile. ZipImportError is raised if 'archivepath' doesn't point to\n\
559 a valid Zip archive.");
561 #define DEFERRED_ADDRESS(ADDR) 0
563 static PyTypeObject ZipImporter_Type = {
564 PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
565 "zipimport.zipimporter",
566 sizeof(ZipImporter),
567 0, /* tp_itemsize */
568 (destructor)zipimporter_dealloc, /* tp_dealloc */
569 0, /* tp_print */
570 0, /* tp_getattr */
571 0, /* tp_setattr */
572 0, /* tp_compare */
573 (reprfunc)zipimporter_repr, /* tp_repr */
574 0, /* tp_as_number */
575 0, /* tp_as_sequence */
576 0, /* tp_as_mapping */
577 0, /* tp_hash */
578 0, /* tp_call */
579 0, /* tp_str */
580 PyObject_GenericGetAttr, /* tp_getattro */
581 0, /* tp_setattro */
582 0, /* tp_as_buffer */
583 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
584 Py_TPFLAGS_HAVE_GC, /* tp_flags */
585 zipimporter_doc, /* tp_doc */
586 zipimporter_traverse, /* tp_traverse */
587 0, /* tp_clear */
588 0, /* tp_richcompare */
589 0, /* tp_weaklistoffset */
590 0, /* tp_iter */
591 0, /* tp_iternext */
592 zipimporter_methods, /* tp_methods */
593 zipimporter_members, /* tp_members */
594 0, /* tp_getset */
595 0, /* tp_base */
596 0, /* tp_dict */
597 0, /* tp_descr_get */
598 0, /* tp_descr_set */
599 0, /* tp_dictoffset */
600 (initproc)zipimporter_init, /* tp_init */
601 PyType_GenericAlloc, /* tp_alloc */
602 PyType_GenericNew, /* tp_new */
603 PyObject_GC_Del, /* tp_free */
607 /* implementation */
609 /* Given a buffer, return the long that is represented by the first
610 4 bytes, encoded as little endian. This partially reimplements
611 marshal.c:r_long() */
612 static long
613 get_long(unsigned char *buf) {
614 long x;
615 x = buf[0];
616 x |= (long)buf[1] << 8;
617 x |= (long)buf[2] << 16;
618 x |= (long)buf[3] << 24;
619 #if SIZEOF_LONG > 4
620 /* Sign extension for 64-bit machines */
621 x |= -(x & 0x80000000L);
622 #endif
623 return x;
627 read_directory(archive) -> files dict (new reference)
629 Given a path to a Zip archive, build a dict, mapping file names
630 (local to the archive, using SEP as a separator) to toc entries.
632 A toc_entry is a tuple:
634 (__file__, # value to use for __file__, available for all files
635 compress, # compression kind; 0 for uncompressed
636 data_size, # size of compressed data on disk
637 file_size, # size of decompressed data
638 file_offset, # offset of file header from start of archive
639 time, # mod time of file (in dos format)
640 date, # mod data of file (in dos format)
641 crc, # crc checksum of the data
644 Directories can be recognized by the trailing SEP in the name,
645 data_size and file_offset are 0.
647 static PyObject *
648 read_directory(char *archive)
650 PyObject *files = NULL;
651 FILE *fp;
652 long compress, crc, data_size, file_size, file_offset, date, time;
653 long header_offset, name_size, header_size, header_position;
654 long i, l, count;
655 size_t length;
656 char path[MAXPATHLEN + 5];
657 char name[MAXPATHLEN + 5];
658 char *p, endof_central_dir[22];
659 long arc_offset; /* offset from beginning of file to start of zip-archive */
661 if (strlen(archive) > MAXPATHLEN) {
662 PyErr_SetString(PyExc_OverflowError,
663 "Zip path name is too long");
664 return NULL;
666 strcpy(path, archive);
668 fp = fopen(archive, "rb");
669 if (fp == NULL) {
670 PyErr_Format(ZipImportError, "can't open Zip file: "
671 "'%.200s'", archive);
672 return NULL;
674 fseek(fp, -22, SEEK_END);
675 header_position = ftell(fp);
676 if (fread(endof_central_dir, 1, 22, fp) != 22) {
677 fclose(fp);
678 PyErr_Format(ZipImportError, "can't read Zip file: "
679 "'%.200s'", archive);
680 return NULL;
682 if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
683 /* Bad: End of Central Dir signature */
684 fclose(fp);
685 PyErr_Format(ZipImportError, "not a Zip file: "
686 "'%.200s'", archive);
687 return NULL;
690 header_size = get_long((unsigned char *)endof_central_dir + 12);
691 header_offset = get_long((unsigned char *)endof_central_dir + 16);
692 arc_offset = header_position - header_offset - header_size;
693 header_offset += arc_offset;
695 files = PyDict_New();
696 if (files == NULL)
697 goto error;
699 length = (long)strlen(path);
700 path[length] = SEP;
702 /* Start of Central Directory */
703 count = 0;
704 for (;;) {
705 PyObject *t;
706 int err;
708 fseek(fp, header_offset, 0); /* Start of file header */
709 l = PyMarshal_ReadLongFromFile(fp);
710 if (l != 0x02014B50)
711 break; /* Bad: Central Dir File Header */
712 fseek(fp, header_offset + 10, 0);
713 compress = PyMarshal_ReadShortFromFile(fp);
714 time = PyMarshal_ReadShortFromFile(fp);
715 date = PyMarshal_ReadShortFromFile(fp);
716 crc = PyMarshal_ReadLongFromFile(fp);
717 data_size = PyMarshal_ReadLongFromFile(fp);
718 file_size = PyMarshal_ReadLongFromFile(fp);
719 name_size = PyMarshal_ReadShortFromFile(fp);
720 header_size = 46 + name_size +
721 PyMarshal_ReadShortFromFile(fp) +
722 PyMarshal_ReadShortFromFile(fp);
723 fseek(fp, header_offset + 42, 0);
724 file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
725 if (name_size > MAXPATHLEN)
726 name_size = MAXPATHLEN;
728 p = name;
729 for (i = 0; i < name_size; i++) {
730 *p = (char)getc(fp);
731 if (*p == '/')
732 *p = SEP;
733 p++;
735 *p = 0; /* Add terminating null byte */
736 header_offset += header_size;
738 strncpy(path + length + 1, name, MAXPATHLEN - length - 1);
740 t = Py_BuildValue("siiiiiii", path, compress, data_size,
741 file_size, file_offset, time, date, crc);
742 if (t == NULL)
743 goto error;
744 err = PyDict_SetItemString(files, name, t);
745 Py_DECREF(t);
746 if (err != 0)
747 goto error;
748 count++;
750 fclose(fp);
751 if (Py_VerboseFlag)
752 PySys_WriteStderr("# zipimport: found %ld names in %s\n",
753 count, archive);
754 return files;
755 error:
756 fclose(fp);
757 Py_XDECREF(files);
758 return NULL;
761 /* Return the zlib.decompress function object, or NULL if zlib couldn't
762 be imported. The function is cached when found, so subsequent calls
763 don't import zlib again. Returns a *borrowed* reference.
764 XXX This makes zlib.decompress immortal. */
765 static PyObject *
766 get_decompress_func(void)
768 static PyObject *decompress = NULL;
770 if (decompress == NULL) {
771 PyObject *zlib;
772 static int importing_zlib = 0;
774 if (importing_zlib != 0)
775 /* Someone has a zlib.py[co] in their Zip file;
776 let's avoid a stack overflow. */
777 return NULL;
778 importing_zlib = 1;
779 zlib = PyImport_ImportModuleNoBlock("zlib");
780 importing_zlib = 0;
781 if (zlib != NULL) {
782 decompress = PyObject_GetAttrString(zlib,
783 "decompress");
784 Py_DECREF(zlib);
786 else
787 PyErr_Clear();
788 if (Py_VerboseFlag)
789 PySys_WriteStderr("# zipimport: zlib %s\n",
790 zlib != NULL ? "available": "UNAVAILABLE");
792 return decompress;
795 /* Given a path to a Zip file and a toc_entry, return the (uncompressed)
796 data as a new reference. */
797 static PyObject *
798 get_data(char *archive, PyObject *toc_entry)
800 PyObject *raw_data, *data = NULL, *decompress;
801 char *buf;
802 FILE *fp;
803 int err;
804 Py_ssize_t bytes_read = 0;
805 long l;
806 char *datapath;
807 long compress, data_size, file_size, file_offset;
808 long time, date, crc;
810 if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,
811 &data_size, &file_size, &file_offset, &time,
812 &date, &crc)) {
813 return NULL;
816 fp = fopen(archive, "rb");
817 if (!fp) {
818 PyErr_Format(PyExc_IOError,
819 "zipimport: can not open file %s", archive);
820 return NULL;
823 /* Check to make sure the local file header is correct */
824 fseek(fp, file_offset, 0);
825 l = PyMarshal_ReadLongFromFile(fp);
826 if (l != 0x04034B50) {
827 /* Bad: Local File Header */
828 PyErr_Format(ZipImportError,
829 "bad local file header in %s",
830 archive);
831 fclose(fp);
832 return NULL;
834 fseek(fp, file_offset + 26, 0);
835 l = 30 + PyMarshal_ReadShortFromFile(fp) +
836 PyMarshal_ReadShortFromFile(fp); /* local header size */
837 file_offset += l; /* Start of file data */
839 raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ?
840 data_size : data_size + 1);
841 if (raw_data == NULL) {
842 fclose(fp);
843 return NULL;
845 buf = PyString_AsString(raw_data);
847 err = fseek(fp, file_offset, 0);
848 if (err == 0)
849 bytes_read = fread(buf, 1, data_size, fp);
850 fclose(fp);
851 if (err || bytes_read != data_size) {
852 PyErr_SetString(PyExc_IOError,
853 "zipimport: can't read data");
854 Py_DECREF(raw_data);
855 return NULL;
858 if (compress != 0) {
859 buf[data_size] = 'Z'; /* saw this in zipfile.py */
860 data_size++;
862 buf[data_size] = '\0';
864 if (compress == 0) /* data is not compressed */
865 return raw_data;
867 /* Decompress with zlib */
868 decompress = get_decompress_func();
869 if (decompress == NULL) {
870 PyErr_SetString(ZipImportError,
871 "can't decompress data; "
872 "zlib not available");
873 goto error;
875 data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
876 error:
877 Py_DECREF(raw_data);
878 return data;
881 /* Lenient date/time comparison function. The precision of the mtime
882 in the archive is lower than the mtime stored in a .pyc: we
883 must allow a difference of at most one second. */
884 static int
885 eq_mtime(time_t t1, time_t t2)
887 time_t d = t1 - t2;
888 if (d < 0)
889 d = -d;
890 /* dostime only stores even seconds, so be lenient */
891 return d <= 1;
894 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
895 and return the code object. Return None if it the magic word doesn't
896 match (we do this instead of raising an exception as we fall back
897 to .py if available and we don't want to mask other errors).
898 Returns a new reference. */
899 static PyObject *
900 unmarshal_code(char *pathname, PyObject *data, time_t mtime)
902 PyObject *code;
903 char *buf = PyString_AsString(data);
904 Py_ssize_t size = PyString_Size(data);
906 if (size <= 9) {
907 PyErr_SetString(ZipImportError,
908 "bad pyc data");
909 return NULL;
912 if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
913 if (Py_VerboseFlag)
914 PySys_WriteStderr("# %s has bad magic\n",
915 pathname);
916 Py_INCREF(Py_None);
917 return Py_None; /* signal caller to try alternative */
920 if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
921 mtime)) {
922 if (Py_VerboseFlag)
923 PySys_WriteStderr("# %s has bad mtime\n",
924 pathname);
925 Py_INCREF(Py_None);
926 return Py_None; /* signal caller to try alternative */
929 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
930 if (code == NULL)
931 return NULL;
932 if (!PyCode_Check(code)) {
933 Py_DECREF(code);
934 PyErr_Format(PyExc_TypeError,
935 "compiled module %.200s is not a code object",
936 pathname);
937 return NULL;
939 return code;
942 /* Replace any occurances of "\r\n?" in the input string with "\n".
943 This converts DOS and Mac line endings to Unix line endings.
944 Also append a trailing "\n" to be compatible with
945 PyParser_SimpleParseFile(). Returns a new reference. */
946 static PyObject *
947 normalize_line_endings(PyObject *source)
949 char *buf, *q, *p = PyString_AsString(source);
950 PyObject *fixed_source;
952 if (!p)
953 return NULL;
955 /* one char extra for trailing \n and one for terminating \0 */
956 buf = (char *)PyMem_Malloc(PyString_Size(source) + 2);
957 if (buf == NULL) {
958 PyErr_SetString(PyExc_MemoryError,
959 "zipimport: no memory to allocate "
960 "source buffer");
961 return NULL;
963 /* replace "\r\n?" by "\n" */
964 for (q = buf; *p != '\0'; p++) {
965 if (*p == '\r') {
966 *q++ = '\n';
967 if (*(p + 1) == '\n')
968 p++;
970 else
971 *q++ = *p;
973 *q++ = '\n'; /* add trailing \n */
974 *q = '\0';
975 fixed_source = PyString_FromString(buf);
976 PyMem_Free(buf);
977 return fixed_source;
980 /* Given a string buffer containing Python source code, compile it
981 return and return a code object as a new reference. */
982 static PyObject *
983 compile_source(char *pathname, PyObject *source)
985 PyObject *code, *fixed_source;
987 fixed_source = normalize_line_endings(source);
988 if (fixed_source == NULL)
989 return NULL;
991 code = Py_CompileString(PyString_AsString(fixed_source), pathname,
992 Py_file_input);
993 Py_DECREF(fixed_source);
994 return code;
997 /* Convert the date/time values found in the Zip archive to a value
998 that's compatible with the time stamp stored in .pyc files. */
999 static time_t
1000 parse_dostime(int dostime, int dosdate)
1002 struct tm stm;
1004 memset((void *) &stm, '\0', sizeof(stm));
1006 stm.tm_sec = (dostime & 0x1f) * 2;
1007 stm.tm_min = (dostime >> 5) & 0x3f;
1008 stm.tm_hour = (dostime >> 11) & 0x1f;
1009 stm.tm_mday = dosdate & 0x1f;
1010 stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1011 stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1012 stm.tm_isdst = -1; /* wday/yday is ignored */
1014 return mktime(&stm);
1017 /* Given a path to a .pyc or .pyo file in the archive, return the
1018 modifictaion time of the matching .py file, or 0 if no source
1019 is available. */
1020 static time_t
1021 get_mtime_of_source(ZipImporter *self, char *path)
1023 PyObject *toc_entry;
1024 time_t mtime = 0;
1025 Py_ssize_t lastchar = strlen(path) - 1;
1026 char savechar = path[lastchar];
1027 path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */
1028 toc_entry = PyDict_GetItemString(self->files, path);
1029 if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1030 PyTuple_Size(toc_entry) == 8) {
1031 /* fetch the time stamp of the .py file for comparison
1032 with an embedded pyc time stamp */
1033 int time, date;
1034 time = PyInt_AsLong(PyTuple_GetItem(toc_entry, 5));
1035 date = PyInt_AsLong(PyTuple_GetItem(toc_entry, 6));
1036 mtime = parse_dostime(time, date);
1038 path[lastchar] = savechar;
1039 return mtime;
1042 /* Return the code object for the module named by 'fullname' from the
1043 Zip archive as a new reference. */
1044 static PyObject *
1045 get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
1046 time_t mtime, PyObject *toc_entry)
1048 PyObject *data, *code;
1049 char *modpath;
1050 char *archive = PyString_AsString(self->archive);
1052 if (archive == NULL)
1053 return NULL;
1055 data = get_data(archive, toc_entry);
1056 if (data == NULL)
1057 return NULL;
1059 modpath = PyString_AsString(PyTuple_GetItem(toc_entry, 0));
1061 if (isbytecode) {
1062 code = unmarshal_code(modpath, data, mtime);
1064 else {
1065 code = compile_source(modpath, data);
1067 Py_DECREF(data);
1068 return code;
1071 /* Get the code object assoiciated with the module specified by
1072 'fullname'. */
1073 static PyObject *
1074 get_module_code(ZipImporter *self, char *fullname,
1075 int *p_ispackage, char **p_modpath)
1077 PyObject *toc_entry;
1078 char *subname, path[MAXPATHLEN + 1];
1079 int len;
1080 struct st_zip_searchorder *zso;
1082 subname = get_subname(fullname);
1084 len = make_filename(PyString_AsString(self->prefix), subname, path);
1085 if (len < 0)
1086 return NULL;
1088 for (zso = zip_searchorder; *zso->suffix; zso++) {
1089 PyObject *code = NULL;
1091 strcpy(path + len, zso->suffix);
1092 if (Py_VerboseFlag > 1)
1093 PySys_WriteStderr("# trying %s%c%s\n",
1094 PyString_AsString(self->archive),
1095 SEP, path);
1096 toc_entry = PyDict_GetItemString(self->files, path);
1097 if (toc_entry != NULL) {
1098 time_t mtime = 0;
1099 int ispackage = zso->type & IS_PACKAGE;
1100 int isbytecode = zso->type & IS_BYTECODE;
1102 if (isbytecode)
1103 mtime = get_mtime_of_source(self, path);
1104 if (p_ispackage != NULL)
1105 *p_ispackage = ispackage;
1106 code = get_code_from_data(self, ispackage,
1107 isbytecode, mtime,
1108 toc_entry);
1109 if (code == Py_None) {
1110 /* bad magic number or non-matching mtime
1111 in byte code, try next */
1112 Py_DECREF(code);
1113 continue;
1115 if (code != NULL && p_modpath != NULL)
1116 *p_modpath = PyString_AsString(
1117 PyTuple_GetItem(toc_entry, 0));
1118 return code;
1121 PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);
1122 return NULL;
1126 /* Module init */
1128 PyDoc_STRVAR(zipimport_doc,
1129 "zipimport provides support for importing Python modules from Zip archives.\n\
1131 This module exports three objects:\n\
1132 - zipimporter: a class; its constructor takes a path to a Zip archive.\n\
1133 - ZipImportError: exception raised by zipimporter objects. It's a\n\
1134 subclass of ImportError, so it can be caught as ImportError, too.\n\
1135 - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1136 info dicts, as used in zipimporter._files.\n\
1138 It is usually not needed to use the zipimport module explicitly; it is\n\
1139 used by the builtin import mechanism for sys.path items that are paths\n\
1140 to Zip archives.");
1142 PyMODINIT_FUNC
1143 initzipimport(void)
1145 PyObject *mod;
1147 if (PyType_Ready(&ZipImporter_Type) < 0)
1148 return;
1150 /* Correct directory separator */
1151 zip_searchorder[0].suffix[0] = SEP;
1152 zip_searchorder[1].suffix[0] = SEP;
1153 zip_searchorder[2].suffix[0] = SEP;
1154 if (Py_OptimizeFlag) {
1155 /* Reverse *.pyc and *.pyo */
1156 struct st_zip_searchorder tmp;
1157 tmp = zip_searchorder[0];
1158 zip_searchorder[0] = zip_searchorder[1];
1159 zip_searchorder[1] = tmp;
1160 tmp = zip_searchorder[3];
1161 zip_searchorder[3] = zip_searchorder[4];
1162 zip_searchorder[4] = tmp;
1165 mod = Py_InitModule4("zipimport", NULL, zipimport_doc,
1166 NULL, PYTHON_API_VERSION);
1167 if (mod == NULL)
1168 return;
1170 ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1171 PyExc_ImportError, NULL);
1172 if (ZipImportError == NULL)
1173 return;
1175 Py_INCREF(ZipImportError);
1176 if (PyModule_AddObject(mod, "ZipImportError",
1177 ZipImportError) < 0)
1178 return;
1180 Py_INCREF(&ZipImporter_Type);
1181 if (PyModule_AddObject(mod, "zipimporter",
1182 (PyObject *)&ZipImporter_Type) < 0)
1183 return;
1185 zip_directory_cache = PyDict_New();
1186 if (zip_directory_cache == NULL)
1187 return;
1188 Py_INCREF(zip_directory_cache);
1189 if (PyModule_AddObject(mod, "_zip_directory_cache",
1190 zip_directory_cache) < 0)
1191 return;