00001
00047 #include "re_object_recorder/qminizip.h"
00048
00049 #include "minizip/zip.h"
00050 #include "minizip/unzip.h"
00051 #include <stdexcept>
00052
00053 #include <QDateTime>
00054 #include <QDebug>
00055 #include <QDir>
00056
00057 QMiniZip::QMiniZip(QString zipfile_, OpenMode mode_) : zipFileInfo(zipfile_), mode(mode_) {
00058 if (mode == ZIP_CREATE ) {
00059
00060 zf = zipOpen64(qPrintable(zipfile_), mode == ZIP_APPEND);
00061 if (zf == NULL)
00062 throw std::runtime_error("could not open zip file");
00063 }
00064 else if (mode == UNZIP) {
00065 uf = unzOpen64(qPrintable(zipfile_));
00066 }
00067 else
00068 throw std::logic_error("not implemented yet");
00069 }
00070
00071 QMiniZip::~QMiniZip() {
00072 if (mode == ZIP_APPEND || mode == ZIP_CREATE)
00073 zipClose(zf, NULL);
00074 else if (mode == UNZIP)
00075 unzClose(uf);
00076 else
00077 throw std::logic_error("unknown mode in destructor");
00078 }
00079
00080 void QMiniZip::addFile(const QFileInfo& fileInfo, const QString& nameInZip) {
00081 if (mode != ZIP_CREATE && mode != ZIP_APPEND) {
00082 throw std::logic_error("cannot add to zip file that was opened in UNZIP mode");
00083 }
00084
00085 zip_fileinfo zi;
00086 zi.dosDate = 0;
00087 zi.internal_fa = 0;
00088 zi.external_fa = 0;
00089
00090 QDateTime lastModified = fileInfo.lastModified();
00091 zi.tmz_date.tm_hour = lastModified.time().hour();
00092 zi.tmz_date.tm_min = lastModified.time().minute();
00093 zi.tmz_date.tm_sec = lastModified.time().second();
00094 zi.tmz_date.tm_mday = lastModified.date().day();
00095 zi.tmz_date.tm_mon = lastModified.date().month() - 1;
00096 zi.tmz_date.tm_year = lastModified.date().year();
00097
00098 QString niz = nameInZip.isEmpty() ? fileInfo.fileName() : nameInZip;
00099 int opt_compress_level = Z_DEFAULT_COMPRESSION;
00100 int err = zipOpenNewFileInZip3_64(zf, qPrintable(niz), &zi,
00101 NULL,0,NULL,0,NULL,
00102 (opt_compress_level != 0) ? Z_DEFLATED : 0,
00103 opt_compress_level,0,
00104 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
00105 NULL, 0, 1);
00106 if (err != ZIP_OK)
00107 {
00108 throw std::runtime_error("could not create file in zip");
00109 }
00110
00111 const size_t WRITE_BUFFER_SIZE = 16384;
00112 char *buf = new char[WRITE_BUFFER_SIZE];
00113 FILE *fin = fopen64(qPrintable(fileInfo.absoluteFilePath()), "rb");
00114 int size_read;
00115 do {
00116 size_read = fread(buf, 1, WRITE_BUFFER_SIZE, fin);
00117
00118 if (size_read > 0)
00119 err = zipWriteInFileInZip(zf, buf, size_read);
00120 } while ((err == ZIP_OK) && (size_read > 0));
00121
00122 if (err != ZIP_OK) {
00123 throw std::runtime_error("error reading input file");
00124 }
00125
00126 fclose(fin);
00127 err = zipCloseFileInZip(zf);
00128 if (err != ZIP_OK) {
00129 throw std::runtime_error("error closing newly created file in zip");
00130 }
00131 delete [] buf;
00132 }
00133
00134 QStringList QMiniZip::unzip(QDir target_path) {
00135 QStringList result;
00136 unz_global_info64 gi;
00137 int err;
00138
00139 unzGoToFirstFile(uf);
00140
00141 err = unzGetGlobalInfo64(uf, &gi);
00142 if (err!=UNZ_OK) {
00143 qDebug() << "error with zipfile in unzGetGlobalInfo";
00144 }
00145
00146
00147
00148 for (size_t i=0; i<gi.number_entry; i++)
00149 {
00150 QString extracted_file = do_extract_currentfile(target_path);
00151 if (extracted_file.isEmpty())
00152 break;
00153 result.append(extracted_file);
00154
00155 if ((i+1)<gi.number_entry)
00156 {
00157 err = unzGoToNextFile(uf);
00158 if (err!=UNZ_OK)
00159 {
00160 printf("error %d with zipfile in unzGoToNextFile\n",err);
00161 break;
00162 }
00163 }
00164 }
00165 return result;
00166 }
00167
00168 QString QMiniZip::do_extract_currentfile(const QDir& target_dir) {
00169 char filename_inzip[256];
00170 unz_file_info64 file_info;
00171 int err;
00172
00173 err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
00174 if (err != UNZ_OK)
00175 throw std::runtime_error("error during unzGetCurrentFileInfo");
00176
00177 const size_t WRITE_BUFFER_SIZE = 16384;
00178 char *buf = new char[WRITE_BUFFER_SIZE];
00179
00180 QString filename_inzip_qstr(filename_inzip);
00181 QString path = filename_inzip_qstr.left(filename_inzip_qstr.lastIndexOf("/"));
00182 if (!path.isEmpty() && path != filename_inzip_qstr) {
00183 QFileInfo p(target_dir.filePath(path));
00184 if (!p.exists()) {
00185
00186 target_dir.mkpath(path);
00187 }
00188 }
00189
00190 err = unzOpenCurrentFilePassword(uf,NULL);
00191 if (err!=UNZ_OK)
00192 {
00193 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
00194 }
00195
00196 QString resulting_filename(target_dir.filePath(filename_inzip_qstr));
00197
00198 FILE *fout;
00199 fout=fopen64(qPrintable(resulting_filename),"wb");
00200 do
00201 {
00202 err = unzReadCurrentFile(uf, buf, WRITE_BUFFER_SIZE);
00203 if (err<0)
00204 {
00205 printf("error %d with zipfile in unzReadCurrentFile\n",err);
00206 break;
00207 }
00208 if (err>0)
00209 if (fwrite(buf,err,1,fout)!=1)
00210 {
00211 printf("error in writing extracted file\n");
00212 err=UNZ_ERRNO;
00213 break;
00214 }
00215 } while (err>0);
00216 if (fout)
00217 fclose(fout);
00218
00219 if (err==UNZ_OK)
00220 {
00221 err = unzCloseCurrentFile (uf);
00222 }
00223
00224
00225 delete [] buf;
00226 return resulting_filename;
00227 }
00228
00229 QByteArray QMiniZip::getFile(const QString& filename) {
00230 unz_file_info64 file_info;
00231 QByteArray result;
00232 char filename_inzip[256];
00233
00234 unz_global_info64 gi;
00235 int err;
00236
00237 unzGoToFirstFile(uf);
00238
00239 err = unzGetGlobalInfo64(uf, &gi);
00240 if (err!=UNZ_OK) {
00241 qDebug() << "error with zipfile in unzGetGlobalInfo";
00242 }
00243
00244 for (size_t i=0; i<gi.number_entry; i++)
00245 {
00246 err = unzGoToNextFile(uf);
00247 if (err != UNZ_OK) {
00248 return result;
00249 }
00250 err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
00251 err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
00252 if (err != UNZ_OK)
00253 return result;
00254 QString fn(filename_inzip);
00255 if (fn.endsWith(filename)) {
00256 break;
00257 }
00258 }
00259
00260 const size_t WRITE_BUFFER_SIZE = 16384;
00261 static char buf[WRITE_BUFFER_SIZE];
00262
00263 err = unzOpenCurrentFilePassword(uf, NULL);
00264 if (err!=UNZ_OK) {
00265 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
00266 }
00267
00268 do {
00269 err = unzReadCurrentFile(uf, buf, WRITE_BUFFER_SIZE);
00270 if (err<0) {
00271 printf("error %d with zipfile in unzReadCurrentFile\n",err);
00272 break;
00273 }
00274 if (err>0) {
00275 result.append(buf, err);
00276 }
00277 } while (err>0);
00278 if (err==UNZ_OK) {
00279 err = unzCloseCurrentFile (uf);
00280 }
00281
00282 return result;
00283 }
00284
00285 QStringList QMiniZip::getContents() {
00286 QStringList result;
00287 unz_global_info64 gi;
00288 int err;
00289
00290 unzGoToFirstFile(uf);
00291
00292 err = unzGetGlobalInfo64(uf, &gi);
00293
00294
00295
00296 for (uLong i=0;i<gi.number_entry;i++) {
00297 char filename_inzip[256];
00298 unz_file_info64 file_info;
00299 err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
00300 if (err!=UNZ_OK)
00301 {
00302
00303 break;
00304 }
00305 result.append(QString::fromLocal8Bit(filename_inzip));
00306
00307 if ((i+1)<gi.number_entry)
00308 {
00309 err = unzGoToNextFile(uf);
00310 if (err!=UNZ_OK)
00311 {
00312 printf("error %d with zipfile in unzGoToNextFile\n",err);
00313 break;
00314 }
00315 }
00316 }
00317
00318 return result;
00319 }