1#include "Python.h"
2#include "structmember.h"
3#include "osdefs.h"
4#include "marshal.h"
5#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 {
13    char suffix[14];
14    int type;
15};
16
17#ifdef ALTSEP
18_Py_IDENTIFIER(replace);
19#endif
20
21/* zip_searchorder defines how we search for a module in the Zip
22   archive: we first search for a package __init__, then for
23   non-package .pyc, and .py entries. The .pyc entries
24   are swapped by initzipimport() if we run in optimized mode. Also,
25   '/' is replaced by SEP there. */
26static struct st_zip_searchorder zip_searchorder[] = {
27    {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
28    {"/__init__.py", IS_PACKAGE | IS_SOURCE},
29    {".pyc", IS_BYTECODE},
30    {".py", IS_SOURCE},
31    {"", 0}
32};
33
34/* zipimporter object definition and support */
35
36typedef struct _zipimporter ZipImporter;
37
38struct _zipimporter {
39    PyObject_HEAD
40    PyObject *archive;  /* pathname of the Zip archive,
41                           decoded from the filesystem encoding */
42    PyObject *prefix;   /* file prefix: "a/sub/directory/",
43                           encoded to the filesystem encoding */
44    PyObject *files;    /* dict with file info {path: toc_entry} */
45};
46
47static PyObject *ZipImportError;
48/* read_directory() cache */
49static PyObject *zip_directory_cache = NULL;
50
51/* forward decls */
52static PyObject *read_directory(PyObject *archive);
53static PyObject *get_data(PyObject *archive, PyObject *toc_entry);
54static PyObject *get_module_code(ZipImporter *self, PyObject *fullname,
55                                 int *p_ispackage, PyObject **p_modpath);
56
57
58#define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
59
60
61/* zipimporter.__init__
62   Split the "subdirectory" from the Zip archive path, lookup a matching
63   entry in sys.path_importer_cache, fetch the file directory from there
64   if found, or else read it from the archive. */
65static int
66zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
67{
68    PyObject *path, *files, *tmp;
69    PyObject *filename = NULL;
70    Py_ssize_t len, flen;
71
72    if (!_PyArg_NoKeywords("zipimporter()", kwds))
73        return -1;
74
75    if (!PyArg_ParseTuple(args, "O&:zipimporter",
76                          PyUnicode_FSDecoder, &path))
77        return -1;
78
79    if (PyUnicode_READY(path) == -1)
80        return -1;
81
82    len = PyUnicode_GET_LENGTH(path);
83    if (len == 0) {
84        PyErr_SetString(ZipImportError, "archive path is empty");
85        goto error;
86    }
87
88#ifdef ALTSEP
89    tmp = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
90    if (!tmp)
91        goto error;
92    Py_DECREF(path);
93    path = tmp;
94#endif
95
96    filename = path;
97    Py_INCREF(filename);
98    flen = len;
99    for (;;) {
100        struct stat statbuf;
101        int rv;
102
103        rv = _Py_stat(filename, &statbuf);
104        if (rv == -2)
105            goto error;
106        if (rv == 0) {
107            /* it exists */
108            if (!S_ISREG(statbuf.st_mode))
109                /* it's a not file */
110                Py_CLEAR(filename);
111            break;
112        }
113        Py_CLEAR(filename);
114        /* back up one path element */
115        flen = PyUnicode_FindChar(path, SEP, 0, flen, -1);
116        if (flen == -1)
117            break;
118        filename = PyUnicode_Substring(path, 0, flen);
119        if (filename == NULL)
120            goto error;
121    }
122    if (filename == NULL) {
123        PyErr_SetString(ZipImportError, "not a Zip file");
124        goto error;
125    }
126
127    if (PyUnicode_READY(filename) < 0)
128        goto error;
129
130    files = PyDict_GetItem(zip_directory_cache, filename);
131    if (files == NULL) {
132        files = read_directory(filename);
133        if (files == NULL)
134            goto error;
135        if (PyDict_SetItem(zip_directory_cache, filename, files) != 0)
136            goto error;
137    }
138    else
139        Py_INCREF(files);
140    self->files = files;
141
142    /* Transfer reference */
143    self->archive = filename;
144    filename = NULL;
145
146    /* Check if there is a prefix directory following the filename. */
147    if (flen != len) {
148        tmp = PyUnicode_Substring(path, flen+1,
149                                  PyUnicode_GET_LENGTH(path));
150        if (tmp == NULL)
151            goto error;
152        self->prefix = tmp;
153        if (PyUnicode_READ_CHAR(path, len-1) != SEP) {
154            /* add trailing SEP */
155            tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP);
156            if (tmp == NULL)
157                goto error;
158            Py_SETREF(self->prefix, tmp);
159        }
160    }
161    else
162        self->prefix = PyUnicode_New(0, 0);
163    Py_DECREF(path);
164    return 0;
165
166error:
167    Py_DECREF(path);
168    Py_XDECREF(filename);
169    return -1;
170}
171
172/* GC support. */
173static int
174zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
175{
176    ZipImporter *self = (ZipImporter *)obj;
177    Py_VISIT(self->files);
178    return 0;
179}
180
181static void
182zipimporter_dealloc(ZipImporter *self)
183{
184    PyObject_GC_UnTrack(self);
185    Py_XDECREF(self->archive);
186    Py_XDECREF(self->prefix);
187    Py_XDECREF(self->files);
188    Py_TYPE(self)->tp_free((PyObject *)self);
189}
190
191static PyObject *
192zipimporter_repr(ZipImporter *self)
193{
194    if (self->archive == NULL)
195        return PyUnicode_FromString("<zipimporter object \"???\">");
196    else if (self->prefix != NULL && PyUnicode_GET_LENGTH(self->prefix) != 0)
197        return PyUnicode_FromFormat("<zipimporter object \"%U%c%U\">",
198                                    self->archive, SEP, self->prefix);
199    else
200        return PyUnicode_FromFormat("<zipimporter object \"%U\">",
201                                    self->archive);
202}
203
204/* return fullname.split(".")[-1] */
205static PyObject *
206get_subname(PyObject *fullname)
207{
208    Py_ssize_t len, dot;
209    if (PyUnicode_READY(fullname) < 0)
210        return NULL;
211    len = PyUnicode_GET_LENGTH(fullname);
212    dot = PyUnicode_FindChar(fullname, '.', 0, len, -1);
213    if (dot == -1) {
214        Py_INCREF(fullname);
215        return fullname;
216    } else
217        return PyUnicode_Substring(fullname, dot+1, len);
218}
219
220/* Given a (sub)modulename, write the potential file path in the
221   archive (without extension) to the path buffer. Return the
222   length of the resulting string.
223
224   return self.prefix + name.replace('.', os.sep) */
225static PyObject*
226make_filename(PyObject *prefix, PyObject *name)
227{
228    PyObject *pathobj;
229    Py_UCS4 *p, *buf;
230    Py_ssize_t len;
231
232    len = PyUnicode_GET_LENGTH(prefix) + PyUnicode_GET_LENGTH(name) + 1;
233    p = buf = PyMem_New(Py_UCS4, len);
234    if (buf == NULL) {
235        PyErr_NoMemory();
236        return NULL;
237    }
238
239    if (!PyUnicode_AsUCS4(prefix, p, len, 0)) {
240        PyMem_Free(buf);
241        return NULL;
242    }
243    p += PyUnicode_GET_LENGTH(prefix);
244    len -= PyUnicode_GET_LENGTH(prefix);
245    if (!PyUnicode_AsUCS4(name, p, len, 1)) {
246        PyMem_Free(buf);
247        return NULL;
248    }
249    for (; *p; p++) {
250        if (*p == '.')
251            *p = SEP;
252    }
253    pathobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
254                                        buf, p-buf);
255    PyMem_Free(buf);
256    return pathobj;
257}
258
259enum zi_module_info {
260    MI_ERROR,
261    MI_NOT_FOUND,
262    MI_MODULE,
263    MI_PACKAGE
264};
265
266/* Does this path represent a directory?
267   on error, return < 0
268   if not a dir, return 0
269   if a dir, return 1
270*/
271static int
272check_is_directory(ZipImporter *self, PyObject* prefix, PyObject *path)
273{
274    PyObject *dirpath;
275    int res;
276
277    /* See if this is a "directory". If so, it's eligible to be part
278       of a namespace package. We test by seeing if the name, with an
279       appended path separator, exists. */
280    dirpath = PyUnicode_FromFormat("%U%U%c", prefix, path, SEP);
281    if (dirpath == NULL)
282        return -1;
283    /* If dirpath is present in self->files, we have a directory. */
284    res = PyDict_Contains(self->files, dirpath);
285    Py_DECREF(dirpath);
286    return res;
287}
288
289/* Return some information about a module. */
290static enum zi_module_info
291get_module_info(ZipImporter *self, PyObject *fullname)
292{
293    PyObject *subname;
294    PyObject *path, *fullpath, *item;
295    struct st_zip_searchorder *zso;
296
297    subname = get_subname(fullname);
298    if (subname == NULL)
299        return MI_ERROR;
300
301    path = make_filename(self->prefix, subname);
302    Py_DECREF(subname);
303    if (path == NULL)
304        return MI_ERROR;
305
306    for (zso = zip_searchorder; *zso->suffix; zso++) {
307        fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix);
308        if (fullpath == NULL) {
309            Py_DECREF(path);
310            return MI_ERROR;
311        }
312        item = PyDict_GetItem(self->files, fullpath);
313        Py_DECREF(fullpath);
314        if (item != NULL) {
315            Py_DECREF(path);
316            if (zso->type & IS_PACKAGE)
317                return MI_PACKAGE;
318            else
319                return MI_MODULE;
320        }
321    }
322    Py_DECREF(path);
323    return MI_NOT_FOUND;
324}
325
326typedef enum {
327    FL_ERROR = -1,       /* error */
328    FL_NOT_FOUND,        /* no loader or namespace portions found */
329    FL_MODULE_FOUND,     /* module/package found */
330    FL_NS_FOUND          /* namespace portion found: */
331                         /* *namespace_portion will point to the name */
332} find_loader_result;
333
334/* The guts of "find_loader" and "find_module".
335*/
336static find_loader_result
337find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion)
338{
339    enum zi_module_info mi;
340
341    *namespace_portion = NULL;
342
343    mi = get_module_info(self, fullname);
344    if (mi == MI_ERROR)
345        return FL_ERROR;
346    if (mi == MI_NOT_FOUND) {
347        /* Not a module or regular package. See if this is a directory, and
348           therefore possibly a portion of a namespace package. */
349        find_loader_result result = FL_NOT_FOUND;
350        PyObject *subname;
351        int is_dir;
352
353        /* We're only interested in the last path component of fullname;
354           earlier components are recorded in self->prefix. */
355        subname = get_subname(fullname);
356        if (subname == NULL) {
357            return FL_ERROR;
358        }
359
360        is_dir = check_is_directory(self, self->prefix, subname);
361        if (is_dir < 0)
362            result = FL_ERROR;
363        else if (is_dir) {
364            /* This is possibly a portion of a namespace
365               package. Return the string representing its path,
366               without a trailing separator. */
367            *namespace_portion = PyUnicode_FromFormat("%U%c%U%U",
368                                                      self->archive, SEP,
369                                                      self->prefix, subname);
370            if (*namespace_portion == NULL)
371                result = FL_ERROR;
372            else
373                result = FL_NS_FOUND;
374        }
375        Py_DECREF(subname);
376        return result;
377    }
378    /* This is a module or package. */
379    return FL_MODULE_FOUND;
380}
381
382
383/* Check whether we can satisfy the import of the module named by
384   'fullname'. Return self if we can, None if we can't. */
385static PyObject *
386zipimporter_find_module(PyObject *obj, PyObject *args)
387{
388    ZipImporter *self = (ZipImporter *)obj;
389    PyObject *path = NULL;
390    PyObject *fullname;
391    PyObject *namespace_portion = NULL;
392    PyObject *result = NULL;
393
394    if (!PyArg_ParseTuple(args, "U|O:zipimporter.find_module", &fullname, &path))
395        return NULL;
396
397    switch (find_loader(self, fullname, &namespace_portion)) {
398    case FL_ERROR:
399        return NULL;
400    case FL_NS_FOUND:
401        /* A namespace portion is not allowed via find_module, so return None. */
402        Py_DECREF(namespace_portion);
403        /* FALL THROUGH */
404    case FL_NOT_FOUND:
405        result = Py_None;
406        break;
407    case FL_MODULE_FOUND:
408        result = (PyObject *)self;
409        break;
410    default:
411        PyErr_BadInternalCall();
412        return NULL;
413    }
414    Py_INCREF(result);
415    return result;
416}
417
418
419/* Check whether we can satisfy the import of the module named by
420   'fullname', or whether it could be a portion of a namespace
421   package. Return self if we can load it, a string containing the
422   full path if it's a possible namespace portion, None if we
423   can't load it. */
424static PyObject *
425zipimporter_find_loader(PyObject *obj, PyObject *args)
426{
427    ZipImporter *self = (ZipImporter *)obj;
428    PyObject *path = NULL;
429    PyObject *fullname;
430    PyObject *result = NULL;
431    PyObject *namespace_portion = NULL;
432
433    if (!PyArg_ParseTuple(args, "U|O:zipimporter.find_module", &fullname, &path))
434        return NULL;
435
436    switch (find_loader(self, fullname, &namespace_portion)) {
437    case FL_ERROR:
438        return NULL;
439    case FL_NOT_FOUND:        /* Not found, return (None, []) */
440        result = Py_BuildValue("O[]", Py_None);
441        break;
442    case FL_MODULE_FOUND:     /* Return (self, []) */
443        result = Py_BuildValue("O[]", self);
444        break;
445    case FL_NS_FOUND:         /* Return (None, [namespace_portion]) */
446        result = Py_BuildValue("O[O]", Py_None, namespace_portion);
447        Py_DECREF(namespace_portion);
448        return result;
449    default:
450        PyErr_BadInternalCall();
451        return NULL;
452    }
453    return result;
454}
455
456/* Load and return the module named by 'fullname'. */
457static PyObject *
458zipimporter_load_module(PyObject *obj, PyObject *args)
459{
460    ZipImporter *self = (ZipImporter *)obj;
461    PyObject *code = NULL, *mod, *dict;
462    PyObject *fullname;
463    PyObject *modpath = NULL;
464    int ispackage;
465
466    if (!PyArg_ParseTuple(args, "U:zipimporter.load_module",
467                          &fullname))
468        return NULL;
469    if (PyUnicode_READY(fullname) == -1)
470        return NULL;
471
472    code = get_module_code(self, fullname, &ispackage, &modpath);
473    if (code == NULL)
474        goto error;
475
476    mod = PyImport_AddModuleObject(fullname);
477    if (mod == NULL)
478        goto error;
479    dict = PyModule_GetDict(mod);
480
481    /* mod.__loader__ = self */
482    if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
483        goto error;
484
485    if (ispackage) {
486        /* add __path__ to the module *before* the code gets
487           executed */
488        PyObject *pkgpath, *fullpath, *subname;
489        int err;
490
491        subname = get_subname(fullname);
492        if (subname == NULL)
493            goto error;
494
495        fullpath = PyUnicode_FromFormat("%U%c%U%U",
496                                self->archive, SEP,
497                                self->prefix, subname);
498        Py_DECREF(subname);
499        if (fullpath == NULL)
500            goto error;
501
502        pkgpath = Py_BuildValue("[N]", fullpath);
503        if (pkgpath == NULL)
504            goto error;
505        err = PyDict_SetItemString(dict, "__path__", pkgpath);
506        Py_DECREF(pkgpath);
507        if (err != 0)
508            goto error;
509    }
510    mod = PyImport_ExecCodeModuleObject(fullname, code, modpath, NULL);
511    Py_CLEAR(code);
512    if (mod == NULL)
513        goto error;
514
515    if (Py_VerboseFlag)
516        PySys_FormatStderr("import %U # loaded from Zip %U\n",
517                           fullname, modpath);
518    Py_DECREF(modpath);
519    return mod;
520error:
521    Py_XDECREF(code);
522    Py_XDECREF(modpath);
523    return NULL;
524}
525
526/* Return a string matching __file__ for the named module */
527static PyObject *
528zipimporter_get_filename(PyObject *obj, PyObject *args)
529{
530    ZipImporter *self = (ZipImporter *)obj;
531    PyObject *fullname, *code, *modpath;
532    int ispackage;
533
534    if (!PyArg_ParseTuple(args, "U:zipimporter.get_filename",
535                          &fullname))
536        return NULL;
537
538    /* Deciding the filename requires working out where the code
539       would come from if the module was actually loaded */
540    code = get_module_code(self, fullname, &ispackage, &modpath);
541    if (code == NULL)
542        return NULL;
543    Py_DECREF(code); /* Only need the path info */
544
545    return modpath;
546}
547
548/* Return a bool signifying whether the module is a package or not. */
549static PyObject *
550zipimporter_is_package(PyObject *obj, PyObject *args)
551{
552    ZipImporter *self = (ZipImporter *)obj;
553    PyObject *fullname;
554    enum zi_module_info mi;
555
556    if (!PyArg_ParseTuple(args, "U:zipimporter.is_package",
557                          &fullname))
558        return NULL;
559
560    mi = get_module_info(self, fullname);
561    if (mi == MI_ERROR)
562        return NULL;
563    if (mi == MI_NOT_FOUND) {
564        PyErr_Format(ZipImportError, "can't find module %R", fullname);
565        return NULL;
566    }
567    return PyBool_FromLong(mi == MI_PACKAGE);
568}
569
570
571static PyObject *
572zipimporter_get_data(PyObject *obj, PyObject *args)
573{
574    ZipImporter *self = (ZipImporter *)obj;
575    PyObject *path, *key;
576    PyObject *toc_entry;
577    Py_ssize_t path_start, path_len, len;
578
579    if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path))
580        return NULL;
581
582#ifdef ALTSEP
583    path = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
584    if (!path)
585        return NULL;
586#else
587    Py_INCREF(path);
588#endif
589    if (PyUnicode_READY(path) == -1)
590        goto error;
591
592    path_len = PyUnicode_GET_LENGTH(path);
593
594    len = PyUnicode_GET_LENGTH(self->archive);
595    path_start = 0;
596    if (PyUnicode_Tailmatch(path, self->archive, 0, len, -1)
597        && PyUnicode_READ_CHAR(path, len) == SEP) {
598        path_start = len + 1;
599    }
600
601    key = PyUnicode_Substring(path, path_start, path_len);
602    if (key == NULL)
603        goto error;
604    toc_entry = PyDict_GetItem(self->files, key);
605    if (toc_entry == NULL) {
606        PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key);
607        Py_DECREF(key);
608        goto error;
609    }
610    Py_DECREF(key);
611    Py_DECREF(path);
612    return get_data(self->archive, toc_entry);
613  error:
614    Py_DECREF(path);
615    return NULL;
616}
617
618static PyObject *
619zipimporter_get_code(PyObject *obj, PyObject *args)
620{
621    ZipImporter *self = (ZipImporter *)obj;
622    PyObject *fullname;
623
624    if (!PyArg_ParseTuple(args, "U:zipimporter.get_code", &fullname))
625        return NULL;
626
627    return get_module_code(self, fullname, NULL, NULL);
628}
629
630static PyObject *
631zipimporter_get_source(PyObject *obj, PyObject *args)
632{
633    ZipImporter *self = (ZipImporter *)obj;
634    PyObject *toc_entry;
635    PyObject *fullname, *subname, *path, *fullpath;
636    enum zi_module_info mi;
637
638    if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname))
639        return NULL;
640
641    mi = get_module_info(self, fullname);
642    if (mi == MI_ERROR)
643        return NULL;
644    if (mi == MI_NOT_FOUND) {
645        PyErr_Format(ZipImportError, "can't find module %R", fullname);
646        return NULL;
647    }
648
649    subname = get_subname(fullname);
650    if (subname == NULL)
651        return NULL;
652
653    path = make_filename(self->prefix, subname);
654    Py_DECREF(subname);
655    if (path == NULL)
656        return NULL;
657
658    if (mi == MI_PACKAGE)
659        fullpath = PyUnicode_FromFormat("%U%c__init__.py", path, SEP);
660    else
661        fullpath = PyUnicode_FromFormat("%U.py", path);
662    Py_DECREF(path);
663    if (fullpath == NULL)
664        return NULL;
665
666    toc_entry = PyDict_GetItem(self->files, fullpath);
667    Py_DECREF(fullpath);
668    if (toc_entry != NULL) {
669        PyObject *res, *bytes;
670        bytes = get_data(self->archive, toc_entry);
671        if (bytes == NULL)
672            return NULL;
673        res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes),
674                                          PyBytes_GET_SIZE(bytes));
675        Py_DECREF(bytes);
676        return res;
677    }
678
679    /* we have the module, but no source */
680    Py_INCREF(Py_None);
681    return Py_None;
682}
683
684PyDoc_STRVAR(doc_find_module,
685"find_module(fullname, path=None) -> self or None.\n\
686\n\
687Search for a module specified by 'fullname'. 'fullname' must be the\n\
688fully qualified (dotted) module name. It returns the zipimporter\n\
689instance itself if the module was found, or None if it wasn't.\n\
690The optional 'path' argument is ignored -- it's there for compatibility\n\
691with the importer protocol.");
692
693PyDoc_STRVAR(doc_find_loader,
694"find_loader(fullname, path=None) -> self, str or None.\n\
695\n\
696Search for a module specified by 'fullname'. 'fullname' must be the\n\
697fully qualified (dotted) module name. It returns the zipimporter\n\
698instance itself if the module was found, a string containing the\n\
699full path name if it's possibly a portion of a namespace package,\n\
700or None otherwise. The optional 'path' argument is ignored -- it's\n\
701 there for compatibility with the importer protocol.");
702
703PyDoc_STRVAR(doc_load_module,
704"load_module(fullname) -> module.\n\
705\n\
706Load the module specified by 'fullname'. 'fullname' must be the\n\
707fully qualified (dotted) module name. It returns the imported\n\
708module, or raises ZipImportError if it wasn't found.");
709
710PyDoc_STRVAR(doc_get_data,
711"get_data(pathname) -> string with file data.\n\
712\n\
713Return the data associated with 'pathname'. Raise IOError if\n\
714the file wasn't found.");
715
716PyDoc_STRVAR(doc_is_package,
717"is_package(fullname) -> bool.\n\
718\n\
719Return True if the module specified by fullname is a package.\n\
720Raise ZipImportError if the module couldn't be found.");
721
722PyDoc_STRVAR(doc_get_code,
723"get_code(fullname) -> code object.\n\
724\n\
725Return the code object for the specified module. Raise ZipImportError\n\
726if the module couldn't be found.");
727
728PyDoc_STRVAR(doc_get_source,
729"get_source(fullname) -> source string.\n\
730\n\
731Return the source code for the specified module. Raise ZipImportError\n\
732if the module couldn't be found, return None if the archive does\n\
733contain the module, but has no source for it.");
734
735
736PyDoc_STRVAR(doc_get_filename,
737"get_filename(fullname) -> filename string.\n\
738\n\
739Return the filename for the specified module.");
740
741static PyMethodDef zipimporter_methods[] = {
742    {"find_module", zipimporter_find_module, METH_VARARGS,
743     doc_find_module},
744    {"find_loader", zipimporter_find_loader, METH_VARARGS,
745     doc_find_loader},
746    {"load_module", zipimporter_load_module, METH_VARARGS,
747     doc_load_module},
748    {"get_data", zipimporter_get_data, METH_VARARGS,
749     doc_get_data},
750    {"get_code", zipimporter_get_code, METH_VARARGS,
751     doc_get_code},
752    {"get_source", zipimporter_get_source, METH_VARARGS,
753     doc_get_source},
754    {"get_filename", zipimporter_get_filename, METH_VARARGS,
755     doc_get_filename},
756    {"is_package", zipimporter_is_package, METH_VARARGS,
757     doc_is_package},
758    {NULL,              NULL}   /* sentinel */
759};
760
761static PyMemberDef zipimporter_members[] = {
762    {"archive",  T_OBJECT, offsetof(ZipImporter, archive),  READONLY},
763    {"prefix",   T_OBJECT, offsetof(ZipImporter, prefix),   READONLY},
764    {"_files",   T_OBJECT, offsetof(ZipImporter, files),    READONLY},
765    {NULL}
766};
767
768PyDoc_STRVAR(zipimporter_doc,
769"zipimporter(archivepath) -> zipimporter object\n\
770\n\
771Create a new zipimporter instance. 'archivepath' must be a path to\n\
772a zipfile, or to a specific path inside a zipfile. For example, it can be\n\
773'/tmp/myimport.zip', or '/tmp/myimport.zip/mydirectory', if mydirectory is a\n\
774valid directory inside the archive.\n\
775\n\
776'ZipImportError is raised if 'archivepath' doesn't point to a valid Zip\n\
777archive.\n\
778\n\
779The 'archive' attribute of zipimporter objects contains the name of the\n\
780zipfile targeted.");
781
782#define DEFERRED_ADDRESS(ADDR) 0
783
784static PyTypeObject ZipImporter_Type = {
785    PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
786    "zipimport.zipimporter",
787    sizeof(ZipImporter),
788    0,                                          /* tp_itemsize */
789    (destructor)zipimporter_dealloc,            /* tp_dealloc */
790    0,                                          /* tp_print */
791    0,                                          /* tp_getattr */
792    0,                                          /* tp_setattr */
793    0,                                          /* tp_reserved */
794    (reprfunc)zipimporter_repr,                 /* tp_repr */
795    0,                                          /* tp_as_number */
796    0,                                          /* tp_as_sequence */
797    0,                                          /* tp_as_mapping */
798    0,                                          /* tp_hash */
799    0,                                          /* tp_call */
800    0,                                          /* tp_str */
801    PyObject_GenericGetAttr,                    /* tp_getattro */
802    0,                                          /* tp_setattro */
803    0,                                          /* tp_as_buffer */
804    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
805        Py_TPFLAGS_HAVE_GC,                     /* tp_flags */
806    zipimporter_doc,                            /* tp_doc */
807    zipimporter_traverse,                       /* tp_traverse */
808    0,                                          /* tp_clear */
809    0,                                          /* tp_richcompare */
810    0,                                          /* tp_weaklistoffset */
811    0,                                          /* tp_iter */
812    0,                                          /* tp_iternext */
813    zipimporter_methods,                        /* tp_methods */
814    zipimporter_members,                        /* tp_members */
815    0,                                          /* tp_getset */
816    0,                                          /* tp_base */
817    0,                                          /* tp_dict */
818    0,                                          /* tp_descr_get */
819    0,                                          /* tp_descr_set */
820    0,                                          /* tp_dictoffset */
821    (initproc)zipimporter_init,                 /* tp_init */
822    PyType_GenericAlloc,                        /* tp_alloc */
823    PyType_GenericNew,                          /* tp_new */
824    PyObject_GC_Del,                            /* tp_free */
825};
826
827
828/* implementation */
829
830/* Given a buffer, return the unsigned int that is represented by the first
831   4 bytes, encoded as little endian. This partially reimplements
832   marshal.c:r_long() */
833static unsigned int
834get_uint32(const unsigned char *buf)
835{
836    unsigned int x;
837    x =  buf[0];
838    x |= (unsigned int)buf[1] <<  8;
839    x |= (unsigned int)buf[2] << 16;
840    x |= (unsigned int)buf[3] << 24;
841    return x;
842}
843
844/* Given a buffer, return the unsigned int that is represented by the first
845   2 bytes, encoded as little endian. This partially reimplements
846   marshal.c:r_short() */
847static unsigned short
848get_uint16(const unsigned char *buf)
849{
850    unsigned short x;
851    x =  buf[0];
852    x |= (unsigned short)buf[1] <<  8;
853    return x;
854}
855
856static void
857set_file_error(PyObject *archive, int eof)
858{
859    if (eof) {
860        PyErr_SetString(PyExc_EOFError, "EOF read where not expected");
861    }
862    else {
863        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, archive);
864    }
865}
866
867/*
868   read_directory(archive) -> files dict (new reference)
869
870   Given a path to a Zip archive, build a dict, mapping file names
871   (local to the archive, using SEP as a separator) to toc entries.
872
873   A toc_entry is a tuple:
874
875   (__file__,      # value to use for __file__, available for all files,
876                   # encoded to the filesystem encoding
877    compress,      # compression kind; 0 for uncompressed
878    data_size,     # size of compressed data on disk
879    file_size,     # size of decompressed data
880    file_offset,   # offset of file header from start of archive
881    time,          # mod time of file (in dos format)
882    date,          # mod data of file (in dos format)
883    crc,           # crc checksum of the data
884   )
885
886   Directories can be recognized by the trailing SEP in the name,
887   data_size and file_offset are 0.
888*/
889static PyObject *
890read_directory(PyObject *archive)
891{
892    PyObject *files = NULL;
893    FILE *fp;
894    unsigned short flags, compress, time, date, name_size;
895    unsigned int crc, data_size, file_size, header_size, header_offset;
896    unsigned long file_offset, header_position;
897    unsigned long arc_offset;  /* Absolute offset to start of the zip-archive. */
898    unsigned int count, i;
899    unsigned char buffer[46];
900    char name[MAXPATHLEN + 5];
901    PyObject *nameobj = NULL;
902    PyObject *path;
903    const char *charset;
904    int bootstrap;
905    const char *errmsg = NULL;
906
907    fp = _Py_fopen_obj(archive, "rb");
908    if (fp == NULL) {
909        if (PyErr_ExceptionMatches(PyExc_OSError)) {
910            _PyErr_FormatFromCause(ZipImportError,
911                                   "can't open Zip file: %R", archive);
912        }
913        return NULL;
914    }
915
916    if (fseek(fp, -22, SEEK_END) == -1) {
917        goto file_error;
918    }
919    header_position = (unsigned long)ftell(fp);
920    if (header_position == (unsigned long)-1) {
921        goto file_error;
922    }
923    assert(header_position <= (unsigned long)LONG_MAX);
924    if (fread(buffer, 1, 22, fp) != 22) {
925        goto file_error;
926    }
927    if (get_uint32(buffer) != 0x06054B50u) {
928        /* Bad: End of Central Dir signature */
929        errmsg = "not a Zip file";
930        goto invalid_header;
931    }
932
933    header_size = get_uint32(buffer + 12);
934    header_offset = get_uint32(buffer + 16);
935    if (header_position < header_size) {
936        errmsg = "bad central directory size";
937        goto invalid_header;
938    }
939    if (header_position < header_offset) {
940        errmsg = "bad central directory offset";
941        goto invalid_header;
942    }
943    if (header_position - header_size < header_offset) {
944        errmsg = "bad central directory size or offset";
945        goto invalid_header;
946    }
947    header_position -= header_size;
948    arc_offset = header_position - header_offset;
949
950    files = PyDict_New();
951    if (files == NULL) {
952        goto error;
953    }
954    /* Start of Central Directory */
955    count = 0;
956    if (fseek(fp, (long)header_position, 0) == -1) {
957        goto file_error;
958    }
959    for (;;) {
960        PyObject *t;
961        size_t n;
962        int err;
963
964        n = fread(buffer, 1, 46, fp);
965        if (n < 4) {
966            goto eof_error;
967        }
968        /* Start of file header */
969        if (get_uint32(buffer) != 0x02014B50u) {
970            break;              /* Bad: Central Dir File Header */
971        }
972        if (n != 46) {
973            goto eof_error;
974        }
975        flags = get_uint16(buffer + 8);
976        compress = get_uint16(buffer + 10);
977        time = get_uint16(buffer + 12);
978        date = get_uint16(buffer + 14);
979        crc = get_uint32(buffer + 16);
980        data_size = get_uint32(buffer + 20);
981        file_size = get_uint32(buffer + 24);
982        name_size = get_uint16(buffer + 28);
983        header_size = (unsigned int)name_size +
984           get_uint16(buffer + 30) /* extra field */ +
985           get_uint16(buffer + 32) /* comment */;
986
987        file_offset = get_uint32(buffer + 42);
988        if (file_offset > header_offset) {
989            errmsg = "bad local header offset";
990            goto invalid_header;
991        }
992        file_offset += arc_offset;
993
994        if (name_size > MAXPATHLEN) {
995            name_size = MAXPATHLEN;
996        }
997        if (fread(name, 1, name_size, fp) != name_size) {
998            goto file_error;
999        }
1000        name[name_size] = '\0';  /* Add terminating null byte */
1001        if (SEP != '/') {
1002            for (i = 0; i < name_size; i++) {
1003                if (name[i] == '/') {
1004                    name[i] = SEP;
1005                }
1006            }
1007        }
1008        /* Skip the rest of the header.
1009         * On Windows, calling fseek to skip over the fields we don't use is
1010         * slower than reading the data because fseek flushes stdio's
1011         * internal buffers.  See issue #8745. */
1012        assert(header_size <= 3*0xFFFFu);
1013        for (i = name_size; i < header_size; i++) {
1014            if (getc(fp) == EOF) {
1015                goto file_error;
1016            }
1017        }
1018
1019        bootstrap = 0;
1020        if (flags & 0x0800) {
1021            charset = "utf-8";
1022        }
1023        else if (!PyThreadState_GET()->interp->codecs_initialized) {
1024            /* During bootstrap, we may need to load the encodings
1025               package from a ZIP file. But the cp437 encoding is implemented
1026               in Python in the encodings package.
1027
1028               Break out of this dependency by assuming that the path to
1029               the encodings module is ASCII-only. */
1030            charset = "ascii";
1031            bootstrap = 1;
1032        }
1033        else {
1034            charset = "cp437";
1035        }
1036        nameobj = PyUnicode_Decode(name, name_size, charset, NULL);
1037        if (nameobj == NULL) {
1038            if (bootstrap) {
1039                PyErr_Format(PyExc_NotImplementedError,
1040                    "bootstrap issue: python%i%i.zip contains non-ASCII "
1041                    "filenames without the unicode flag",
1042                    PY_MAJOR_VERSION, PY_MINOR_VERSION);
1043            }
1044            goto error;
1045        }
1046        if (PyUnicode_READY(nameobj) == -1) {
1047            goto error;
1048        }
1049        path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
1050        if (path == NULL) {
1051            goto error;
1052        }
1053        t = Py_BuildValue("NHIIkHHI", path, compress, data_size,
1054                          file_size, file_offset, time, date, crc);
1055        if (t == NULL) {
1056            goto error;
1057        }
1058        err = PyDict_SetItem(files, nameobj, t);
1059        Py_CLEAR(nameobj);
1060        Py_DECREF(t);
1061        if (err != 0) {
1062            goto error;
1063        }
1064        count++;
1065    }
1066    fclose(fp);
1067    if (Py_VerboseFlag) {
1068        PySys_FormatStderr("# zipimport: found %u names in %R\n",
1069                           count, archive);
1070    }
1071    return files;
1072
1073eof_error:
1074    set_file_error(archive, !ferror(fp));
1075    goto error;
1076
1077file_error:
1078    PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
1079    goto error;
1080
1081invalid_header:
1082    assert(errmsg != NULL);
1083    PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
1084    goto error;
1085
1086error:
1087    fclose(fp);
1088    Py_XDECREF(files);
1089    Py_XDECREF(nameobj);
1090    return NULL;
1091}
1092
1093/* Return the zlib.decompress function object, or NULL if zlib couldn't
1094   be imported. The function is cached when found, so subsequent calls
1095   don't import zlib again. */
1096static PyObject *
1097get_decompress_func(void)
1098{
1099    static int importing_zlib = 0;
1100    PyObject *zlib;
1101    PyObject *decompress;
1102    _Py_IDENTIFIER(decompress);
1103
1104    if (importing_zlib != 0)
1105        /* Someone has a zlib.py[co] in their Zip file;
1106           let's avoid a stack overflow. */
1107        return NULL;
1108    importing_zlib = 1;
1109    zlib = PyImport_ImportModuleNoBlock("zlib");
1110    importing_zlib = 0;
1111    if (zlib != NULL) {
1112        decompress = _PyObject_GetAttrId(zlib,
1113                                         &PyId_decompress);
1114        Py_DECREF(zlib);
1115    }
1116    else {
1117        PyErr_Clear();
1118        decompress = NULL;
1119    }
1120    if (Py_VerboseFlag)
1121        PySys_WriteStderr("# zipimport: zlib %s\n",
1122            zlib != NULL ? "available": "UNAVAILABLE");
1123    return decompress;
1124}
1125
1126/* Given a path to a Zip file and a toc_entry, return the (uncompressed)
1127   data as a new reference. */
1128static PyObject *
1129get_data(PyObject *archive, PyObject *toc_entry)
1130{
1131    PyObject *raw_data = NULL, *data, *decompress;
1132    char *buf;
1133    FILE *fp;
1134    PyObject *datapath;
1135    unsigned short compress, time, date;
1136    unsigned int crc;
1137    Py_ssize_t data_size, file_size, bytes_size;
1138    long file_offset, header_size;
1139    unsigned char buffer[30];
1140    const char *errmsg = NULL;
1141
1142    if (!PyArg_ParseTuple(toc_entry, "OHnnlHHI", &datapath, &compress,
1143                          &data_size, &file_size, &file_offset, &time,
1144                          &date, &crc)) {
1145        return NULL;
1146    }
1147    if (data_size < 0) {
1148        PyErr_Format(ZipImportError, "negative data size");
1149        return NULL;
1150    }
1151
1152    fp = _Py_fopen_obj(archive, "rb");
1153    if (!fp) {
1154        return NULL;
1155    }
1156    /* Check to make sure the local file header is correct */
1157    if (fseek(fp, file_offset, 0) == -1) {
1158        goto file_error;
1159    }
1160    if (fread(buffer, 1, 30, fp) != 30) {
1161        goto eof_error;
1162    }
1163    if (get_uint32(buffer) != 0x04034B50u) {
1164        /* Bad: Local File Header */
1165        errmsg = "bad local file header";
1166        goto invalid_header;
1167    }
1168
1169    header_size = (unsigned int)30 +
1170        get_uint16(buffer + 26) /* file name */ +
1171        get_uint16(buffer + 28) /* extra field */;
1172    if (file_offset > LONG_MAX - header_size) {
1173        errmsg = "bad local file header size";
1174        goto invalid_header;
1175    }
1176    file_offset += header_size;  /* Start of file data */
1177
1178    if (data_size > LONG_MAX - 1) {
1179        fclose(fp);
1180        PyErr_NoMemory();
1181        return NULL;
1182    }
1183    bytes_size = compress == 0 ? data_size : data_size + 1;
1184    if (bytes_size == 0) {
1185        bytes_size++;
1186    }
1187    raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);
1188    if (raw_data == NULL) {
1189        goto error;
1190    }
1191    buf = PyBytes_AsString(raw_data);
1192
1193    if (fseek(fp, file_offset, 0) == -1) {
1194        goto file_error;
1195    }
1196    if (fread(buf, 1, data_size, fp) != (size_t)data_size) {
1197        PyErr_SetString(PyExc_IOError,
1198                        "zipimport: can't read data");
1199        goto error;
1200    }
1201
1202    fclose(fp);
1203    fp = NULL;
1204
1205    if (compress != 0) {
1206        buf[data_size] = 'Z';  /* saw this in zipfile.py */
1207        data_size++;
1208    }
1209    buf[data_size] = '\0';
1210
1211    if (compress == 0) {  /* data is not compressed */
1212        data = PyBytes_FromStringAndSize(buf, data_size);
1213        Py_DECREF(raw_data);
1214        return data;
1215    }
1216
1217    /* Decompress with zlib */
1218    decompress = get_decompress_func();
1219    if (decompress == NULL) {
1220        PyErr_SetString(ZipImportError,
1221                        "can't decompress data; "
1222                        "zlib not available");
1223        goto error;
1224    }
1225    data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
1226    Py_DECREF(decompress);
1227    Py_DECREF(raw_data);
1228    return data;
1229
1230eof_error:
1231    set_file_error(archive, !ferror(fp));
1232    goto error;
1233
1234file_error:
1235    PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
1236    goto error;
1237
1238invalid_header:
1239    assert(errmsg != NULL);
1240    PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
1241    goto error;
1242
1243error:
1244    if (fp != NULL) {
1245        fclose(fp);
1246    }
1247    Py_XDECREF(raw_data);
1248    return NULL;
1249}
1250
1251/* Lenient date/time comparison function. The precision of the mtime
1252   in the archive is lower than the mtime stored in a .pyc: we
1253   must allow a difference of at most one second. */
1254static int
1255eq_mtime(time_t t1, time_t t2)
1256{
1257    time_t d = t1 - t2;
1258    if (d < 0)
1259        d = -d;
1260    /* dostime only stores even seconds, so be lenient */
1261    return d <= 1;
1262}
1263
1264/* Given the contents of a .py[co] file in a buffer, unmarshal the data
1265   and return the code object. Return None if it the magic word doesn't
1266   match (we do this instead of raising an exception as we fall back
1267   to .py if available and we don't want to mask other errors).
1268   Returns a new reference. */
1269static PyObject *
1270unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
1271{
1272    PyObject *code;
1273    unsigned char *buf = (unsigned char *)PyBytes_AsString(data);
1274    Py_ssize_t size = PyBytes_Size(data);
1275
1276    if (size < 12) {
1277        PyErr_SetString(ZipImportError,
1278                        "bad pyc data");
1279        return NULL;
1280    }
1281
1282    if (get_uint32(buf) != (unsigned int)PyImport_GetMagicNumber()) {
1283        if (Py_VerboseFlag) {
1284            PySys_FormatStderr("# %R has bad magic\n",
1285                               pathname);
1286        }
1287        Py_INCREF(Py_None);
1288        return Py_None;  /* signal caller to try alternative */
1289    }
1290
1291    if (mtime != 0 && !eq_mtime(get_uint32(buf + 4), mtime)) {
1292        if (Py_VerboseFlag) {
1293            PySys_FormatStderr("# %R has bad mtime\n",
1294                               pathname);
1295        }
1296        Py_INCREF(Py_None);
1297        return Py_None;  /* signal caller to try alternative */
1298    }
1299
1300    /* XXX the pyc's size field is ignored; timestamp collisions are probably
1301       unimportant with zip files. */
1302    code = PyMarshal_ReadObjectFromString((char *)buf + 12, size - 12);
1303    if (code == NULL) {
1304        return NULL;
1305    }
1306    if (!PyCode_Check(code)) {
1307        Py_DECREF(code);
1308        PyErr_Format(PyExc_TypeError,
1309             "compiled module %R is not a code object",
1310             pathname);
1311        return NULL;
1312    }
1313    return code;
1314}
1315
1316/* Replace any occurrences of "\r\n?" in the input string with "\n".
1317   This converts DOS and Mac line endings to Unix line endings.
1318   Also append a trailing "\n" to be compatible with
1319   PyParser_SimpleParseFile(). Returns a new reference. */
1320static PyObject *
1321normalize_line_endings(PyObject *source)
1322{
1323    char *buf, *q, *p;
1324    PyObject *fixed_source;
1325    int len = 0;
1326
1327    p = PyBytes_AsString(source);
1328    if (p == NULL) {
1329        return PyBytes_FromStringAndSize("\n\0", 2);
1330    }
1331
1332    /* one char extra for trailing \n and one for terminating \0 */
1333    buf = (char *)PyMem_Malloc(PyBytes_Size(source) + 2);
1334    if (buf == NULL) {
1335        PyErr_SetString(PyExc_MemoryError,
1336                        "zipimport: no memory to allocate "
1337                        "source buffer");
1338        return NULL;
1339    }
1340    /* replace "\r\n?" by "\n" */
1341    for (q = buf; *p != '\0'; p++) {
1342        if (*p == '\r') {
1343            *q++ = '\n';
1344            if (*(p + 1) == '\n')
1345                p++;
1346        }
1347        else
1348            *q++ = *p;
1349        len++;
1350    }
1351    *q++ = '\n';  /* add trailing \n */
1352    *q = '\0';
1353    fixed_source = PyBytes_FromStringAndSize(buf, len + 2);
1354    PyMem_Free(buf);
1355    return fixed_source;
1356}
1357
1358/* Given a string buffer containing Python source code, compile it
1359   and return a code object as a new reference. */
1360static PyObject *
1361compile_source(PyObject *pathname, PyObject *source)
1362{
1363    PyObject *code, *fixed_source;
1364
1365    fixed_source = normalize_line_endings(source);
1366    if (fixed_source == NULL) {
1367        return NULL;
1368    }
1369
1370    code = Py_CompileStringObject(PyBytes_AsString(fixed_source),
1371                                  pathname, Py_file_input, NULL, -1);
1372
1373    Py_DECREF(fixed_source);
1374    return code;
1375}
1376
1377/* Convert the date/time values found in the Zip archive to a value
1378   that's compatible with the time stamp stored in .pyc files. */
1379static time_t
1380parse_dostime(int dostime, int dosdate)
1381{
1382    struct tm stm;
1383
1384    memset((void *) &stm, '\0', sizeof(stm));
1385
1386    stm.tm_sec   =  (dostime        & 0x1f) * 2;
1387    stm.tm_min   =  (dostime >> 5)  & 0x3f;
1388    stm.tm_hour  =  (dostime >> 11) & 0x1f;
1389    stm.tm_mday  =   dosdate        & 0x1f;
1390    stm.tm_mon   = ((dosdate >> 5)  & 0x0f) - 1;
1391    stm.tm_year  = ((dosdate >> 9)  & 0x7f) + 80;
1392    stm.tm_isdst =   -1; /* wday/yday is ignored */
1393
1394    return mktime(&stm);
1395}
1396
1397/* Given a path to a .pyc file in the archive, return the
1398   modification time of the matching .py file, or 0 if no source
1399   is available. */
1400static time_t
1401get_mtime_of_source(ZipImporter *self, PyObject *path)
1402{
1403    PyObject *toc_entry, *stripped;
1404    time_t mtime;
1405
1406    /* strip 'c' or 'o' from *.py[co] */
1407    if (PyUnicode_READY(path) == -1)
1408        return (time_t)-1;
1409    stripped = PyUnicode_FromKindAndData(PyUnicode_KIND(path),
1410                                         PyUnicode_DATA(path),
1411                                         PyUnicode_GET_LENGTH(path) - 1);
1412    if (stripped == NULL)
1413        return (time_t)-1;
1414
1415    toc_entry = PyDict_GetItem(self->files, stripped);
1416    Py_DECREF(stripped);
1417    if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1418        PyTuple_Size(toc_entry) == 8) {
1419        /* fetch the time stamp of the .py file for comparison
1420           with an embedded pyc time stamp */
1421        int time, date;
1422        time = PyLong_AsLong(PyTuple_GetItem(toc_entry, 5));
1423        date = PyLong_AsLong(PyTuple_GetItem(toc_entry, 6));
1424        mtime = parse_dostime(time, date);
1425    } else
1426        mtime = 0;
1427    return mtime;
1428}
1429
1430/* Return the code object for the module named by 'fullname' from the
1431   Zip archive as a new reference. */
1432static PyObject *
1433get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
1434                   time_t mtime, PyObject *toc_entry)
1435{
1436    PyObject *data, *modpath, *code;
1437
1438    data = get_data(self->archive, toc_entry);
1439    if (data == NULL)
1440        return NULL;
1441
1442    modpath = PyTuple_GetItem(toc_entry, 0);
1443    if (isbytecode)
1444        code = unmarshal_code(modpath, data, mtime);
1445    else
1446        code = compile_source(modpath, data);
1447    Py_DECREF(data);
1448    return code;
1449}
1450
1451/* Get the code object associated with the module specified by
1452   'fullname'. */
1453static PyObject *
1454get_module_code(ZipImporter *self, PyObject *fullname,
1455                int *p_ispackage, PyObject **p_modpath)
1456{
1457    PyObject *code = NULL, *toc_entry, *subname;
1458    PyObject *path, *fullpath = NULL;
1459    struct st_zip_searchorder *zso;
1460
1461    subname = get_subname(fullname);
1462    if (subname == NULL)
1463        return NULL;
1464
1465    path = make_filename(self->prefix, subname);
1466    Py_DECREF(subname);
1467    if (path == NULL)
1468        return NULL;
1469
1470    for (zso = zip_searchorder; *zso->suffix; zso++) {
1471        code = NULL;
1472
1473        fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix);
1474        if (fullpath == NULL)
1475            goto exit;
1476
1477        if (Py_VerboseFlag > 1)
1478            PySys_FormatStderr("# trying %U%c%U\n",
1479                               self->archive, (int)SEP, fullpath);
1480        toc_entry = PyDict_GetItem(self->files, fullpath);
1481        if (toc_entry != NULL) {
1482            time_t mtime = 0;
1483            int ispackage = zso->type & IS_PACKAGE;
1484            int isbytecode = zso->type & IS_BYTECODE;
1485
1486            if (isbytecode) {
1487                mtime = get_mtime_of_source(self, fullpath);
1488                if (mtime == (time_t)-1 && PyErr_Occurred()) {
1489                    goto exit;
1490                }
1491            }
1492            Py_CLEAR(fullpath);
1493            if (p_ispackage != NULL)
1494                *p_ispackage = ispackage;
1495            code = get_code_from_data(self, ispackage,
1496                                      isbytecode, mtime,
1497                                      toc_entry);
1498            if (code == Py_None) {
1499                /* bad magic number or non-matching mtime
1500                   in byte code, try next */
1501                Py_DECREF(code);
1502                continue;
1503            }
1504            if (code != NULL && p_modpath != NULL) {
1505                *p_modpath = PyTuple_GetItem(toc_entry, 0);
1506                Py_INCREF(*p_modpath);
1507            }
1508            goto exit;
1509        }
1510        else
1511            Py_CLEAR(fullpath);
1512    }
1513    PyErr_Format(ZipImportError, "can't find module %R", fullname);
1514exit:
1515    Py_DECREF(path);
1516    Py_XDECREF(fullpath);
1517    return code;
1518}
1519
1520
1521/* Module init */
1522
1523PyDoc_STRVAR(zipimport_doc,
1524"zipimport provides support for importing Python modules from Zip archives.\n\
1525\n\
1526This module exports three objects:\n\
1527- zipimporter: a class; its constructor takes a path to a Zip archive.\n\
1528- ZipImportError: exception raised by zipimporter objects. It's a\n\
1529  subclass of ImportError, so it can be caught as ImportError, too.\n\
1530- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1531  info dicts, as used in zipimporter._files.\n\
1532\n\
1533It is usually not needed to use the zipimport module explicitly; it is\n\
1534used by the builtin import mechanism for sys.path items that are paths\n\
1535to Zip archives.");
1536
1537static struct PyModuleDef zipimportmodule = {
1538    PyModuleDef_HEAD_INIT,
1539    "zipimport",
1540    zipimport_doc,
1541    -1,
1542    NULL,
1543    NULL,
1544    NULL,
1545    NULL,
1546    NULL
1547};
1548
1549PyMODINIT_FUNC
1550PyInit_zipimport(void)
1551{
1552    PyObject *mod;
1553
1554    if (PyType_Ready(&ZipImporter_Type) < 0)
1555        return NULL;
1556
1557    /* Correct directory separator */
1558    zip_searchorder[0].suffix[0] = SEP;
1559    zip_searchorder[1].suffix[0] = SEP;
1560
1561    mod = PyModule_Create(&zipimportmodule);
1562    if (mod == NULL)
1563        return NULL;
1564
1565    ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1566                                        PyExc_ImportError, NULL);
1567    if (ZipImportError == NULL)
1568        return NULL;
1569
1570    Py_INCREF(ZipImportError);
1571    if (PyModule_AddObject(mod, "ZipImportError",
1572                           ZipImportError) < 0)
1573        return NULL;
1574
1575    Py_INCREF(&ZipImporter_Type);
1576    if (PyModule_AddObject(mod, "zipimporter",
1577                           (PyObject *)&ZipImporter_Type) < 0)
1578        return NULL;
1579
1580    zip_directory_cache = PyDict_New();
1581    if (zip_directory_cache == NULL)
1582        return NULL;
1583    Py_INCREF(zip_directory_cache);
1584    if (PyModule_AddObject(mod, "_zip_directory_cache",
1585                           zip_directory_cache) < 0)
1586        return NULL;
1587    return mod;
1588}
1589