Exemple #1
0
static int ExtractCurrentFile (unzFile uf,
                               void* buffer,
                               const size_t bufferSize,
                               const char* outPath,
                               const bool skipPaths,
                               const bool overwrite,
                               const char* password) {
  char filenameInZip[256];
  char* filenameWithoutPath;
  char* fullPath;
  char* p;
  FILE *fout;
  unz_file_info64 fileInfo;

  if (unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0) != UNZ_OK) {
    return TRI_ERROR_INTERNAL;
  }

  p = filenameWithoutPath = filenameInZip;

  // get the file name without any path prefix
  while (*p != '\0') {
    if (*p == '/' || *p == '\\') {
      filenameWithoutPath = p + 1;
    }

    p++;
  }
  
  // found a directory
  if (*filenameWithoutPath == '\0') {
    if (! skipPaths) {
      fullPath = TRI_Concatenate2File(outPath, filenameInZip);
      TRI_CreateRecursiveDirectory(fullPath);
      TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
    }
  }

  // found a file
  else {
    const char* writeFilename;

    if (! skipPaths) {
      writeFilename = filenameInZip;
    }
    else {
      writeFilename = filenameWithoutPath;
    }

    if (unzOpenCurrentFilePassword(uf, password) != UNZ_OK) {
      return TRI_ERROR_INTERNAL;
    }

    // prefix the name from the zip file with the path specified
    fullPath = TRI_Concatenate2File(outPath, writeFilename);
    
    if (! overwrite && TRI_ExistsFile(fullPath)) {
      return TRI_ERROR_INTERNAL;
    }

    // try to write the outfile
    fout = fopen(fullPath, "wb");

    // cannot write to outfile. this may be due to the target directory missing
    if (fout == NULL && ! skipPaths && filenameWithoutPath != (char*) filenameInZip) {
      char* d;

      char c = *(filenameWithoutPath - 1);
      *(filenameWithoutPath - 1) = '\0';

      // create target directory recursively
      d = TRI_Concatenate2File(outPath, filenameInZip);
      TRI_CreateRecursiveDirectory(d);
      TRI_Free(TRI_CORE_MEM_ZONE, d);

      *(filenameWithoutPath - 1) = c;

      // try again
      fout = fopen(fullPath, "wb");
    }
    
    TRI_Free(TRI_CORE_MEM_ZONE, fullPath);

    if (fout == NULL) {
      return TRI_ERROR_CANNOT_WRITE_FILE;
    }

    while (true) {
      int result = unzReadCurrentFile(uf, buffer, bufferSize);

      if (result < 0) {
        fclose(fout);

        return TRI_ERROR_INTERNAL;
      }

      if (result > 0) {
        if (fwrite(buffer, result, 1, fout) != 1) {
          fclose(fout);

          return TRI_set_errno(TRI_ERROR_SYS_ERROR);
        }
      }
      else {
        assert(result == 0);
        break;
      }
    }

    fclose(fout);
  }

  unzCloseCurrentFile(uf);
  
  return TRI_ERROR_NO_ERROR;
}
Exemple #2
0
static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize,
                              char const* outPath, bool const skipPaths,
                              bool const overwrite, char const* password,
                              std::string& errorMessage) {
  char filenameInZip[256];
  char* filenameWithoutPath;
  char* fullPath;
  char* p;
  unz_file_info64 fileInfo;
  long systemError;
  int err;

  // cppcheck-suppress *
  FILE* fout;

  filenameInZip[0] = '\0';
  err = unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip,
                                sizeof(filenameInZip), NULL, 0, NULL, 0);
  if (err != UNZ_OK) {
    errorMessage = std::string("Failed to get file info for ") + filenameInZip +
                   ": " + std::to_string(err);
    return TRI_ERROR_INTERNAL;
  }

  // adjust file name
  p = filenameInZip;
  while (*p != '\0') {
#ifdef WIN32
    if (*p == '/') {
      *p = '\\';
    }
#else
    if (*p == '\\') {
      *p = '/';
    }
#endif
    ++p;
  }

  p = filenameWithoutPath = filenameInZip;

  // get the file name without any path prefix
  while (*p != '\0') {
    if (*p == '/' || *p == '\\' || *p == ':') {
      filenameWithoutPath = p + 1;
    }

    p++;
  }

  // found a directory
  if (*filenameWithoutPath == '\0') {
    if (!skipPaths) {
      fullPath = TRI_Concatenate2File(outPath, filenameInZip);
      int res =
          TRI_CreateRecursiveDirectory(fullPath, systemError, errorMessage);

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
        return res;
      }

      TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
    }
  }

  // found a file
  else {
    char const* writeFilename;

    if (!skipPaths) {
      writeFilename = filenameInZip;
    } else {
      writeFilename = filenameWithoutPath;
    }

    err = unzOpenCurrentFilePassword(uf, password);
    if (err != UNZ_OK) {
      errorMessage = "failed to authenticate the password in the zip: " +
                     std::to_string(err);
      return TRI_ERROR_INTERNAL;
    }

    // prefix the name from the zip file with the path specified
    fullPath = TRI_Concatenate2File(outPath, writeFilename);

    if (!overwrite && TRI_ExistsFile(fullPath)) {
      TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
      errorMessage = std::string("not allowed to overwrite file ") + fullPath;
      return TRI_ERROR_CANNOT_OVERWRITE_FILE;
    }

    // try to write the outfile
    fout = fopen(fullPath, "wb");

    // cannot write to outfile. this may be due to the target directory missing
    if (fout == nullptr && !skipPaths &&
        filenameWithoutPath != (char*)filenameInZip) {
      char c = *(filenameWithoutPath - 1);
      *(filenameWithoutPath - 1) = '\0';

      // create target directory recursively
      char* d = TRI_Concatenate2File(outPath, filenameInZip);
      int res = TRI_CreateRecursiveDirectory(d, systemError, errorMessage);

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_Free(TRI_CORE_MEM_ZONE, d);
        return res;
      }

      TRI_Free(TRI_CORE_MEM_ZONE, d);

      *(filenameWithoutPath - 1) = c;

      // try again
      fout = fopen(fullPath, "wb");
    } else if (fout == nullptr) {
      // try to create the target directory recursively
      char* d = TRI_Concatenate2File(outPath, filenameInZip);
      // strip filename so we only have the directory name
      char* dir = TRI_Dirname(d);
      int res = TRI_CreateRecursiveDirectory(dir, systemError, errorMessage);

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_Free(TRI_CORE_MEM_ZONE, d);
        TRI_Free(TRI_CORE_MEM_ZONE, dir);
        return res;
      }

      TRI_Free(TRI_CORE_MEM_ZONE, d);
      TRI_Free(TRI_CORE_MEM_ZONE, dir);
      // try again
      fout = fopen(fullPath, "wb");
    }

    if (fout == NULL) {
      errorMessage = std::string("failed to open file for writing: ") +
                     fullPath + " - " + strerror(errno);
      TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
      return TRI_ERROR_CANNOT_WRITE_FILE;
    }

    while (true) {
      int result = unzReadCurrentFile(uf, buffer, (unsigned int)bufferSize);

      if (result < 0) {
        errorMessage = std::string("failed to write file ") + fullPath + " - " +
                       strerror(errno);
        fclose(fout);
        TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
        return TRI_ERROR_CANNOT_WRITE_FILE;
      }

      if (result > 0) {
        if (fwrite(buffer, result, 1, fout) != 1) {
          errorMessage = std::string("failed to write file ") + fullPath +
                         " - " + strerror(errno);
          TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
          fclose(fout);
          return TRI_set_errno(TRI_ERROR_SYS_ERROR);
        }
      } else {
        TRI_ASSERT(result == 0);
        break;
      }
    }
    TRI_Free(TRI_CORE_MEM_ZONE, fullPath);

    fclose(fout);
  }

  unzCloseCurrentFile(uf);

  return TRI_ERROR_NO_ERROR;
}