Launcher, based on PickleLauncher
[mupen64plus-pandora.git] / source / mupen64launcher / src / czip.cpp
CommitLineData
8b5037a6 1/**
2 * @section LICENSE
3 *
4 * PickleLauncher
5 * Copyright (C) 2010-2011 Scott Smith
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * @section LOCATION
21 */
22
23 /*
24 czip.cpp is based on miniunz.c
25
26 miniunz.c
27 Version 1.1, February 14h, 2010
28 sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
29
30 Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
31
32 Modifications of Unzip for Zip64
33 Copyright (C) 2007-2008 Even Rouault
34
35 Modifications for Zip64 support on both zip and unzip
36 Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
37*/
38
39#include "czip.h"
40
41CZip::CZip() : CBase(),
42 UnzipFiles ()
43{
44}
45
46CZip::~CZip()
47{
48}
49
50void CZip::ListFiles( const string& zipfile, vector<string>& list )
51{
52 uint32_t i;
53 int32_t err;
54 unzFile uf=NULL;
55 unz_global_info64 gi;
56
57 // Open the zip file
58 uf = unzOpen64( zipfile.c_str() );
59
60 if (uf != NULL)
61 {
62 // Get file info for the zip file
63 err = unzGetGlobalInfo64( uf,&gi );
64 if (err != UNZ_OK)
65 {
66 Log( "error %d with zipfile in unzGetGlobalInfo\n",err);
67 return;
68 }
69 }
70 else
71 {
72 Log( "error with zipfile %s in unzOpen64\n", zipfile.c_str() );
73 return;
74 }
75 Log( "Reading zip file %s\n", zipfile.c_str() );
76
77 // Spit out some information about the files in the zip for debug
78 Log( " Length Method Size Ratio Date Time CRC-32 Name\n" );
79 Log( " ------ ------ ---- ----- ---- ---- ------ ----\n" );
80 for (i=0; i<gi.number_entry; i++)
81 {
82 char filename_inzip[256];
83 unz_file_info64 file_info;
84 uLong ratio=0;
85 const char *string_method = NULL;
86 char charCrypt=' ';
87 err = unzGetCurrentFileInfo64( uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0 );
88 if (err != UNZ_OK)
89 {
90 Log( "error %d with zipfile in unzGetCurrentFileInfo\n",err);
91 break;
92 }
93 if (file_info.uncompressed_size > 0)
94 ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);
95
96 /* display a '*' if the file is crypted */
97 if ((file_info.flag & 1) != 0)
98 charCrypt='*';
99
100 if (file_info.compression_method == 0)
101 string_method="Stored";
102 else
103 if (file_info.compression_method == Z_DEFLATED)
104 {
105 uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
106 if (iLevel==0)
107 string_method="Defl:N";
108 else if (iLevel==1)
109 string_method="Defl:X";
110 else if ((iLevel==2) || (iLevel==3))
111 string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
112 }
113 else
114 if (file_info.compression_method == Z_BZIP2ED)
115 {
116 string_method="BZip2 ";
117 }
118 else
119 string_method="Unkn. ";
120
121 Display64BitsSize( file_info.uncompressed_size,7 );
122 Log( " %6s%c",string_method,charCrypt);
123 Display64BitsSize( file_info.compressed_size,7 );
124 Log( " %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n",
125 ratio,
126 (uLong)file_info.tmu_date.tm_mon + 1,
127 (uLong)file_info.tmu_date.tm_mday,
128 (uLong)file_info.tmu_date.tm_year % 100,
129 (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
130 (uLong)file_info.crc,filename_inzip);
131 if ((i+1) < gi.number_entry)
132 {
133 err = unzGoToNextFile( uf );
134 if (err != UNZ_OK)
135 {
136 Log( "error %d with zipfile in unzGoToNextFile\n",err);
137 break;
138 }
139 }
140
141 // Save the names of the files in the zip
142 list.push_back( filename_inzip );
143 }
144
145 // Close the zip file
146 unzClose( uf );
147}
148
149void CZip::ExtractFile( const string& zipfile, const string& location, const string& filename )
150{
151 uint32_t i;
152 int32_t err;
153 unzFile uf = NULL;
154 unz_global_info64 gi;
155
156 // Open the zip file
157 uf = unzOpen64( zipfile.c_str() );
158
159 if (uf != NULL)
160 {
161 // Get file info for the zip file
162 err = unzGetGlobalInfo64( uf,&gi );
163 if (err != UNZ_OK)
164 {
165 Log( "error %d with zipfile in unzGetGlobalInfo\n",err);
166 return;
167 }
168 }
169 else
170 {
171 Log( "error with zipfile %s in unzOpen64\n", zipfile.c_str() );
172 return;
173 }
174
175 for (i=0; i<gi.number_entry; i++)
176 {
177 char filename_inzip[256];
178 unz_file_info64 file_info;
179
180 err = unzGetCurrentFileInfo64( uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0 );
181 if (err != UNZ_OK)
182 {
183 Log( "error %d with zipfile in unzGetCurrentFileInfo\n",err);
184 break;
185 }
186
187 if (filename.compare(filename_inzip) == 0)
188 {
189 Extract( uf, location );
190 break;
191 }
192
193 if ((i+1) < gi.number_entry)
194 {
195 err = unzGoToNextFile( uf );
196 if (err != UNZ_OK)
197 {
198 Log( "error %d with zipfile in unzGoToNextFile\n",err);
199 break;
200 }
201 }
202 }
203
204 // Close the zip file
205 unzClose( uf );
206}
207
208void CZip::ExtractFiles( const string& zipfile, const string& location )
209{
210 uint16_t i;
211 int32_t err;
212 unzFile uf=NULL;
213 unz_global_info64 gi;
214
215 uf = unzOpen64( zipfile.c_str() );
216
217 if (uf != NULL)
218 {
219 err = unzGetGlobalInfo64( uf, &gi );
220 if (err != UNZ_OK)
221 {
222 Log( "error %d with zipfile in unzGetGlobalInfo \n", err );
223 return;
224 }
225 }
226 else
227 {
228 Log( "error with zipfile in unzOpen64 \n" );
229 return;
230 }
231
232 for (i=0;i<gi.number_entry;i++)
233 {
234 if (Extract( uf, location ) != UNZ_OK)
235 {
236 break;
237 }
238
239 if ((uint16_t)(i+1) < gi.number_entry)
240 {
241 // Go the next file
242 err = unzGoToNextFile( uf );
243 if (err != UNZ_OK)
244 {
245 Log( "error %d with zipfile in unzGoToNextFile\n", err );
246 break;
247 }
248 }
249 }
250
251 // Close the zip file
252 unzClose( uf );
253}
254
255#define WRITEBUFFERSIZE (8192)
256int32_t CZip::Extract( unzFile uf, const string& location )
257{
258 string write_filename;
259 void* buf;
260 char filename_inzip[256];
261 int32_t err=UNZ_OK;
262 FILE* fout=NULL;
263 unz_file_info64 file_info;
264
265 err = unzGetCurrentFileInfo64( uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0 );
266 if (err != UNZ_OK)
267 {
268 Log( "error %d with zipfile in unzGetCurrentFileInfo\n", err );
269 return err;
270 }
271
272 buf = (void*)malloc(WRITEBUFFERSIZE);
273 if (buf == NULL)
274 {
275 Log( "Error allocating memory\n" );
276 free(buf);
277 return UNZ_INTERNALERROR;
278 }
279
280 err = unzOpenCurrentFile( uf );
281 if (err != UNZ_OK)
282 {
283 Log( "error %d with zipfile in unzOpenCurrentFile\n", err );
284 free(buf);
285 return err;
286 }
287
288 write_filename = location + '/' + string(filename_inzip);
289
290 fout = fopen64( write_filename.c_str(), "wb" );
291
292 if (fout != NULL)
293 {
294 Log( " extracting: %s\n", write_filename.c_str() );
295
296 do {
297 err = unzReadCurrentFile( uf, buf, WRITEBUFFERSIZE );
298 if (err < 0)
299 {
300 Log( "error %d with zipfile in unzReadCurrentFile\n",err);
301 break;
302 }
303 if (err > 0)
304 {
305 if (fwrite( buf, err, 1, fout ) != 1)
306 {
307 Log( "error in writing extracted file\n" );
308 err = UNZ_ERRNO;
309 break;
310 }
311 }
312 }
313 while (err > 0);
314
315 if (fout)
316 {
317 fclose( fout );
318 }
319 }
320
321 if (err==UNZ_OK)
322 {
323 err = unzCloseCurrentFile( uf );
324 if (err != UNZ_OK)
325 {
326 Log( "error %d with zipfile in unzCloseCurrentFile\n",err);
327 }
328
329 AddUnzipFile( write_filename );
330 }
331 else
332 {
333 unzCloseCurrentFile( uf ); /* don't lose the error */
334 }
335
336 free(buf);
337 return err;
338}
339
340void CZip::Display64BitsSize(ZPOS64_T n, int size_char)
341{
342 /* to avoid compatibility problem , we do here the conversion */
343 char number[21];
344 int offset=19;
345 int pos_string = 19;
346 number[20]=0;
347 for (;;) {
348 number[offset]=(char)((n%10)+'0');
349 if (number[offset] != '0')
350 pos_string=offset;
351 n/=10;
352 if (offset==0)
353 break;
354 offset--;
355 }
356 {
357 int size_display_string = 19-pos_string;
358 while (size_char > size_display_string)
359 {
360 size_char--;
361 Log( " " );
362 }
363 }
364
365 Log( "%s",&number[pos_string]);
366}
367
368void CZip::AddUnzipFile( const string& filename )
369{
370 uint16_t i;
371
372 for (i=0; i<UnzipFiles.size(); i++)
373 {
374 if (UnzipFiles.at(i) == filename)
375 return;
376 }
377 UnzipFiles.push_back( filename );
378}
379
380void CZip::DelUnzipFiles( void )
381{
382 uint16_t i;
383
384 for (i=0; i<UnzipFiles.size(); i++)
385 {
386#if defined(DEBUG)
387 Log( "Removing file %s\n", UnzipFiles.at(i).c_str() );
388#endif
389 remove( UnzipFiles.at(i).c_str() );
390 }
391 UnzipFiles.clear();
392}
393
394int8_t CZip::SaveUnzipList( const string& location )
395{
396 uint8_t i;
397 ofstream fout;
398
399 fout.open(location.c_str(), ios_base::trunc);
400
401 if (!fout)
402 {
403 Log( "Failed to open ziplist at %s\n", location.c_str() );
404 return 1;
405 }
406
407 // Write out the profile
408 if (fout.is_open())
409 {
410 for (i=0; i<UnzipFiles.size(); i++)
411 {
412 if (UnzipFiles.at(i).length()>0)
413 {
414#if defined(DEBUG)
415 Log( "Saving file %s to ziplist\n", UnzipFiles.at(i).c_str());
416#endif
417 fout << UnzipFiles.at(i) << endl;
418 }
419 }
420 }
421
422 return 0;
423}
424
425int8_t CZip::LoadUnzipList( const string& location )
426{
427 string line;
428 ifstream fin;
429
430 fin.open(location.c_str(), ios_base::in);
431
432 if (!fin)
433 {
434 Log( "Failed to open unziplist at %s\n", location.c_str() );
435 return 0; // Dont stop the app if it cant be opened, default values will be used and then save to file.
436 }
437
438 UnzipFiles.clear();
439
440 // Read in the profile
441 if (fin.is_open())
442 {
443 while (!fin.eof())
444 {
445 getline(fin,line);
446
447 if (line.length() > 0)
448 {
449 UnzipFiles.push_back(line);
450 }
451 }
452 }
453
454 return 0;
455}
456