ZipEntry *ZipEntry::Create(const wxString &path) { wxFile file(path); int error; auto zipFile = zip_fdopen(file.fd(), ZIP_RDONLY, &error); file.Detach(); if (zipFile == nullptr) { throw error; } auto mutex = new wxMutex(); ZipEntry *root = new ZipEntry(zipFile, mutex, ""); std::vector<wxString> innerPaths; int num_entries = zip_get_num_entries(zipFile, ZIP_FL_UNCHANGED); for (int i = 0; i < num_entries; i++) { auto path = wxString(zip_get_name(zipFile, i, ZIP_FL_UNCHANGED)); innerPaths.push_back(path); } std::sort(innerPaths.begin(), innerPaths.end()); std::map<wxString, ZipEntry *> entryMap; entryMap[""] = root; for (auto &path : innerPaths) { AddChildrenFromPath(zipFile, mutex, entryMap, path); } return root; }
archive_t arch_zip_read(const char* name,int buf){ archive_t arch=(archive_t)HREmalloc(NULL,sizeof(struct archive_s)); arch_init(arch); int err; arch->archive=zip_open(name,ZIP_CHECKCONS,&err); if (arch->archive==NULL){ char errstr[1024]; zip_error_to_str(errstr, sizeof(errstr), err, errno); Abort("cannot open zip archive `%s': %s\n",name , errstr); } arch->stream_index=SIcreate(); #ifdef LIBZIP_VERSION int count=zip_get_num_entries(arch->archive,0); #else int count=zip_get_num_files(arch->archive); #endif for(int i=0;i<count;i++){ struct zip_stat sb; int res=zip_stat_index(arch->archive,i,0,&sb); if (res<0) { Abort("cannot stat zip archive: %s\n",zip_strerror(arch->archive)); } SIputAt(arch->stream_index,sb.name,i); Print(infoShort,"stream %d is %s",i,sb.name); } arch->procs.contains=zip_contains; arch->procs.read=hre_zip_read; arch->procs.read_raw=hre_zip_read_raw; arch->procs.enumerator=zip_enum; arch->procs.close=hre_zip_close; arch->buf=buf; return arch; }
bool get_jar_index( const std::string &jar_file, std::vector<std::string> &entries) { #ifdef HAVE_LIBZIP int zip_error; struct zip *zip=zip_open(jar_file.c_str(), 0, &zip_error); if(zip==NULL) return true; std::size_t number_of_files=zip_get_num_entries(zip, 0); for(std::size_t index=0; index<number_of_files; index++) { std::string file_name=zip_get_name(zip, index, 0); entries.push_back(file_name); } zip_close(zip); return false; #else return true; #endif }
void jar_filet::open(const std::string &filename) { #ifdef HAVE_LIBZIP if(zip!=nullptr) zip_close(static_cast<struct zip *>(zip)); int zip_error; zip=zip_open(filename.c_str(), 0, &zip_error); if(zip!=nullptr) { std::size_t number_of_files= zip_get_num_entries(static_cast<struct zip *>(zip), 0); index.reserve(number_of_files); for(std::size_t i=0; i<number_of_files; i++) { std::string file_name= zip_get_name(static_cast<struct zip *>(zip), i, 0); index.push_back(file_name); } } #else zip=nullptr; #endif }
static void vfs_zipfile_init_pathmap(VFSNode *node) { VFSZipFileData *zdata = node->data1; VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true); zip_int64_t num = zip_get_num_entries(tls->zip, 0); ht_create(&zdata->pathmap); for(zip_int64_t i = 0; i < num; ++i) { const char *original = zip_get_name(tls->zip, i, 0); char normalized[strlen(original) + 1]; vfs_path_normalize(original, normalized); if(*normalized) { char *c = strchr(normalized, 0) - 1; if(*c == '/') { *c = 0; } } if(strcmp(original, normalized)) { ht_set(&zdata->pathmap, normalized, i); } } }
size_t Unzip(const char *dst_path_, const char *archive, const UnzipFileHandler& handler) { struct zip *za; struct zip_file *zf; struct zip_stat sb; char buf[1024]; size_t ret = 0; std::string dst_path = dst_path_; int err; if ((za = zip_open(archive, 0, &err)) == nullptr) { zip_error_to_str(buf, sizeof(buf), err, errno); return false; } for (int i = 0; i < zip_get_num_entries(za, 0); ++i) { if (zip_stat_index(za, i, 0, &sb) == 0) { std::string dstpath = dst_path + '/' + sb.name; if (dstpath.back() == '/') { std::experimental::filesystem::create_directories(dstpath.c_str()); } else { zf = zip_fopen_index(za, i, 0); if (!zf) { goto bail_out; } FILE *of = fopen(dstpath.c_str(), "wb"); if (of == nullptr) { goto bail_out; } size_t sum = 0; while (sum != sb.size) { size_t len = (size_t)zip_fread(zf, buf, sizeof(buf)); if (len < 0) { fclose(of); goto bail_out; } fwrite(buf, 1, len, of); sum += len; } fclose(of); zip_fclose(zf); if (handler) { handler(dstpath.c_str()); } ++ret; } } } if (zip_close(za) == -1) { return false; } return ret; bail_out: zip_close(za); return ret; }
QStringList KaraokePlayable_ZIP::enumerate() { QStringList filelist; // http://www.nih.at/libzip/zip_get_num_entries.html int files = zip_get_num_entries( m_zip, ZIP_FL_UNCHANGED ); if ( files == 0 ) { m_errorMsg = "archive has no files"; return filelist; } for ( int i = 0; i < files; i++ ) { // Retrieve the file size struct zip_stat fileinfo; // http://www.nih.at/libzip/zip_stat_index.html if ( zip_stat_index( m_zip, i, 0, &fileinfo) != 0 ) { m_errorMsg = "file info not found"; return QStringList(); } filelist.push_back( decodeFilename( fileinfo.name ) ); } return filelist; }
void ZipReader::readFileInfo() { zip_int64_t count = zip_get_num_entries(m_archive, 0); for (zip_int64_t i = 0; i < count; ++i) { QString name = QString::fromUtf8(zip_get_name(m_archive, i, 0)); m_files.insert(name, i); } }
bool Upgrader::unzipper(int targetfile) { bfs::path target = path(DATA) / "upgrade"; if (!verifyPath(target.c_str(), true)) {return false;} const char *targetzip = (target / targetswitch(targetfile)).string().c_str(); struct zip *archive; struct zip_file *zipfile; struct zip_stat filestat; char buffer[1024*1024]; FILE *file; int bufferlength, err; unsigned long long sum; printf("Extracting %s\n", targetzip); if ((archive = zip_open(targetzip, 0, &err)) == NULL) { printf("Failed to open archive %s\n", targetzip); return false; } for (unsigned int i = 0; i < zip_get_num_entries(archive, 0); i++) { if (zip_stat_index(archive, i, 0, &filestat) == 0) { verifyPath((target / filestat.name).parent_path(), true); if (!is_directory(target / filestat.name)) { zipfile = zip_fopen_index(archive, i, 0); if (!zipfile) { printf("Could not open %s in archive\n", filestat.name); continue; } file = fopen((target / filestat.name).string().c_str(), "w"); sum = 0; while (sum != filestat.size) { bufferlength = zip_fread(zipfile, buffer, 1024*1024); fwrite(buffer, sizeof(char), bufferlength, file); sum += bufferlength; } printf("Finished extracting %s\n", filestat.name); fclose(file); zip_fclose(zipfile); } } } if (zip_close(archive) == -1) { printf("Can't close zip archive %s\n", targetzip); return false; } bfs::remove(target / targetswitch(targetfile)); return true; }
COpcPackageReader::COpcPackageReader(_In_ PImportStream pImportStream) { if (pImportStream.get() == nullptr) throw CNMRException(NMR_ERROR_INVALIDPARAM); m_ZIPError.str = nullptr; m_ZIPError.sys_err = 0; m_ZIPError.zip_err = 0; m_ZIParchive = nullptr; m_ZIPsource = nullptr; try { // determine stream size nfUint64 nStreamSize = pImportStream->retrieveSize(); pImportStream->seekPosition(0, true); if (nStreamSize == 0) throw CNMRException(NMR_ERROR_COULDNOTGETSTREAMPOSITION); // read ZIP into memory m_Buffer.resize ((size_t) nStreamSize); pImportStream->readBuffer(&m_Buffer[0], nStreamSize, true); // create ZIP objects zip_error_init(&m_ZIPError); m_ZIPsource = zip_source_buffer_create(&m_Buffer[0], (size_t) nStreamSize, 0, &m_ZIPError); if (m_ZIPsource == nullptr) throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE); m_ZIParchive = zip_open_from_source(m_ZIPsource, ZIP_RDONLY | ZIP_CHECKCONS, &m_ZIPError); if (m_ZIParchive == nullptr) throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE); // Get ZIP Content nfInt64 nEntryCount = zip_get_num_entries(m_ZIParchive, ZIP_FL_UNCHANGED); if (nEntryCount < 0) throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE); // List Entries nfInt64 nIndex; for (nIndex = 0; nIndex < nEntryCount; nIndex++) { const char * pszName = zip_get_name(m_ZIParchive, (nfUint64) nIndex, ZIP_FL_ENC_GUESS); std::string sUTF8Name(pszName); std::wstring sUTF16Name = fnUTF8toUTF16(sUTF8Name); m_ZIPEntries.insert(std::make_pair(sUTF16Name, nIndex)); } readContentTypes(); readRootRelationships(); } catch (...) { releaseZIP(); throw; } }
struct VDirEntry* _vdzListNext(struct VDir* vd) { struct VDirZip* vdz = (struct VDirZip*) vd; zip_int64_t maxIndex = zip_get_num_entries(vdz->z, 0); if (maxIndex <= vdz->dirent.index + 1) { return 0; } ++vdz->dirent.index; return &vdz->dirent.d; }
int main(int argc, char *argv[]) { const char *archive; struct zip *za; char buf[100]; int err; int i; prg = argv[0]; if (argc != 2) { fprintf(stderr, "usage: %s archive\n", prg); return 1; } archive = argv[1]; if ((za=zip_open(archive, 0, &err)) == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); fprintf(stderr, "%s: can't open zip archive `%s': %s\n", prg, archive, buf); return 1; } if (zip_set_archive_comment(za, new_archive_comment, (zip_uint16_t)strlen(new_archive_comment)) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n", prg, buf); } for (i=0; i<zip_get_num_entries(za, 0); i++) { snprintf(buf, sizeof(buf), "File comment no %d", i); if (zip_file_set_comment(za, i, buf, (zip_uint16_t)strlen(buf), 0) < 0) { zip_error_to_str(buf, sizeof(buf), err, errno); fprintf(stderr, "%s: zip_set_file_comment on file %d failed: %s\n", prg, i, buf); } } if (zip_unchange_all(za) == -1) { fprintf(stderr, "%s: can't revert changes to archive `%s'\n", prg, archive); return 1; } if (zip_close(za) == -1) { fprintf(stderr, "%s: can't close zip archive `%s': %s\n", prg, archive, zip_strerror(za)); return 1; } return 0; }
static const char* vfs_zipfile_iter(VFSNode *node, void **opaque) { VFSZipFileData *zdata = node->data1; VFSZipFileIterData *idata = *opaque; VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true); if(!idata) { *opaque = idata = calloc(1, sizeof(VFSZipFileIterData)); idata->num = zip_get_num_entries(tls->zip, 0); } return vfs_zipfile_iter_shared(node, zdata, idata, tls); }
void iterateFiles(FunctorT Functor) { struct zip_stat Stat; auto NumEntries = zip_get_num_entries(mZip, 0); for (zip_uint64_t I = 0; I != NumEntries; ++I) { auto Error = zip_stat_index(mZip, I, 0, &Stat); if (Error != 0) throw std::runtime_error{"Error reading zip"}; auto Length = std::char_traits<char>::length(Stat.name); if (Length == 0 || Stat.name[Length - 1] == '/') continue; auto File = ZipFileT{Stat.name, zip_fopen_index(mZip, I, 0)}; Functor(File); } }
static arch_enum_t zip_enum(archive_t archive,char *regex){ if (regex!=NULL) Abort("regex not supported"); arch_enum_t e=(arch_enum_t)HREmalloc(NULL,sizeof(struct arch_enum)); e->procs.enumerate=zip_enumerate; e->procs.free=zip_enum_free; e->archive=archive; e->next=0; #ifdef LIBZIP_VERSION e->count=zip_get_num_entries(archive->archive,0); #else e->count=zip_get_num_files(archive->archive); #endif return e; }
void ZipByteReader::Register(const std::map<std::string, size_t>& sequences) { auto zipFile = m_zips.pop_or_create([this]() { return OpenZip(); }); zip_stat_t stat; zip_stat_init(&stat); size_t numberOfEntries = 0; size_t numEntries = zip_get_num_entries(zipFile.get(), 0); for (size_t i = 0; i < numEntries; ++i) { int err = zip_stat_index(zipFile.get(), i, 0, &stat); if (ZIP_ER_OK != err) RuntimeError("Failed to get file info for index %d, zip library error: %s", (int)i, GetZipError(err).c_str()); auto sequenceId = sequences.find(std::string(stat.name)); if (sequenceId == sequences.end()) { continue; } else { m_seqIdToIndex[sequenceId->second] = std::make_pair(stat.index, stat.size); numberOfEntries++; } } m_zips.push(std::move(zipFile)); if (numberOfEntries != sequences.size()) { // Not all sequences have been found. Let's print them out and throw. for (const auto& s : sequences) { auto index = m_seqIdToIndex.find(s.second); if (index == m_seqIdToIndex.end()) { fprintf(stderr, "Sequence %s is not found in container %s.\n", s.first.c_str(), m_zipPath.c_str()); } } RuntimeError("Cannot retrieve image data for some sequences. For more detail, please see the log file."); } }
static int fs_cd_file_zip(struct directory *parent, const char *filename) { int isdirexist = 0; char buf[NAME_MAX]; int len; zip_int64_t nentries, i; struct directory dir; if (strcmp(filename, "..") == 0) { sf_list_pop(&fs.directories); return SF_OK; } get_zip_cwd(buf, NAME_MAX); strcat(buf, filename); len = strlen(buf); buf[len++] = '/'; buf[len] = '\0'; nentries = zip_get_num_entries(parent->zip, 0); for (i = 0; i < nentries; ++i) { if (strncmp(zip_get_name(parent->zip, i, 0), buf, len) == 0) { isdirexist = 1; break; } } if (isdirexist) { strncpy(dir.name, filename, NAME_MAX); dir.iszip = 1; dir.isopened = 1; dir.zip = parent->zip; dir.nopens = parent->nopens + 1; sf_list_push(&fs.directories, &dir); return SF_OK; } else { sf_log(SF_LOG_ERR, "not a directory: %s", filename); return SF_ERR; } }
static int fs_file_walker_zip(struct directory *d, int (*func)(int type, const char *filename, void *arg), void *arg) { char buf[PATH_MAX]; size_t len; int ret = SF_OK; zip_int64_t nentries = zip_get_num_entries(d->zip, 0); zip_int64_t i; get_zip_cwd(buf, PATH_MAX); len = strlen(buf); for (i = 0; i < nentries; ++i) { const char *filename = zip_get_name(d->zip, i, 0); char *ptr; if (strncmp(filename, buf, len) == 0) { filename += len; if (*filename == '\0') { continue; } if ((ptr = strchr(filename, '/')) == NULL) { if ((ret = func(FS_FILE, filename, arg)) != SF_OK) { break; } } else if (ptr == filename + strlen(filename) - 1) { char tmp[NAME_MAX]; strncpy(tmp, filename, strlen(filename) - 1); tmp[strlen(filename) - 1] = '\0'; if ((ret = func(FS_DIR, tmp, arg)) != SF_OK) { break; } } } } return ret; }
cnpy::NpArrayDict cnpy::npz_load(const std::string& fname) { Handler<struct zip> zip = zip_open(fname.c_str(), ZIP_CHECKCONS, nullptr); if(zip.handle()==nullptr) throw std::runtime_error("Error opening npz file "+fname); NpArrayDict arrays; zip_uint64_t numFiles = zip_get_num_entries(zip.handle(), 0); for(zip_uint64_t fid=0; fid<numFiles; ++fid) { const char* arrName = zip_get_name(zip.handle(), fid, 0); if(arrName==nullptr) continue; Handler<struct zip_file> zipFile = zip_fopen_index(zip.handle(), fid, 0); std::string name = arrName; name.erase(name.size()-4); arrays.insert(NpArrayDictItem(name, load_the_npy_file(zipFile))); } return arrays; }
static jstatus_t __stdcall find( struct judgefs *fs, /* out */ const char **path, const char *prefix, /* in out */ void **context) { struct zipfs *zipfs = (struct zipfs *)fs; uintptr_t *index = (uintptr_t *)context; zip_uint64_t num_entries; int zep; EnterCriticalSection(&zipfs->zip_cs); num_entries = zip_get_num_entries(zipfs->zip, ZIP_FL_NOCASE); while (1) { if (*index < num_entries) { const char *name = zip_get_name(zipfs->zip, *index, ZIP_FL_NOCASE); if (!name) { zip_error_get(zipfs->zip, &zep, NULL); LeaveCriticalSection(&zipfs->zip_cs); return zep_to_jstatus(zep); } ++*index; if (strncmp(name, prefix, strlen(prefix)) == 0) { LeaveCriticalSection(&zipfs->zip_cs); *path = name; return JSTATUS_SUCCESS; } } else { LeaveCriticalSection(&zipfs->zip_cs); *path = NULL; *index = 0; return JSTATUS_SUCCESS; } } }
int _unzip(char const* path, char const* outpath) { int err; int i, len; int filelen; struct zip* archive; struct zip_file* file; struct zip_stat stat; int fd; size_t sum; char buf[4096]; int outlen; char tmp[FILENAME_MAX]; archive = zip_open(path, 0, &err); if (!archive) { return 1; } outlen = strlen(outpath); len = zip_get_num_entries(archive, 0); for (i = 0; i < len; i++) { if (zip_stat_index(archive, i, 0, &stat)) { goto error; } filelen = strlen(stat.name); memcpy(tmp, outpath, outlen); memcpy(tmp + outlen, "/", 1); memcpy(tmp + outlen + 1, stat.name, filelen); tmp[outlen + filelen + 1] = '\0'; if (tmp[outlen + filelen + 1 - 1] == '/') { if (mkdir(tmp, 0755)) { fprintf(stderr, "Error: Creating directory: %s\n", tmp); goto error; } } else { file = zip_fopen_index(archive, i, 0); if (!file) { fprintf(stderr, "Error: Opening zip content: %s", tmp); goto error; } fd = open(tmp, O_RDWR | O_TRUNC | O_CREAT | BINARY, 0644); if (fd < 0) { fprintf(stderr, "Error: Opening file: %s\n", tmp); zip_fclose(file); goto error; } sum = 0; while (sum != stat.size) { filelen = zip_fread(file, buf, 4096); if (len < 0) { fprintf(stderr, "Error: Reading file: %s\n", tmp); close(fd); zip_fclose(file); goto error; } write(fd, buf, filelen); sum += filelen; } close(fd); zip_fclose(file); } } zip_close(archive); return 0; error: zip_close(archive); return 1; }
int extract_to_cache(const char *archive, const char *cache_path) { struct zip *ziparchive; struct zip_file *zipfile; struct zip_stat zipstat; char buf[4096]; int err; int i, len; int fd; int dirname_len; long long sum; char *full_path; char *dir_name; Stat localfile; utimbuf modified; android_printf("unzip: Preparing to cache. This could take a while..."); if ((ziparchive = zip_open(archive, 0, &err)) == NULL) { zip_error_to_str(buf, sizeof(buf), err, errno); android_printf("unzip error: can't open archive %s/n",archive); return 1; } mkpath(cache_path); for (i = 0; i < zip_get_num_entries(ziparchive, 0); i++) { if (zip_stat_index(ziparchive, i, 0, &zipstat) != 0) { android_printf("unzip error: can't open entry: %i/n",i); continue; } if(strncmp (zipstat.name,"assets/",7) != 0) continue; modified.modtime = modified.actime = zipstat.mtime; full_path = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + strlen(zipstat.name) + 1)); sprintf(full_path, "%s/%s",cache_path,zipstat.name); if (zipstat.name[strlen(zipstat.name) - 1] == '/') { mkpath(full_path); free(full_path); continue; } zipfile = zip_fopen_index(ziparchive, i, 0); if (!zipfile) { android_printf("unzip error: can't open index"); free(full_path); continue; } if (stat(full_path, &localfile) != 0) { dirname_len = strrchr(zipstat.name,'/') - zipstat.name; dir_name = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + dirname_len + 1)); strncpy(dir_name, full_path, strlen(cache_path) + dirname_len + 1); dir_name[strlen(cache_path) + dirname_len + 1] = '\0'; mkpath(dir_name); free(dir_name); } else if (localfile.st_mtime == zipstat.mtime) { free(full_path); continue; } fd = open(full_path, O_RDWR | O_TRUNC | O_CREAT, 0644); if(fd < 0) { android_printf("unzip error: could not open %s",full_path); free(full_path); continue; } sum = 0; while (sum != zipstat.size) { len = zip_fread(zipfile, buf, 4096); if (len < 0) { android_printf("unzip error: no data in %s",full_path); free(full_path); continue; } write(fd, buf, len); sum += len; } close(fd); zip_fclose(zipfile); if (stat(full_path, &localfile) == 0) { // save the zip time. this way we know for certain if we need to refresh. utime(full_path, &modified); } else { android_printf("unzip error: failed to extract %s",full_path); } free(full_path); } if (zip_close(ziparchive) == -1) android_printf("unzip error: can't close zip archive `%s'/n", archive); return 0; }
bool GetCompressedFiles(std::string ZipName, std::vector<std::string>* pFileNames, std::vector<std::vector<char> >* data, std::string* pError) { #ifdef WIN32 HZIP hz = OpenZip(ZipName.c_str(),0); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} ZIPENTRY ze; if (GetZipItem(hz, -1, &ze) != ZR_OK) {if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} int NumFiles = ze.index; //set up returns for data... data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ if (GetZipItem(hz,i,&ze) != ZR_OK) {if(pError) *pError += "Error loading ZIP file information. Aborting.\n"; return false;} int NumDesiredFiles = pFileNames->size(); for (int j=0; j<NumDesiredFiles; j++){ if ((*pFileNames)[j].compare(ze.name)==0){ //if this is one of the file's we're looking for int size = ze.unc_size; (*data)[j].resize(size+1); //or clear... if (UnzipItem(hz, i, &((*data)[j].front()), size) != ZR_OK) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[j][size] = '\0'; } } } if (CloseZip(hz) != ZR_OK) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #else //Mac/Linux Zip read code int err; struct zip * hz = zip_open(ZipName.c_str(), ZIP_CHECKCONS, &err); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} int NumFiles = zip_get_num_entries(hz,0); if (NumFiles < 0) { if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} //set up returns for data... data->resize(NumFiles); for (uint i=0; i<NumFiles; i++){ struct zip_file * zfile = zip_fopen_index(hz, i, 0); int NumDesiredFiles = pFileNames->size(); const char * entryname = zip_get_name(hz, i, 0); struct zip_stat stat; err = zip_stat_index(hz, i, 0, &stat); for (int j=0; j<NumDesiredFiles; j++){ if ((*pFileNames)[j].compare(entryname)==0){ //if this is one of the file's we're looking for int size = stat.size; (*data)[j].resize(size+1); //or clear... if (zip_fread(zfile, &((*data)[j].front()), size) != size) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[j][size] = '\0'; } } zip_fclose(zfile); } if (zip_close(hz) != 0) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #endif }
/* read (extract) 'zipfile' in current directory */ int zread(const char *zipfile, unsigned long long maxsize) { struct filedesc *fdesc; int err, fd; size_t len; struct zip *zip; zip_int64_t z64; zip_uint64_t uz64; unsigned int count, index; struct zip_file *zfile; struct zip_stat zstat; char buffer[32768]; ssize_t sizr, sizw; size_t esize; /* open the zip file */ zip = zip_open(zipfile, ZIP_CHECKCONS, &err); if (!zip) { ERROR("Can't connect to file %s", zipfile); return -1; } z64 = zip_get_num_entries(zip, 0); if (z64 < 0 || z64 > UINT_MAX) { ERROR("too many entries in %s", zipfile); goto error; } count = (unsigned int)z64; /* records the files */ file_reset(); esize = 0; for (index = 0 ; index < count ; index++) { err = zip_stat_index(zip, index, ZIP_FL_ENC_GUESS, &zstat); /* check the file name */ if (!is_valid_filename(zstat.name)) { ERROR("invalid entry %s found in %s", zstat.name, zipfile); goto error; } if (zstat.name[0] == '/') { ERROR("absolute entry %s found in %s", zstat.name, zipfile); goto error; } len = strlen(zstat.name); if (len == 0) { ERROR("empty entry found in %s", zipfile); goto error; } if (zstat.name[len - 1] == '/') /* record */ fdesc = file_add_directory(zstat.name); else { /* get the size */ esize += zstat.size; /* record */ fdesc = file_add_file(zstat.name); } if (!fdesc) goto error; fdesc->zindex = index; } /* check the size */ if (maxsize && esize > maxsize) { ERROR("extracted size %zu greater than allowed size %llu", esize, maxsize); goto error; } /* unpack the recorded files */ assert(count == file_count()); for (index = 0 ; index < count ; index++) { fdesc = file_of_index(index); assert(fdesc != NULL); err = zip_stat_index(zip, fdesc->zindex, ZIP_FL_ENC_GUESS, &zstat); assert(zstat.name[0] != '/'); len = strlen(zstat.name); assert(len > 0); if (zstat.name[len - 1] == '/') { /* directory name */ err = create_directory((char*)zstat.name, MODE_OF_DIRECTORY_CREATION); if (err && errno != EEXIST) goto error; } else { /* file name */ zfile = zip_fopen_index(zip, fdesc->zindex, 0); if (!zfile) { ERROR("Can't open %s in %s", zstat.name, zipfile); goto error; } fd = create_file((char*)zstat.name, MODE_OF_FILE_CREATION, MODE_OF_DIRECTORY_CREATION); if (fd < 0) goto errorz; /* extract */ uz64 = zstat.size; while (uz64) { sizr = zip_fread(zfile, buffer, sizeof buffer); if (sizr < 0) { ERROR("error while reading %s in %s", zstat.name, zipfile); goto errorzf; } sizw = write(fd, buffer, (size_t)sizr); if (sizw < 0) { ERROR("error while writing %s", zstat.name); goto errorzf; } uz64 -= (size_t)sizw; } close(fd); zip_fclose(zfile); } } zip_close(zip); return 0; errorzf: close(fd); errorz: zip_fclose(zfile); error: zip_close(zip); return -1; }
static int zip_append(const struct sr_output *o, unsigned char *buf, int unitsize, int length) { struct out_context *outc; struct zip *archive; struct zip_source *logicsrc; zip_int64_t num_files; struct zip_file *zf; struct zip_stat zs; struct zip_source *metasrc; GKeyFile *kf; GError *error; gsize len; int chunk_num, next_chunk_num, tmpfile, ret, i; const char *entry_name; char *metafile, tmpname[32], chunkname[16]; outc = o->priv; if (!(archive = zip_open(outc->filename, 0, &ret))) return SR_ERR; if (zip_stat(archive, "metadata", 0, &zs) == -1) return SR_ERR; metafile = g_malloc(zs.size); zf = zip_fopen_index(archive, zs.index, 0); zip_fread(zf, metafile, zs.size); zip_fclose(zf); /* * If the file was only initialized but doesn't yet have any * data it in, it won't have a unitsize field in metadata yet. */ error = NULL; kf = g_key_file_new(); if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, &error)) { sr_err("Failed to parse metadata: %s.", error->message); return SR_ERR; } g_free(metafile); tmpname[0] = '\0'; if (!g_key_file_has_key(kf, "device 1", "unitsize", &error)) { if (error && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) { sr_err("Failed to check unitsize key: %s", error ? error->message : "?"); return SR_ERR; } /* Add unitsize field. */ g_key_file_set_integer(kf, "device 1", "unitsize", unitsize); metafile = g_key_file_to_data(kf, &len, &error); strcpy(tmpname, "sigrok-meta-XXXXXX"); if ((tmpfile = g_mkstemp(tmpname)) == -1) return SR_ERR; if (write(tmpfile, metafile, len) < 0) { sr_dbg("Failed to create new metadata: %s", strerror(errno)); g_free(metafile); unlink(tmpname); return SR_ERR; } close(tmpfile); if (!(metasrc = zip_source_file(archive, tmpname, 0, -1))) { sr_err("Failed to create zip source for metadata."); g_free(metafile); unlink(tmpname); return SR_ERR; } if (zip_replace(archive, zs.index, metasrc) == -1) { sr_err("Failed to replace metadata file."); g_free(metafile); unlink(tmpname); return SR_ERR; } g_free(metafile); } g_key_file_free(kf); next_chunk_num = 1; num_files = zip_get_num_entries(archive, 0); for (i = 0; i < num_files; i++) { entry_name = zip_get_name(archive, i, 0); if (strncmp(entry_name, "logic-1", 7)) continue; if (strlen(entry_name) == 7) { /* This file has no extra chunks, just a single "logic-1". * Rename it to "logic-1-1" * and continue with chunk 2. */ if (zip_rename(archive, i, "logic-1-1") == -1) { sr_err("Failed to rename 'logic-1' to 'logic-1-1'."); unlink(tmpname); return SR_ERR; } next_chunk_num = 2; break; } else if (strlen(entry_name) > 8 && entry_name[7] == '-') { chunk_num = strtoull(entry_name + 8, NULL, 10); if (chunk_num >= next_chunk_num) next_chunk_num = chunk_num + 1; } } snprintf(chunkname, 15, "logic-1-%d", next_chunk_num); if (!(logicsrc = zip_source_buffer(archive, buf, length, FALSE))) { unlink(tmpname); return SR_ERR; } if (zip_add(archive, chunkname, logicsrc) == -1) { unlink(tmpname); return SR_ERR; } if ((ret = zip_close(archive)) == -1) { sr_info("error saving session file: %s", zip_strerror(archive)); unlink(tmpname); return SR_ERR; } unlink(tmpname); return SR_OK; }
bool UncompressAllFiles(std::string ZipName, std::vector<std::string>* pFileNames, std::vector<std::vector<char> >* data, std::string* pError) { #ifdef WIN32 HZIP hz = OpenZip(ZipName.c_str(),0); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} ZIPENTRY ze; if (GetZipItem(hz, -1, &ze) != ZR_OK) {if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} int NumFiles = ze.index; //set up returns for the number of files... pFileNames->resize(NumFiles); data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ if (GetZipItem(hz,i,&ze) != ZR_OK) {if(pError) *pError += "Error loading ZIP file information. Aborting.\n"; return false;} int size = ze.unc_size; (*data)[i].resize(size+1); if (UnzipItem(hz, i, &((*data)[i].front()), size) != ZR_OK) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[i][size] = '\0'; (*pFileNames)[i] = ze.name; } if (CloseZip(hz) != ZR_OK) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #else //Mac/Linux Zip read code int err; struct zip * hz = zip_open(ZipName.c_str(), ZIP_CHECKCONS, &err); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} int NumFiles = zip_get_num_entries(hz,0); if (NumFiles < 0) { if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} //set up returns for the number of files... pFileNames->resize(NumFiles); data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ struct zip_stat stat; err = zip_stat_index(hz, i, 0, &stat); int size = stat.size; (*data)[i].resize(size+1); struct zip_file * zfile = zip_fopen_index(hz, i, 0); if (zip_fread(zfile, &((*data)[i].front()), size) != size) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[i][size] = '\0'; (*pFileNames)[i] = zip_get_name(hz, i, 0); } if (zip_close(hz) != 0) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #endif }
struct input_file *read_file_list (int argc, char **argv, int *nf_r, char *errstr) { struct input_file *list = (struct input_file *) NULL; FILE *fp = (FILE *) NULL; char line[16384], *av, *p, *s; int a, f, nf = 0; #ifndef _WIN32 glob_t gbuf; int rv, op; /* Init */ gbuf.gl_pathv = (char **) NULL; #endif int is_zip; #ifdef ZIPSUPPORT zip_t *z = (zip_t *) NULL; zip_error_t ze; struct zip_stat sb; int zerrno; int ent, nent; const char *name; int namelen; zip_uint8_t opsys; zip_uint32_t extattr; #endif /* Loop over arguments */ for(a = 0; a < argc; a++) { av = argv[a]; if(*av == '@') { /* @list form */ av++; /* skip past the @ */ is_zip = is_zip_file(av, errstr); if(is_zip < 0) goto error; if(is_zip) { #ifdef ZIPSUPPORT z = zip_open(av, 0, &zerrno); if(!z) { zip_error_init_with_code(&ze, zerrno); report_err(errstr, "zip_open: %s: %s", av, zip_error_strerror(&ze)); zip_error_fini(&ze); goto error; } nent = zip_get_num_entries(z, 0); if(nent < 0) { report_err(errstr, "zip_get_num_entries: %s", zip_strerror(z)); goto error; } for(ent = 0; ent < nent; ent++) { if(zip_stat_index(z, ent, 0, &sb)) { report_err(errstr, "zip_stat_index(%d): %s\n", ent, zip_strerror(z)); goto error; } if(zip_file_get_external_attributes(z, ent, 0, &opsys, &extattr)) { report_err(errstr, "zip_get_external_attributes(%d): %s\n", ent, zip_strerror(z)); goto error; } name = sb.name; namelen = strlen(name); if((opsys != ZIP_OPSYS_AMIGA && extattr & 0x10) || (namelen > 0 && name[namelen-1] == '/')) /* Is directory */ continue; /* Otherwise, add to list */ list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(name); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = ent; list[nf].iarg = a; list[nf].arg = av; nf++; } if(zip_close(z)) { report_err(errstr, "zip_close: %s", zip_strerror(z)); goto error; } z = (zip_t *) NULL; #else report_err(errstr, "not compiled with zip support"); goto error; #endif } else { fp = fopen(av, "r"); if(!fp) { report_syserr(errstr, "open: %s", av); goto error; } while(fgets(line, sizeof(line), fp)) { p = sstrip(line); if(*p) { list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(p); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = -1; list[nf].iarg = a; list[nf].arg = av; nf++; } } if(ferror(fp)) { report_syserr(errstr, "read: %s", av); goto error; } fclose(fp); fp = (FILE *) NULL; } } else { /* glob or single filename */ #ifndef _WIN32 rv = glob(av, 0, NULL, &gbuf); if(rv == 0) { /* succeeded */ /* Allocate block */ list = (struct input_file *) realloc(list, (nf+gbuf.gl_pathc) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } /* Zero out the new pointers */ memset(list+nf, 0, gbuf.gl_pathc * sizeof(struct input_file)); /* Record so we know to free them */ op = nf; nf += gbuf.gl_pathc; for(f = 0; f < gbuf.gl_pathc; f++) { s = strdup(gbuf.gl_pathv[f]); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[op].filename = s; list[op].ient = -1; list[op].iarg = a; list[op].arg = av; op++; } globfree(&gbuf); gbuf.gl_pathv = (char **) NULL; } else if(rv == GLOB_NOMATCH) { /* no match */ #endif /* _WIN32 */ /* Assume it's a single entry. */ list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(av); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = -1; list[nf].iarg = a; list[nf].arg = av; nf++; #ifndef _WIN32 } else { report_err(errstr, "glob error: %s", av); goto error; } #endif } } *nf_r = nf; return(list); error: if(fp) fclose(fp); #ifndef _WIN32 if(gbuf.gl_pathv) globfree(&gbuf); #endif #ifdef ZIPSUPPORT if(z) { zip_close(z); z = (zip_t *) NULL; } #endif if(list) { for(f = 0; f < nf; f++) if(list[f].filename) free((void *) list[f].filename); free((void *) list); } return((struct input_file *) NULL); }
bool extractMap(const std::string& file) { int err = 0; zip* zipFile = zip_open(file.c_str(), 0, &err); if(!zipFile) { std::cout << "[ERROR]: Failed to open archive file: " << file << ".\n"; return false; } auto fileNumber = zip_get_num_entries(zipFile, 0); std::string folderName = file.substr(0, file.find_last_of('.')) + "/"; // cut off file extension, add dir char stripWebChars(folderName); if(!makeFolder(folderName)) return false; for(auto i = 0u; i < fileNumber; i++) { zip_file* zipped = zip_fopen_index(zipFile, i, 0); struct zip_stat fileInfo; zip_stat_init(&fileInfo); zip_stat_index(zipFile, i, 0, &fileInfo); if(fileInfo.valid & ZIP_STAT_NAME && fileInfo.valid & ZIP_STAT_SIZE && fileInfo.valid & ZIP_STAT_COMP_SIZE) { std::string fileStr = fileInfo.name; if(fileStr.find('.') == std::string::npos) // if we don't have a dot, this is a folder { continue; // skip this folder } if(fileStr.find('/') != std::string::npos) // if we have any dir chars in the string, strip out dirs { fileStr = fileStr.substr(fileStr.find_last_of('/') + 1); } #ifndef __linux__ #pragma warning(push) #pragma warning(disable: 4244) #endif std::vector<bbyte> bytes(fileInfo.size); // just gotta deal with this conversion #ifndef __linux__ #pragma warning(pop) #endif zip_fread(zipped, bytes.data(), fileInfo.size); std::ofstream fout; fout.open(folderName + fileStr, std::ofstream::binary); if(fout.bad()) { std::cout << "[ERROR]: Unable to extract file: " << fileInfo.name << '\n'; return false; } fout.write(bytes.data(), bytes.size()); fout.close(); } else { std::cout << "[ERROR]: Bad file data for file in archive: " << file << '\n'; return false; } zip_fclose(zipped); } zip_close(zipFile); // delete the zip file, it's no longer needed #ifdef __linux__ // TBD #else DeleteFile(file.c_str()); #endif return true; }
int main(int argc, char **argv) { idevice_t phone = NULL; lockdownd_client_t client = NULL; instproxy_client_t ipc = NULL; instproxy_error_t err; np_client_t np = NULL; afc_client_t afc = NULL; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 lockdownd_service_descriptor_t service = NULL; #else uint16_t service = 0; #endif int res = 0; char *bundleidentifier = NULL; parse_opts(argc, argv); argc -= optind; argv += optind; if (IDEVICE_E_SUCCESS != idevice_new(&phone, udid)) { fprintf(stderr, "No iOS device found, is it plugged in?\n"); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } if ((lockdownd_start_service (client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.notification_proxy!\n"); goto leave_cleanup; } np_error_t nperr = np_client_new(phone, service, &np); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (nperr != NP_E_SUCCESS) { fprintf(stderr, "Could not connect to notification_proxy!\n"); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 np_set_notify_callback(np, notifier, NULL); #else np_set_notify_callback(np, notifier); #endif const char *noties[3] = { NP_APP_INSTALLED, NP_APP_UNINSTALLED, NULL }; np_observe_notifications(np, noties); run_again: #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.installation_proxy!\n"); goto leave_cleanup; } err = instproxy_client_new(phone, service, &ipc); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to installation_proxy!\n"); goto leave_cleanup; } setbuf(stdout, NULL); if (last_status) { free(last_status); last_status = NULL; } notification_expected = 0; if (cmd == CMD_LIST_APPS) { int xml_mode = 0; plist_t client_opts = instproxy_client_options_new(); instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); plist_t apps = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "list_system")) { if (!client_opts) { client_opts = instproxy_client_options_new(); } instproxy_client_options_add(client_opts, "ApplicationType", "System", NULL); } else if (!strcmp(elem, "list_all")) { instproxy_client_options_free(client_opts); client_opts = NULL; } else if (!strcmp(elem, "list_user")) { /* do nothing, we're already set */ } else if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } free(opts); } err = instproxy_browse(ipc, client_opts, &apps); instproxy_client_options_free(client_opts); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: instproxy_browse returned %d\n", err); goto leave_cleanup; } if (!apps || (plist_get_node_type(apps) != PLIST_ARRAY)) { fprintf(stderr, "ERROR: instproxy_browse returnd an invalid plist!\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(apps, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(apps); goto leave_cleanup; } printf("Total: %d apps\n", plist_array_get_size(apps)); uint32_t i = 0; for (i = 0; i < plist_array_get_size(apps); i++) { plist_t app = plist_array_get_item(apps, i); plist_t p_appid = plist_dict_get_item(app, "CFBundleIdentifier"); char *s_appid = NULL; char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(app, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(app, "CFBundleVersion"); if (p_appid) { plist_get_string_val(p_appid, &s_appid); } if (!s_appid) { fprintf(stderr, "ERROR: Failed to get APPID!\n"); break; } if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(s_appid); } if (s_version) { printf("%s - %s %s\n", s_appid, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", s_appid, s_dispName); } free(s_dispName); free(s_appid); } plist_free(apps); } else if (cmd == CMD_INSTALL || cmd == CMD_UPGRADE) { plist_t sinf = NULL; plist_t meta = NULL; char *pkgname = NULL; struct stat fst; uint64_t af = 0; char buf[8192]; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } if (stat(appid, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", appid, strerror(errno)); goto leave_cleanup; } char **strs = NULL; if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); } } if (strs) { int i = 0; while (strs[i]) { free(strs[i]); i++; } free(strs); } plist_t client_opts = instproxy_client_options_new(); /* open install package */ int errp = 0; struct zip *zf = NULL; if ((strlen(appid) > 5) && (strcmp(&appid[strlen(appid)-5], ".ipcc") == 0)) { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } char* ipcc = strdup(appid); if ((asprintf(&pkgname, "%s/%s", PKG_PATH, basename(ipcc)) > 0) && pkgname) { afc_make_directory(afc, pkgname); } printf("Uploading %s package contents... ", basename(ipcc)); /* extract the contents of the .ipcc file to PublicStaging/<name>.ipcc directory */ zip_uint64_t numzf = zip_get_num_entries(zf, 0); zip_uint64_t i = 0; for (i = 0; numzf > 0 && i < numzf; i++) { const char* zname = zip_get_name(zf, i, 0); char* dstpath = NULL; if (!zname) continue; if (zname[strlen(zname)-1] == '/') { // directory if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) > 0) && dstpath) { afc_make_directory(afc, dstpath); } free(dstpath); dstpath = NULL; } else { // file struct zip_file* zfile = zip_fopen_index(zf, i, 0); if (!zfile) continue; if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) <= 0) || !dstpath || (afc_file_open(afc, dstpath, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS)) { fprintf(stderr, "ERROR: can't open afc://%s for writing\n", dstpath); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } struct zip_stat zs; zip_stat_init(&zs); if (zip_stat_index(zf, i, 0, &zs) != 0) { fprintf(stderr, "ERROR: zip_stat_index %" PRIu64 " failed!\n", i); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } free(dstpath); dstpath = NULL; zip_uint64_t zfsize = 0; while (zfsize < zs.size) { zip_int64_t amount = zip_fread(zfile, buf, sizeof(buf)); if (amount == 0) { break; } if (amount > 0) { uint32_t written, total = 0; while (total < amount) { written = 0; if (afc_file_write(afc, af, buf, amount, &written) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Write error!\n"); break; } total += written; } if (total != amount) { fprintf(stderr, "Error: wrote only %d of %" PRIi64 "\n", total, amount); afc_file_close(afc, af); zip_fclose(zfile); free(dstpath); goto leave_cleanup; } } zfsize += amount; } afc_file_close(afc, af); af = 0; zip_fclose(zfile); } } free(ipcc); printf("DONE.\n"); instproxy_client_options_add(client_opts, "PackageType", "CarrierBundle", NULL); } else if (S_ISDIR(fst.st_mode)) { /* upload developer app directory */ instproxy_client_options_add(client_opts, "PackageType", "Developer", NULL); if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { fprintf(stderr, "ERROR: Out of memory allocating pkgname!?\n"); goto leave_cleanup; } printf("Uploading %s package contents... ", basename(appid)); afc_upload_dir(afc, appid, pkgname); printf("DONE.\n"); } else { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } /* extract iTunesMetadata.plist from package */ char *zbuf = NULL; uint32_t len = 0; plist_t meta_dict = NULL; if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { meta = plist_new_data(zbuf, len); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &meta_dict); } else { plist_from_xml(zbuf, len, &meta_dict); } } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); } if (zbuf) { free(zbuf); } /* determine .app directory in archive */ zbuf = NULL; len = 0; plist_t info = NULL; char* filename = NULL; char* app_directory_name = NULL; if (zip_get_app_directory(zf, &app_directory_name)) { fprintf(stderr, "Unable to locate app directory in archive!\n"); goto leave_cleanup; } /* construct full filename to Info.plist */ filename = (char*)malloc(strlen(app_directory_name)+10+1); strcpy(filename, app_directory_name); free(app_directory_name); app_directory_name = NULL; strcat(filename, "Info.plist"); if (zip_get_contents(zf, filename, 0, &zbuf, &len) < 0) { fprintf(stderr, "WARNING: could not locate %s in archive!\n", filename); free(filename); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } free(filename); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &info); } else { plist_from_xml(zbuf, len, &info); } free(zbuf); if (!info) { fprintf(stderr, "Could not parse Info.plist!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *bundleexecutable = NULL; plist_t bname = plist_dict_get_item(info, "CFBundleExecutable"); if (bname) { plist_get_string_val(bname, &bundleexecutable); } bname = plist_dict_get_item(info, "CFBundleIdentifier"); if (bname) { plist_get_string_val(bname, &bundleidentifier); } plist_free(info); info = NULL; if (!bundleexecutable) { fprintf(stderr, "Could not determine value for CFBundleExecutable!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *sinfname = NULL; if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(bundleexecutable); /* extract .sinf from package */ zbuf = NULL; len = 0; if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { sinf = plist_new_data(zbuf, len); } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); } free(sinfname); if (zbuf) { free(zbuf); } /* copy archive to device */ pkgname = NULL; if (asprintf(&pkgname, "%s/%s", PKG_PATH, bundleidentifier) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } printf("Copying '%s' to device... ", appid); if (afc_upload_file(afc, appid, pkgname) < 0) { free(pkgname); goto leave_cleanup; } printf("DONE.\n"); if (bundleidentifier) { instproxy_client_options_add(client_opts, "CFBundleIdentifier", bundleidentifier, NULL); } if (sinf) { instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); } if (meta) { instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL); } } if (zf) { zip_unchange_all(zf); zip_close(zf); } /* perform installation or upgrade */ if (cmd == CMD_INSTALL) { printf("Installing '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_install(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_install(ipc, pkgname, client_opts, status_cb); #endif } else { printf("Upgrading '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_upgrade(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_upgrade(ipc, pkgname, client_opts, status_cb); #endif } instproxy_client_options_free(client_opts); free(pkgname); wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_UNINSTALL) { printf("Uninstalling '%s'\n", appid); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_uninstall(ipc, appid, NULL, status_cb, NULL); #else instproxy_uninstall(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 0; } else if (cmd == CMD_LIST_ARCHIVES) { int xml_mode = 0; plist_t dict = NULL; plist_t lres = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } } err = instproxy_lookup_archives(ipc, NULL, &dict); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: lookup_archives returned %d\n", err); goto leave_cleanup; } if (!dict) { fprintf(stderr, "ERROR: lookup_archives did not return a plist!?\n"); goto leave_cleanup; } lres = plist_dict_get_item(dict, "LookupResult"); if (!lres || (plist_get_node_type(lres) != PLIST_DICT)) { plist_free(dict); fprintf(stderr, "ERROR: Could not get dict 'LookupResult'\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(lres, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(dict); goto leave_cleanup; } plist_dict_iter iter = NULL; plist_t node = NULL; char *key = NULL; printf("Total: %d archived apps\n", plist_dict_get_size(lres)); plist_dict_new_iter(lres, &iter); if (!iter) { plist_free(dict); fprintf(stderr, "ERROR: Could not create plist_dict_iter!\n"); goto leave_cleanup; } do { key = NULL; node = NULL; plist_dict_next_item(lres, iter, &key, &node); if (key && (plist_get_node_type(node) == PLIST_DICT)) { char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(node, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(node, "CFBundleVersion"); if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(key); } if (s_version) { printf("%s - %s %s\n", key, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", key, s_dispName); } free(s_dispName); free(key); } } while (node); plist_free(dict); } else if (cmd == CMD_ARCHIVE) { char *copy_path = NULL; int remove_after_copy = 0; int skip_uninstall = 1; int app_only = 0; int docs_only = 0; plist_t client_opts = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "uninstall")) { skip_uninstall = 0; } else if (!strcmp(elem, "app_only")) { app_only = 1; docs_only = 0; } else if (!strcmp(elem, "docs_only")) { docs_only = 1; app_only = 0; } else if ((strlen(elem) > 5) && !strncmp(elem, "copy=", 5)) { copy_path = strdup(elem+5); } else if (!strcmp(elem, "remove")) { remove_after_copy = 1; } elem = strtok(NULL, ","); } } if (skip_uninstall || app_only || docs_only) { client_opts = instproxy_client_options_new(); if (skip_uninstall) { instproxy_client_options_add(client_opts, "SkipUninstall", 1, NULL); } if (app_only) { instproxy_client_options_add(client_opts, "ArchiveType", "ApplicationOnly", NULL); } else if (docs_only) { instproxy_client_options_add(client_opts, "ArchiveType", "DocumentsOnly", NULL); } } if (copy_path) { struct stat fst; if (stat(copy_path, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", copy_path, strerror(errno)); free(copy_path); goto leave_cleanup; } if (!S_ISDIR(fst.st_mode)) { fprintf(stderr, "ERROR: '%s' is not a directory as expected.\n", copy_path); free(copy_path); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); free(copy_path); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_archive(ipc, appid, client_opts, status_cb, NULL); #else instproxy_archive(ipc, appid, client_opts, status_cb); #endif instproxy_client_options_free(client_opts); wait_for_op_complete = 1; if (skip_uninstall) { notification_expected = 0; } else { notification_expected = 1; } idevice_wait_for_operation_to_complete(); if (copy_path) { if (err_occured) { afc_client_free(afc); afc = NULL; goto leave_cleanup; } FILE *f = NULL; uint64_t af = 0; /* local filename */ char *localfile = NULL; if (asprintf(&localfile, "%s/%s.ipa", copy_path, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(copy_path); f = fopen(localfile, "wb"); if (!f) { fprintf(stderr, "ERROR: fopen: %s: %s\n", localfile, strerror(errno)); free(localfile); goto leave_cleanup; } /* remote filename */ char *remotefile = NULL; if (asprintf(&remotefile, "%s/%s.zip", APPARCH_PATH, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } uint32_t fsize = 0; char **fileinfo = NULL; if ((afc_get_file_info(afc, remotefile, &fileinfo) != AFC_E_SUCCESS) || !fileinfo) { fprintf(stderr, "ERROR getting AFC file info for '%s' on device!\n", remotefile); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } int i; for (i = 0; fileinfo[i]; i+=2) { if (!strcmp(fileinfo[i], "st_size")) { fsize = atoi(fileinfo[i+1]); break; } } i = 0; while (fileinfo[i]) { free(fileinfo[i]); i++; } free(fileinfo); if (fsize == 0) { fprintf(stderr, "Hm... remote file length could not be determined. Cannot copy.\n"); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } if ((afc_file_open(afc, remotefile, AFC_FOPEN_RDONLY, &af) != AFC_E_SUCCESS) || !af) { fclose(f); fprintf(stderr, "ERROR: could not open '%s' on device for reading!\n", remotefile); free(remotefile); free(localfile); goto leave_cleanup; } /* copy file over */ printf("Copying '%s' --> '%s'... ", remotefile, localfile); free(remotefile); free(localfile); uint32_t amount = 0; uint32_t total = 0; char buf[8192]; do { if (afc_file_read(afc, af, buf, sizeof(buf), &amount) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Read error!\n"); break; } if (amount > 0) { size_t written = fwrite(buf, 1, amount, f); if (written != amount) { fprintf(stderr, "Error when writing %d bytes to local file!\n", amount); break; } total += written; } } while (amount > 0); afc_file_close(afc, af); fclose(f); printf("DONE.\n"); if (total != fsize) { fprintf(stderr, "WARNING: remote and local file sizes don't match (%d != %d)\n", fsize, total); if (remove_after_copy) { fprintf(stderr, "NOTE: archive file will NOT be removed from device\n"); remove_after_copy = 0; } } if (remove_after_copy) { /* remove archive if requested */ printf("Removing '%s'\n", appid); cmd = CMD_REMOVE_ARCHIVE; free(options); options = NULL; if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } goto run_again; } } goto leave_cleanup; } else if (cmd == CMD_RESTORE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_restore(ipc, appid, NULL, status_cb, NULL); #else instproxy_restore(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_REMOVE_ARCHIVE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_remove_archive(ipc, appid, NULL, status_cb, NULL); #else instproxy_remove_archive(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; } else { printf ("ERROR: no operation selected?! This should not be reached!\n"); res = -2; goto leave_cleanup; } if (client) { /* not needed anymore */ lockdownd_client_free(client); client = NULL; } idevice_wait_for_operation_to_complete(); leave_cleanup: if (bundleidentifier) { free(bundleidentifier); } if (np) { np_client_free(np); } if (ipc) { instproxy_client_free(ipc); } if (afc) { afc_client_free(afc); } if (client) { lockdownd_client_free(client); } idevice_free(phone); if (udid) { free(udid); } if (appid) { free(appid); } if (options) { free(options); } return res; }