static int is_valid_extension(char *end, int l, int nameoffset) { int i, len; /* zipcode testing is a special case */ if (l > nameoffset + 2 && is_zipcode_name(end + nameoffset)) return 1; /* others */ for (i = 0; extensions[i]; i++) { len = strlen(extensions[i]); if (l < nameoffset + len) continue; if (!strcasecmp(extensions[i], end + l - len)) return 1; } return 0; }
/* If `name' has a correct extension, try to list its contents and search for the first file with a proper extension; if found, extract it. If this succeeds, return the name of the temporary file; if the archive file is valid but `write_mode' is non-zero, return a zero-length string; in all the other cases, return NULL. */ static char *try_uncompress_archive(const char *name, int write_mode, const char *program, const char *listopts, const char *extractopts, const char *extension, const char *search) { char *tmp_name = NULL; size_t l = strlen(name), len, nameoffset; int found = 0; int exit_status; char *argv[8]; FILE *fd; char tmp[1024]; /* Do we have correct extension? */ len = strlen(extension); if (l <= len || strcasecmp(name + l - len, extension) != 0) { return NULL; } /* First run listing and search for first recognizeable extension. */ argv[0] = lib_stralloc(program); argv[1] = lib_stralloc(listopts); argv[2] = archdep_filename_parameter(name); argv[3] = NULL; ZDEBUG(("try_uncompress_archive: spawning `%s %s %s'", program, listopts, name)); exit_status = archdep_spawn(program, argv, &tmp_name, NULL); lib_free(argv[0]); lib_free(argv[1]); lib_free(argv[2]); /* No luck? */ if (exit_status != 0) { ZDEBUG(("try_uncompress_archive: `%s %s' failed.", program, listopts)); ioutil_remove(tmp_name); lib_free(tmp_name); return NULL; } ZDEBUG(("try_uncompress_archive: `%s %s' successful.", program, listopts)); fd = fopen(tmp_name, MODE_READ); if (!fd) { ZDEBUG(("try_uncompress_archive: cannot read `%s %s' output.", program, tmp_name)); ioutil_remove(tmp_name); lib_free(tmp_name); return NULL; } ZDEBUG(("try_uncompress_archive: searching for the first valid file.")); /* Search for `search' first (if any) to see the offset where filename begins, then search for first recognizeable file. */ nameoffset = search ? -1 : 0; len = search ? strlen(search) : 0; while (!feof(fd) && !found) { if (fgets(tmp, 1024, fd) == NULL) { break; } l = strlen(tmp); while (l > 0) { tmp[--l] = 0; if (((nameoffset < 0) || (nameoffset > 1024)) && l >= len && !strcasecmp(tmp + l - len, search) != 0) { nameoffset = l - 4; } if (nameoffset >= 0 && nameoffset <= 1024 && is_valid_extension(tmp, l, nameoffset)) { ZDEBUG(("try_uncompress_archive: found `%s'.", tmp + nameoffset)); found = 1; break; } } } fclose(fd); ioutil_remove(tmp_name); if (!found) { ZDEBUG(("try_uncompress_archive: no valid file found.")); lib_free(tmp_name); return NULL; } /* This would be a valid ZIP file, but we cannot handle ZIP files in write mode. Return a null temporary file name to report this. */ if (write_mode) { ZDEBUG(("try_uncompress_archive: cannot open file in write mode.")); lib_free(tmp_name); return ""; } /* And then file inside zip. If we have a zipcode extract all of them to the same file. */ argv[0] = lib_stralloc(program); argv[1] = lib_stralloc(extractopts); argv[2] = archdep_filename_parameter(name); if (is_zipcode_name(tmp + nameoffset)) { argv[3] = lib_stralloc(tmp + nameoffset); argv[4] = lib_stralloc(tmp + nameoffset); argv[5] = lib_stralloc(tmp + nameoffset); argv[6] = lib_stralloc(tmp + nameoffset); argv[7] = NULL; argv[3][0] = '1'; argv[4][0] = '2'; argv[5][0] = '3'; argv[6][0] = '4'; } else { argv[3] = archdep_quote_parameter(tmp + nameoffset); argv[4] = NULL; } ZDEBUG(("try_uncompress_archive: spawning `%s %s %s %s'.", program, extractopts, name, tmp + nameoffset)); exit_status = archdep_spawn(program, argv, &tmp_name, NULL); lib_free(argv[0]); lib_free(argv[1]); lib_free(argv[2]); lib_free(argv[3]); if (is_zipcode_name(tmp + nameoffset)) { lib_free(argv[4]); lib_free(argv[5]); lib_free(argv[6]); } if (exit_status != 0) { ZDEBUG(("try_uncompress_archive: `%s %s' failed.", program, extractopts)); ioutil_remove(tmp_name); lib_free(tmp_name); return NULL; } ZDEBUG(("try_uncompress_archive: `%s %s' successful.", program, tmp_name)); return tmp_name; }