/* zipfile.save(callback) */ Handle<Value> ZipFile::Save(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); Local<Value> cb = args[0]; if (!cb->IsFunction()) return ThrowException(Exception::Error( String::New("Second argument should be a callback function."))); save_closure_t *save = new save_closure_t; save->done = false; save->zf = zf; save->error = NULL; save->save_cb = Persistent<Function>::New(Handle<Function>::Cast(cb)); pthread_mutex_init(&save->mutex, NULL); saving_closures.insert(save); zf->saving = true; zf->Ref(); ev_ref(EV_DEFAULT_UC); pthread_create(&save->thread, NULL, Save_Thread, save); return Undefined(); }
/* zipfile.addFile(nameInArchive, name, offset, len) */ Handle<Value> ZipFile::Add_File(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); struct zip_source *source; if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); if (!args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a file name."))); std::string archive_file = TOSTR(args[0]); std::string name; if (args[1]->IsUndefined()) name = archive_file; else if (!args[1]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a file name."))); name = TOSTR(args[1]); zip_int64_t off; if (args[2]->IsUndefined()) off = 0; else off = args[2]->Int32Value(); zip_int64_t len; if (args[3]->IsUndefined()) len = -1; else len = args[3]->Int32Value(); source = zip_source_file(zf->archive, name.c_str(), off, len); if (source == NULL) { std::stringstream s; s << "Error while adding file " << name << " to zip archive: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } int ret = zip_add(zf->archive, archive_file.c_str(), source); if (ret < 0) { zip_source_free(source); std::stringstream s; s << "Error while adding file " << name << " to zip archive: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } zf->GetNames(); return Undefined(); }
/* zipfile.addDirectory(name) */ Handle<Value> ZipFile::Add_Directory(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); if (!args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a directory name."))); std::string directory = TOSTR(args[0]); int ret = zip_add_dir(zf->archive, directory.c_str()); if (ret < 0) { std::stringstream s; s << "Error while adding directory " << directory << " to zip archive: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } zf->GetNames(); return Undefined(); }
Handle<Value> ZipFile::Open(const Arguments& args) { if (args.Length() != 1 || !args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a file name inside the zip"))); std::string name = TOSTR(args[0]); // TODO - enforce valid index ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); zf->file_index = -1; std::vector<std::string>::iterator it = std::find(zf->names.begin(), zf->names.end(), name); if (it!=zf->names.end()) { zf->file_index = distance(zf->names.begin(), it); } if (zf->file_index == -1) { std::stringstream s; s << "No file found by the name of: '" << name << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } if ((zf->file=zip_fopen_index(zf->archive, zf->file_index, 0)) == NULL) { zip_fclose(zf->file); zf->file = NULL; std::stringstream s; s << "cannot open file #" << zf->file_index << " in " << name << ": archive error: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } return Undefined(); }
/* zipfile.replaceFile(nameInArchive, name, offset, len) */ Handle<Value> ZipFile::Replace_File(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); struct zip_source *source; if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); if (!args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a file name."))); std::string archive_file = TOSTR(args[0]); std::string name; if (args[1]->IsUndefined()) name = archive_file; else if (!args[1]->IsString()) return ThrowException(Exception::TypeError( String::New("Argument must be a file name."))); name = TOSTR(args[1]); zip_int64_t off; if (args[2]->IsUndefined()) off = 0; else off = args[2]->Int32Value(); zip_int64_t len; if (args[3]->IsUndefined()) len = -1; else len = args[3]->Int32Value(); int idx = -1; std::vector<std::string>::iterator it = std::find(zf->names.begin(), zf->names.end(), archive_file); if (it!=zf->names.end()) { idx = distance(zf->names.begin(), it); } if (idx == -1) { std::stringstream s; s << "No file found by the name of: '" << archive_file << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } source = zip_source_file(zf->archive, name.c_str(), off, len); if (source == NULL) { std::stringstream s; s << "Error while replacing file " << name << " in zip archive: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } int ret = zip_replace(zf->archive, idx, source); if (ret < 0) { zip_source_free(source); std::stringstream s; s << "Error while replacing file " << name << " in zip archive: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } return Undefined(); }
Handle<Value> ZipFile::readFileSync(const Arguments& args) { HandleScope scope; if (args.Length() != 1 || !args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("first argument must be a file name inside the zip"))); std::string name = TOSTR(args[0]); // TODO - enforce valid index ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); struct zip_file *zf_ptr; int idx = -1; std::vector<std::string>::iterator it = std::find(zf->names.begin(), zf->names.end(), name); if (it!=zf->names.end()) { idx = distance(zf->names.begin(), it); } if (idx == -1) { std::stringstream s; s << "No file found by the name of: '" << name << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } if ((zf_ptr=zip_fopen_index(zf->archive, idx, 0)) == NULL) { zip_fclose(zf_ptr); std::stringstream s; s << "cannot open file #" << idx << " in " << name << ": archive error: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } struct zip_stat st; zip_stat_index(zf->archive, idx, 0, &st); std::vector<unsigned char> data; data.clear(); data.resize( st.size ); int result = 0; result = (int)zip_fread( zf_ptr, reinterpret_cast<void*> (&data[0]), data.size() ); if (result < 0) { zip_fclose(zf_ptr); std::stringstream s; s << "error reading file #" << idx << " in " << name << ": archive error: " << zip_file_strerror(zf_ptr) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } #if NODE_VERSION_AT_LEAST(0,3,0) node::Buffer *retbuf = Buffer::New((char *)&data[0],data.size()); #else node::Buffer *retbuf = Buffer::New(data.size()); std::memcpy(retbuf->data(), (char *)&data[0], data.size()); #endif zip_fclose(zf_ptr); return scope.Close(retbuf->handle_); }