Esempio n. 1
0
/* Open a zip-compatible archive and extract all files
 * into the specified directory (which is assumed to exist)
 */
BOOL
unzip_archive (char *dirname, char *data, DWORD size, NOTIFYPROC notify)
{
    int n;
    char pathname[MAX_PATH];
    char *new_part;

    /* read the end of central directory record */
    struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof
						  (struct eof_cdir)];

    int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir -
	pe->ofsCDir;

    /* set position to start of central directory */
    int pos = arc_start + pe->ofsCDir;

    /* make sure this is a zip file */
    if (pe->tag != 0x06054b50)
	return FALSE;
    
    /* Loop through the central directory, reading all entries */
    for (n = 0; n < pe->nTotalCDir; ++n) {
	char *fname;
	char *pcomp;
	char *dst;
	struct cdir *pcdir = (struct cdir *)&data[pos];
	struct fhdr *pfhdr = (struct fhdr *)&data[pcdir->ofs_local_header +
						 arc_start];

        if (pcdir->tag != 0x02014b50)
	    return FALSE;
	if (pfhdr->tag != 0x04034b50)
	    return FALSE;
	pos += sizeof (struct cdir);
	fname = (char *)&data[pos]; /* This is not null terminated! */
	pos += pcdir->fname_length + pcdir->extra_length +
	    pcdir->comment_length;

	pcomp = &data[pcdir->ofs_local_header
		     + sizeof (struct fhdr)
		     + arc_start
		     + pfhdr->fname_length
		     + pfhdr->extra_length];

	strcpy (pathname, dirname);
	strcat (pathname, "\\");
	new_part = &pathname[lstrlen (pathname)];
	strncat (pathname, fname, pfhdr->fname_length);
	fixpath (pathname);
	if (pathname[strlen(pathname)-1] != '\\') {
	    /*
	     * The local file header (pfhdr) does not always contain
	     * the compressed and uncompressed sizes of the data
	     * depending on bit 3 of the flags field.
	     * So it seems better to use the data from the
	     * central directory (pcdir).
	     */
	    dst = map_new_file (0, pathname, new_part,
				pcdir->uncomp_size,
				pcdir->last_mod_file_date,
				pcdir->last_mod_file_time, notify);
	    if (dst) {
		if (!extract_file (dst, pcomp, pfhdr->method,
				   pcdir->comp_size, pcdir->uncomp_size,
				   notify))
		    return FALSE;
	    } /* else ??? */
	}
	if (notify)
	    notify (NUM_FILES, new_part, (int)pe->nTotalCDir,
		    (int)n+1);
    }
    return TRUE;
}
Esempio n. 2
0
/* Open a zip-compatible archive and extract all files
 * into the specified directory (which is assumed to exist)
 */
BOOL
unzip_archive(SCHEME *scheme, char *dirname, char *data, DWORD size,
              NOTIFYPROC notify)
{
    int n;
    char pathname[MAX_PATH];
    char *new_part;

    /* read the end of central directory record */
    struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof
                                                   (struct eof_cdir)];

    int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir -
        pe->ofsCDir;

    /* set position to start of central directory */
    int pos = arc_start + pe->ofsCDir;

    /* make sure this is a zip file */
    if (pe->tag != 0x06054b50)
        return FALSE;

    /* Loop through the central directory, reading all entries */
    for (n = 0; n < pe->nTotalCDir; ++n) {
        int i;
        char *fname;
        char *pcomp;
        char *dst;
        struct cdir *pcdir;
        struct fhdr *pfhdr;

        pcdir = (struct cdir *)&data[pos];
        pfhdr = (struct fhdr *)&data[pcdir->ofs_local_header +
                                     arc_start];

        if (pcdir->tag != 0x02014b50)
            return FALSE;
        if (pfhdr->tag != 0x04034b50)
            return FALSE;
        pos += sizeof(struct cdir);
        fname = (char *)&data[pos]; /* This is not null terminated! */
        pos += pcdir->fname_length + pcdir->extra_length +
            pcdir->comment_length;

        pcomp = &data[pcdir->ofs_local_header
                      + sizeof(struct fhdr)
                      + arc_start
                      + pfhdr->fname_length
                      + pfhdr->extra_length];

        /* dirname is the Python home directory (prefix) */
        strcpy(pathname, dirname);
        if (pathname[strlen(pathname)-1] != '\\')
            strcat(pathname, "\\");
        new_part = &pathname[lstrlen(pathname)];
        /* we must now match the first part of the pathname
         * in the archive to a component in the installation
         * scheme (PURELIB, PLATLIB, HEADERS, SCRIPTS, or DATA)
         * and replace this part by the one in the scheme to use
         */
        for (i = 0; scheme[i].name; ++i) {
            if (0 == strnicmp(scheme[i].name, fname,
                              strlen(scheme[i].name))) {
                char *rest;
                int len;

                /* length of the replaced part */
                int namelen = strlen(scheme[i].name);

                strcat(pathname, scheme[i].prefix);

                rest = fname + namelen;
                len = pfhdr->fname_length - namelen;

                if ((pathname[strlen(pathname)-1] != '\\')
                    && (pathname[strlen(pathname)-1] != '/'))
                    strcat(pathname, "\\");
                /* Now that pathname ends with a separator,
                 * we must make sure rest does not start with
                 * an additional one.
                 */
                if ((rest[0] == '\\') || (rest[0] == '/')) {
                    ++rest;
                    --len;
                }

                strncat(pathname, rest, len);
                goto Done;
            }
        }
        /* no prefix to replace found, go unchanged */
        strncat(pathname, fname, pfhdr->fname_length);
      Done:
        normpath(pathname);
        if (pathname[strlen(pathname)-1] != '\\') {
            /*
             * The local file header (pfhdr) does not always
             * contain the compressed and uncompressed sizes of
             * the data depending on bit 3 of the flags field.  So
             * it seems better to use the data from the central
             * directory (pcdir).
             */
            dst = map_new_file(0, pathname, new_part,
                               pcdir->uncomp_size,
                               pcdir->last_mod_file_date,
                               pcdir->last_mod_file_time, notify);
            if (dst) {
                if (!extract_file(dst, pcomp, pfhdr->method,
                                  pcdir->comp_size,
                                  pcdir->uncomp_size,
                                  notify))
                    return FALSE;
            } /* else ??? */
        }
        if (notify)
            notify(NUM_FILES, new_part, (int)pe->nTotalCDir,
                   (int)n+1);
    }
    return TRUE;
}