diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/unzip.c | 977 | ||||
-rw-r--r-- | src/common/unzip.h | 20 | ||||
-rw-r--r-- | src/plugins/Makefile.am | 71 | ||||
-rw-r--r-- | src/plugins/deb_extractor.c | 466 | ||||
-rw-r--r-- | src/plugins/nsf_extractor.c | 160 | ||||
-rw-r--r-- | src/plugins/nsfe_extractor.c | 330 | ||||
-rw-r--r-- | src/plugins/odf_extractor.c | 85 | ||||
-rw-r--r-- | src/plugins/sid_extractor.c | 198 | ||||
-rw-r--r-- | src/plugins/test_deb.c | 150 | ||||
-rw-r--r-- | src/plugins/test_odf.c | 100 | ||||
-rw-r--r-- | src/plugins/test_zip.c | 108 | ||||
-rw-r--r-- | src/plugins/testdata/deb_bzip2.deb | bin | 0 -> 49482 bytes | |||
-rw-r--r-- | src/plugins/testdata/odf_cg.odt | bin | 0 -> 28419 bytes | |||
-rw-r--r-- | src/plugins/testdata/zip_test.zip | bin | 0 -> 1904 bytes | |||
-rw-r--r-- | src/plugins/zip_extractor.c | 469 |
15 files changed, 1881 insertions, 1253 deletions
diff --git a/src/common/unzip.c b/src/common/unzip.c index 144c5ac..b4d4258 100644 --- a/src/common/unzip.c +++ b/src/common/unzip.c | |||
@@ -25,6 +25,39 @@ | |||
25 | * This code is based in part on | 25 | * This code is based in part on |
26 | * unzip 1.00 Copyright 1998-2003 Gilles Vollant | 26 | * unzip 1.00 Copyright 1998-2003 Gilles Vollant |
27 | * http://www.winimage.com/zLibDll" | 27 | * http://www.winimage.com/zLibDll" |
28 | * | ||
29 | * | ||
30 | * The filenames for each file in a zipfile are stored in two locations. | ||
31 | * There is one at the start of each entry, just before the compressed data, | ||
32 | * and another at the end in a 'central directory structure'. | ||
33 | * | ||
34 | * In order to catch self-extracting executables, we scan backwards from the end | ||
35 | * of the file looking for the central directory structure. The previous version | ||
36 | * of this went forewards through the local headers, but that only works for plain | ||
37 | * vanilla zip's and I don't feel like writing a special case for each of the dozen | ||
38 | * self-extracting executable stubs. | ||
39 | * | ||
40 | * This assumes that the zip file is considered to be non-corrupt/non-truncated. | ||
41 | * If it is truncated then it's not considered to be a zip and skipped. | ||
42 | * | ||
43 | * ZIP format description from appnote.iz and appnote.txt (more or less): | ||
44 | * | ||
45 | * (this is why you always need to put in the last floppy if you span disks) | ||
46 | * | ||
47 | * 0- 3 end of central dir signature 4 bytes (0x06054b50) P K ^E ^F | ||
48 | * 4- 5 number of this disk 2 bytes | ||
49 | * 6- 7 number of the disk with the | ||
50 | * start of the central directory 2 bytes | ||
51 | * 8- 9 total number of entries in | ||
52 | * the central dir on this disk 2 bytes | ||
53 | * 10-11 total number of entries in | ||
54 | * the central dir 2 bytes | ||
55 | * 12-15 size of the central directory 4 bytes | ||
56 | * 16-19 offset of start of central | ||
57 | * directory with respect to | ||
58 | * the starting disk number 4 bytes | ||
59 | * 20-21 zipfile comment length 2 bytes | ||
60 | * 22-?? zipfile comment (variable size) max length 65536 bytes | ||
28 | */ | 61 | */ |
29 | #include "platform.h" | 62 | #include "platform.h" |
30 | #include <ctype.h> | 63 | #include <ctype.h> |
@@ -49,27 +82,27 @@ | |||
49 | /** | 82 | /** |
50 | * IO callbacks for access to the ZIP data. | 83 | * IO callbacks for access to the ZIP data. |
51 | */ | 84 | */ |
52 | struct EXTRACTOR_UnzipFileFuncDefs | 85 | struct FileFuncDefs |
53 | { | 86 | { |
54 | /** | 87 | /** |
55 | * Callback for reading 'size' bytes from the ZIP archive into buf. | 88 | * Callback for reading 'size' bytes from the ZIP archive into buf. |
56 | */ | 89 | */ |
57 | uLong ( *zread_file) (voidpf opaque, void* buf, uLong size); | 90 | uLong (*zread_file) (voidpf opaque, void* buf, uLong size); |
58 | 91 | ||
59 | /** | 92 | /** |
60 | * Callback to obtain the current read offset in the ZIP archive. | 93 | * Callback to obtain the current read offset in the ZIP archive. |
61 | */ | 94 | */ |
62 | long ( *ztell_file) (voidpf opaque); | 95 | long (*ztell_file) (voidpf opaque); |
63 | 96 | ||
64 | /** | 97 | /** |
65 | * Callback for seeking to a different position in the ZIP archive. | 98 | * Callback for seeking to a different position in the ZIP archive. |
66 | */ | 99 | */ |
67 | long ( *zseek_file) (voidpf opaque, uLong offset, int origin); | 100 | long (*zseek_file) (voidpf opaque, uLong offset, int origin); |
68 | 101 | ||
69 | /** | 102 | /** |
70 | * Opaque argument to pass to all IO functions. | 103 | * Opaque argument to pass to all IO functions. |
71 | */ | 104 | */ |
72 | voidpf opaque; | 105 | voidpf opaque; |
73 | }; | 106 | }; |
74 | 107 | ||
75 | 108 | ||
@@ -119,6 +152,11 @@ struct GlobalInfo | |||
119 | * size of the global comment of the zipfile | 152 | * size of the global comment of the zipfile |
120 | */ | 153 | */ |
121 | uLong size_comment; | 154 | uLong size_comment; |
155 | |||
156 | /** | ||
157 | * offset of the global comment in the zipfile | ||
158 | */ | ||
159 | uLong offset_comment; | ||
122 | }; | 160 | }; |
123 | 161 | ||
124 | 162 | ||
@@ -198,9 +236,9 @@ struct FileInZipReadInfo | |||
198 | uLong rest_read_uncompressed; | 236 | uLong rest_read_uncompressed; |
199 | 237 | ||
200 | /** | 238 | /** |
201 | * IO functions. (FIXME: where is this assigned?) | 239 | * IO functions. |
202 | */ | 240 | */ |
203 | struct EXTRACTOR_UnzipFileFuncDefs z_filefunc; | 241 | struct FileFuncDefs z_filefunc; |
204 | 242 | ||
205 | /** | 243 | /** |
206 | * compression method (0==store) | 244 | * compression method (0==store) |
@@ -223,7 +261,7 @@ struct EXTRACTOR_UnzipFile | |||
223 | /** | 261 | /** |
224 | * io structore of the zipfile | 262 | * io structore of the zipfile |
225 | */ | 263 | */ |
226 | struct EXTRACTOR_UnzipFileFuncDefs z_filefunc; | 264 | struct FileFuncDefs z_filefunc; |
227 | 265 | ||
228 | /** | 266 | /** |
229 | * public global information | 267 | * public global information |
@@ -279,7 +317,7 @@ struct EXTRACTOR_UnzipFile | |||
279 | /** | 317 | /** |
280 | * structure about the current file if we are decompressing it | 318 | * structure about the current file if we are decompressing it |
281 | */ | 319 | */ |
282 | struct FileInZipReadInfo* pfile_in_zip_read; | 320 | struct FileInZipReadInfo *pfile_in_zip_read; |
283 | 321 | ||
284 | /** | 322 | /** |
285 | * Is the file encrypted? | 323 | * Is the file encrypted? |
@@ -292,33 +330,46 @@ struct EXTRACTOR_UnzipFile | |||
292 | * Read a byte from a gz_stream; update next_in and avail_in. Return EOF | 330 | * Read a byte from a gz_stream; update next_in and avail_in. Return EOF |
293 | * for end of file. | 331 | * for end of file. |
294 | * IN assertion: the stream s has been sucessfully opened for reading. | 332 | * IN assertion: the stream s has been sucessfully opened for reading. |
333 | * | ||
334 | * @param ffd functions for performing IO operations | ||
335 | * @param pi where to store the byte that was read | ||
336 | * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF | ||
295 | */ | 337 | */ |
296 | static int | 338 | static int |
297 | unzlocal_getByte (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def, | 339 | read_byte_from_ffd (const struct FileFuncDefs *ffd, |
298 | int *pi) | 340 | int *pi) |
299 | { | 341 | { |
300 | unsigned char c; | 342 | unsigned char c; |
301 | 343 | ||
302 | if (1 != ZREAD (*pzlib_filefunc_def, &c, 1)) | 344 | if (1 != ZREAD (*ffd, &c, 1)) |
303 | return EXTRACTOR_UNZIP_EOF; | 345 | return EXTRACTOR_UNZIP_EOF; |
304 | *pi = (int) c; | 346 | *pi = (int) c; |
305 | return EXTRACTOR_UNZIP_OK; | 347 | return EXTRACTOR_UNZIP_OK; |
306 | } | 348 | } |
307 | 349 | ||
308 | 350 | ||
351 | /** | ||
352 | * Read a short (2 bytes) from a gz_stream; update next_in and avail_in. Return EOF | ||
353 | * for end of file. | ||
354 | * IN assertion: the stream s has been sucessfully opened for reading. | ||
355 | * | ||
356 | * @param ffd functions for performing IO operations | ||
357 | * @param pi where to store the short that was read | ||
358 | * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF | ||
359 | */ | ||
309 | static int | 360 | static int |
310 | unzlocal_getShort (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def, | 361 | read_short_from_ffd (const struct FileFuncDefs *ffd, |
311 | uLong *pX) | 362 | uLong *pX) |
312 | { | 363 | { |
313 | uLong x; | 364 | uLong x; |
314 | int i; | 365 | int i; |
315 | int err; | 366 | int err; |
316 | 367 | ||
317 | *pX = 0; | 368 | *pX = 0; |
318 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 369 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
319 | return err; | 370 | return err; |
320 | x = (uLong) i; | 371 | x = (uLong) i; |
321 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 372 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
322 | return err; | 373 | return err; |
323 | x += ((uLong) i) << 8; | 374 | x += ((uLong) i) << 8; |
324 | *pX = x; | 375 | *pX = x; |
@@ -326,25 +377,34 @@ unzlocal_getShort (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def, | |||
326 | } | 377 | } |
327 | 378 | ||
328 | 379 | ||
380 | /** | ||
381 | * Read a 'long' (4 bytes) from a gz_stream; update next_in and avail_in. Return EOF | ||
382 | * for end of file. | ||
383 | * IN assertion: the stream s has been sucessfully opened for reading. | ||
384 | * | ||
385 | * @param ffd functions for performing IO operations | ||
386 | * @param pi where to store the long that was read | ||
387 | * @return EXTRACTOR_UNZIP_OK on success, or EXTRACTOR_UNZIP_EOF | ||
388 | */ | ||
329 | static int | 389 | static int |
330 | unzlocal_getLong (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def, | 390 | read_long_from_ffd (const struct FileFuncDefs *ffd, |
331 | uLong *pX) | 391 | uLong *pX) |
332 | { | 392 | { |
333 | uLong x; | 393 | uLong x; |
334 | int i; | 394 | int i; |
335 | int err; | 395 | int err; |
336 | 396 | ||
337 | *pX = 0; | 397 | *pX = 0; |
338 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 398 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
339 | return err; | 399 | return err; |
340 | x = (uLong) i; | 400 | x = (uLong) i; |
341 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 401 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
342 | return err; | 402 | return err; |
343 | x += ((uLong) i) << 8; | 403 | x += ((uLong) i) << 8; |
344 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 404 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
345 | return err; | 405 | return err; |
346 | x += ((uLong) i) << 16; | 406 | x += ((uLong) i) << 16; |
347 | if (EXTRACTOR_UNZIP_OK != (err = unzlocal_getByte (pzlib_filefunc_def, &i))) | 407 | if (EXTRACTOR_UNZIP_OK != (err = read_byte_from_ffd (ffd, &i))) |
348 | return err; | 408 | return err; |
349 | x += ((uLong) i) << 24; | 409 | x += ((uLong) i) << 24; |
350 | *pX = x; | 410 | *pX = x; |
@@ -366,7 +426,7 @@ unzlocal_getLong (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def, | |||
366 | 426 | ||
367 | 427 | ||
368 | /** | 428 | /** |
369 | * Compare two filename (fileName1,fileName2). | 429 | * Compare two filenames (fileName1, fileName2). |
370 | * | 430 | * |
371 | * @param filename1 name of first file | 431 | * @param filename1 name of first file |
372 | * @param filename2 name of second file | 432 | * @param filename2 name of second file |
@@ -394,27 +454,24 @@ EXTRACTOR_common_unzip_string_file_name_compare (const char* fileName1, | |||
394 | 454 | ||
395 | 455 | ||
396 | /** | 456 | /** |
457 | * Locate the central directory in the ZIP file. | ||
397 | * | 458 | * |
459 | * @param ffd IO functions | ||
460 | * @return offset of central directory, 0 on error | ||
398 | */ | 461 | */ |
399 | static uLong | 462 | static uLong |
400 | unzlocal_SearchCentralDir (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filefunc_def) | 463 | locate_central_directory (const struct FileFuncDefs *ffd) |
401 | { | 464 | { |
402 | unsigned char *buf; | 465 | unsigned char buf[BUFREADCOMMENT + 4]; |
403 | uLong uSizeFile; | 466 | uLong uSizeFile; |
404 | uLong uBackRead; | 467 | uLong uBackRead; |
405 | uLong uMaxBack = 0xffff; /* maximum size of global comment */ | 468 | uLong uMaxBack = 0xffff; /* maximum size of global comment */ |
406 | uLong uPosFound = 0; | ||
407 | 469 | ||
408 | if (0 != ZSEEK (*pzlib_filefunc_def, 0, SEEK_END)) | 470 | if (0 != ZSEEK (*ffd, 0, SEEK_END)) |
409 | return 0; | 471 | return 0; |
410 | uSizeFile = ZTELL (*pzlib_filefunc_def); | 472 | uSizeFile = ZTELL (*ffd); |
411 | |||
412 | if (uMaxBack > uSizeFile) | 473 | if (uMaxBack > uSizeFile) |
413 | uMaxBack = uSizeFile; | 474 | uMaxBack = uSizeFile; |
414 | |||
415 | if (NULL == (buf = malloc(BUFREADCOMMENT + 4))) | ||
416 | return 0; | ||
417 | |||
418 | uBackRead = 4; | 475 | uBackRead = 4; |
419 | while (uBackRead < uMaxBack) | 476 | while (uBackRead < uMaxBack) |
420 | { | 477 | { |
@@ -427,156 +484,153 @@ unzlocal_SearchCentralDir (const struct EXTRACTOR_UnzipFileFuncDefs* pzlib_filef | |||
427 | else | 484 | else |
428 | uBackRead += BUFREADCOMMENT; | 485 | uBackRead += BUFREADCOMMENT; |
429 | uReadPos = uSizeFile - uBackRead; | 486 | uReadPos = uSizeFile - uBackRead; |
430 | |||
431 | uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) | 487 | uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) |
432 | ? (BUFREADCOMMENT + 4) | 488 | ? (BUFREADCOMMENT + 4) |
433 | : (uSizeFile - uReadPos); | 489 | : (uSizeFile - uReadPos); |
434 | if (0 != ZSEEK (*pzlib_filefunc_def, uReadPos, SEEK_SET)) | 490 | if (0 != ZSEEK (*ffd, uReadPos, SEEK_SET)) |
435 | break; | 491 | break; |
436 | 492 | if (ZREAD (*ffd, buf, uReadSize) != uReadSize) | |
437 | if (ZREAD (*pzlib_filefunc_def, buf, uReadSize) != uReadSize) | ||
438 | break; | 493 | break; |
439 | |||
440 | i = (int) uReadSize - 3; | 494 | i = (int) uReadSize - 3; |
441 | while (i-- > 0) | 495 | while (i-- > 0) |
442 | if ( (0x50 == (*(buf+i))) && | 496 | if ( (0x50 == (*(buf+i))) && |
443 | (0x4b == (*(buf+i+1))) && | 497 | (0x4b == (*(buf+i+1))) && |
444 | (0x05 == (*(buf+i+2))) && | 498 | (0x05 == (*(buf+i+2))) && |
445 | (0x06 == (*(buf+i+3))) ) | 499 | (0x06 == (*(buf+i+3))) ) |
446 | { | 500 | return uReadPos + i; |
447 | uPosFound = uReadPos + i; | ||
448 | break; | ||
449 | } | ||
450 | if (0 != uPosFound) | ||
451 | break; | ||
452 | } | 501 | } |
453 | free (buf); | 502 | return 0; |
454 | return uPosFound; | ||
455 | } | 503 | } |
456 | 504 | ||
457 | 505 | ||
458 | /** | 506 | /** |
459 | * Translate date/time from Dos format to struct | 507 | * Translate date/time from Dos format to struct |
460 | * EXTRACTOR_UnzipDateTimeInfo (readable more easilty) | 508 | * EXTRACTOR_UnzipDateTimeInfo (readable more easilty) |
509 | * | ||
510 | * @param ulDosDate time in DOS format (input) | ||
511 | * @param ptm where to write time in readable format | ||
461 | */ | 512 | */ |
462 | static void | 513 | static void |
463 | unzlocal_DosDateToTmuDate (uLong ulDosDate, | 514 | dos_date_to_tmu_date (uLong ulDosDate, |
464 | struct EXTRACTOR_UnzipDateTimeInfo* ptm) | 515 | struct EXTRACTOR_UnzipDateTimeInfo* ptm) |
465 | { | 516 | { |
466 | uLong uDate; | 517 | uLong uDate; |
467 | 518 | ||
468 | uDate = (uLong) (ulDosDate >> 16); | 519 | uDate = (uLong) (ulDosDate >> 16); |
469 | ptm->tm_mday = (uInt) (uDate & 0x1f); | 520 | ptm->tm_mday = (uInt) (uDate & 0x1f); |
470 | ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1); | 521 | ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1); |
471 | ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980); | 522 | ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980); |
472 | ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800); | 523 | ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800); |
473 | ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20); | 524 | ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20); |
474 | ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f)); | 525 | ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f)); |
475 | } | 526 | } |
476 | 527 | ||
477 | 528 | ||
529 | /** | ||
530 | * Write info about the ZipFile in the *pglobal_info structure. | ||
531 | * No preparation of the structure is needed. | ||
532 | * | ||
533 | * @param file zipfile to manipulate | ||
534 | * @param pfile_info file information to initialize | ||
535 | * @param pfile_info_internal internal file information to initialize | ||
536 | * @param szFileName where to write the name of the current file | ||
537 | * @param fileNameBufferSize number of bytes available in szFileName | ||
538 | * @param extraField where to write extra data | ||
539 | * @param extraFieldBufferSize number of bytes available in extraField | ||
540 | * @param szComment where to write the comment on the current file | ||
541 | * @param commentBufferSize number of bytes available in szComment | ||
542 | * @return EXTRACTOR_UNZIP_OK if there is no problem. | ||
543 | */ | ||
478 | static int | 544 | static int |
479 | unzlocal_GetCurrentFileInfoInternal (struct EXTRACTOR_UnzipFile *s, | 545 | get_current_file_info (struct EXTRACTOR_UnzipFile *file, |
480 | struct EXTRACTOR_UnzipFileInfo *pfile_info, | 546 | struct EXTRACTOR_UnzipFileInfo *pfile_info, |
481 | struct UnzipFileInfoInternal *pfile_info_internal, | 547 | struct UnzipFileInfoInternal *pfile_info_internal, |
482 | char *szFileName, | 548 | char *szFileName, |
483 | uLong fileNameBufferSize, | 549 | uLong fileNameBufferSize, |
484 | void *extraField, | 550 | void *extraField, |
485 | uLong extraFieldBufferSize, | 551 | uLong extraFieldBufferSize, |
486 | char *szComment, | 552 | char *szComment, |
487 | uLong commentBufferSize) | 553 | uLong commentBufferSize) |
488 | { | 554 | { |
489 | struct EXTRACTOR_UnzipFileInfo file_info; | 555 | struct EXTRACTOR_UnzipFileInfo file_info; |
490 | struct UnzipFileInfoInternal file_info_internal; | 556 | struct UnzipFileInfoInternal file_info_internal; |
491 | int err = EXTRACTOR_UNZIP_OK; | ||
492 | uLong uMagic; | 557 | uLong uMagic; |
493 | long lSeek = 0; | 558 | long lSeek = 0; |
494 | 559 | ||
495 | if (s == NULL) | 560 | if (NULL == file) |
496 | return EXTRACTOR_UNZIP_PARAMERROR; | 561 | return EXTRACTOR_UNZIP_PARAMERROR; |
497 | if (0 != ZSEEK (s->z_filefunc, | 562 | if (0 != ZSEEK (file->z_filefunc, |
498 | s->pos_in_central_dir + s->byte_before_the_zipfile, | 563 | file->pos_in_central_dir + file->byte_before_the_zipfile, |
499 | SEEK_SET)) | 564 | SEEK_SET)) |
500 | err = EXTRACTOR_UNZIP_ERRNO; | 565 | return EXTRACTOR_UNZIP_ERRNO; |
501 | 566 | ||
502 | /* we check the magic */ | 567 | /* we check the magic */ |
503 | if (EXTRACTOR_UNZIP_OK == err) | 568 | if (EXTRACTOR_UNZIP_OK != |
504 | { | 569 | read_long_from_ffd(&file->z_filefunc, &uMagic)) |
505 | if (unzlocal_getLong(&s->z_filefunc, &uMagic) != EXTRACTOR_UNZIP_OK) | 570 | return EXTRACTOR_UNZIP_ERRNO; |
506 | err=EXTRACTOR_UNZIP_ERRNO; | 571 | if (0x02014b50 != uMagic) |
507 | else if (uMagic!=0x02014b50) | 572 | return EXTRACTOR_UNZIP_BADZIPFILE; |
508 | err=EXTRACTOR_UNZIP_BADZIPFILE; | ||
509 | } | ||
510 | if (unzlocal_getShort (&s->z_filefunc, &file_info.version) != EXTRACTOR_UNZIP_OK) | ||
511 | err = EXTRACTOR_UNZIP_ERRNO; | ||
512 | |||
513 | if (unzlocal_getShort(&s->z_filefunc, &file_info.version_needed) != EXTRACTOR_UNZIP_OK) | ||
514 | err=EXTRACTOR_UNZIP_ERRNO; | ||
515 | |||
516 | if (unzlocal_getShort(&s->z_filefunc, &file_info.flag) != EXTRACTOR_UNZIP_OK) | ||
517 | err=EXTRACTOR_UNZIP_ERRNO; | ||
518 | |||
519 | if (unzlocal_getShort(&s->z_filefunc, &file_info.compression_method) != EXTRACTOR_UNZIP_OK) | ||
520 | err=EXTRACTOR_UNZIP_ERRNO; | ||
521 | |||
522 | if (unzlocal_getLong(&s->z_filefunc, &file_info.dosDate) != EXTRACTOR_UNZIP_OK) | ||
523 | err=EXTRACTOR_UNZIP_ERRNO; | ||
524 | |||
525 | unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); | ||
526 | |||
527 | if (unzlocal_getLong(&s->z_filefunc, &file_info.crc) != EXTRACTOR_UNZIP_OK) | ||
528 | err=EXTRACTOR_UNZIP_ERRNO; | ||
529 | |||
530 | if (unzlocal_getLong(&s->z_filefunc, &file_info.compressed_size) != EXTRACTOR_UNZIP_OK) | ||
531 | err=EXTRACTOR_UNZIP_ERRNO; | ||
532 | |||
533 | if (unzlocal_getLong(&s->z_filefunc, &file_info.uncompressed_size) != EXTRACTOR_UNZIP_OK) | ||
534 | err=EXTRACTOR_UNZIP_ERRNO; | ||
535 | |||
536 | if (unzlocal_getShort(&s->z_filefunc, &file_info.size_filename) != EXTRACTOR_UNZIP_OK) | ||
537 | err=EXTRACTOR_UNZIP_ERRNO; | ||
538 | |||
539 | if (unzlocal_getShort(&s->z_filefunc, &file_info.size_file_extra) != EXTRACTOR_UNZIP_OK) | ||
540 | err=EXTRACTOR_UNZIP_ERRNO; | ||
541 | |||
542 | if (unzlocal_getShort(&s->z_filefunc, &file_info.size_file_comment) != EXTRACTOR_UNZIP_OK) | ||
543 | err=EXTRACTOR_UNZIP_ERRNO; | ||
544 | |||
545 | if (unzlocal_getShort(&s->z_filefunc, &file_info.disk_num_start) != EXTRACTOR_UNZIP_OK) | ||
546 | err=EXTRACTOR_UNZIP_ERRNO; | ||
547 | |||
548 | if (unzlocal_getShort(&s->z_filefunc, &file_info.internal_fa) != EXTRACTOR_UNZIP_OK) | ||
549 | err=EXTRACTOR_UNZIP_ERRNO; | ||
550 | |||
551 | if (unzlocal_getLong(&s->z_filefunc, &file_info.external_fa) != EXTRACTOR_UNZIP_OK) | ||
552 | err=EXTRACTOR_UNZIP_ERRNO; | ||
553 | 573 | ||
554 | if (unzlocal_getLong (&s->z_filefunc, | 574 | if ( (EXTRACTOR_UNZIP_OK != |
555 | &file_info_internal.offset_curfile) != EXTRACTOR_UNZIP_OK) | 575 | read_short_from_ffd (&file->z_filefunc, &file_info.version)) || |
556 | err = EXTRACTOR_UNZIP_ERRNO; | 576 | (EXTRACTOR_UNZIP_OK != |
577 | read_short_from_ffd (&file->z_filefunc, &file_info.version_needed)) || | ||
578 | (EXTRACTOR_UNZIP_OK != | ||
579 | read_short_from_ffd (&file->z_filefunc, &file_info.flag)) || | ||
580 | (EXTRACTOR_UNZIP_OK != | ||
581 | read_short_from_ffd (&file->z_filefunc, &file_info.compression_method)) || | ||
582 | (EXTRACTOR_UNZIP_OK != | ||
583 | read_long_from_ffd (&file->z_filefunc, &file_info.dosDate)) ) | ||
584 | return EXTRACTOR_UNZIP_ERRNO; | ||
585 | dos_date_to_tmu_date (file_info.dosDate, | ||
586 | &file_info.tmu_date); | ||
587 | if ( (EXTRACTOR_UNZIP_OK != | ||
588 | read_long_from_ffd(&file->z_filefunc, &file_info.crc)) || | ||
589 | (EXTRACTOR_UNZIP_OK != | ||
590 | read_long_from_ffd(&file->z_filefunc, &file_info.compressed_size)) || | ||
591 | (EXTRACTOR_UNZIP_OK != | ||
592 | read_long_from_ffd(&file->z_filefunc, &file_info.uncompressed_size)) || | ||
593 | (EXTRACTOR_UNZIP_OK != | ||
594 | read_short_from_ffd(&file->z_filefunc, &file_info.size_filename)) || | ||
595 | (EXTRACTOR_UNZIP_OK != | ||
596 | read_short_from_ffd(&file->z_filefunc, &file_info.size_file_extra)) || | ||
597 | (EXTRACTOR_UNZIP_OK != | ||
598 | read_short_from_ffd(&file->z_filefunc, &file_info.size_file_comment)) || | ||
599 | (EXTRACTOR_UNZIP_OK != | ||
600 | read_short_from_ffd(&file->z_filefunc, &file_info.disk_num_start)) || | ||
601 | (EXTRACTOR_UNZIP_OK != | ||
602 | read_short_from_ffd(&file->z_filefunc, &file_info.internal_fa)) || | ||
603 | (EXTRACTOR_UNZIP_OK != | ||
604 | read_long_from_ffd(&file->z_filefunc, &file_info.external_fa)) || | ||
605 | (EXTRACTOR_UNZIP_OK != | ||
606 | read_long_from_ffd (&file->z_filefunc, | ||
607 | &file_info_internal.offset_curfile)) ) | ||
608 | return EXTRACTOR_UNZIP_ERRNO; | ||
557 | 609 | ||
558 | lSeek += file_info.size_filename; | 610 | lSeek += file_info.size_filename; |
559 | if ((err==EXTRACTOR_UNZIP_OK) && (szFileName!=NULL)) | 611 | if (NULL != szFileName) |
560 | { | 612 | { |
561 | uLong uSizeRead; | 613 | uLong uSizeRead; |
614 | |||
562 | if (file_info.size_filename < fileNameBufferSize) | 615 | if (file_info.size_filename < fileNameBufferSize) |
563 | { | 616 | { |
564 | *(szFileName+file_info.size_filename) = '\0'; | 617 | *(szFileName + file_info.size_filename) = '\0'; |
565 | uSizeRead = file_info.size_filename; | 618 | uSizeRead = file_info.size_filename; |
566 | } | 619 | } |
567 | else | 620 | else |
568 | uSizeRead = fileNameBufferSize; | 621 | uSizeRead = fileNameBufferSize; |
569 | 622 | ||
570 | if ((file_info.size_filename > 0) && (fileNameBufferSize > 0)) | 623 | if ( (file_info.size_filename > 0) && |
571 | if (ZREAD(s->z_filefunc, szFileName, uSizeRead) != uSizeRead) | 624 | (fileNameBufferSize > 0) ) |
572 | err = EXTRACTOR_UNZIP_ERRNO; | 625 | if (ZREAD(file->z_filefunc, szFileName, uSizeRead) != uSizeRead) |
626 | return EXTRACTOR_UNZIP_ERRNO; | ||
573 | lSeek -= uSizeRead; | 627 | lSeek -= uSizeRead; |
574 | } | 628 | } |
575 | 629 | ||
576 | 630 | if (NULL != extraField) | |
577 | if ((err==EXTRACTOR_UNZIP_OK) && (extraField!=NULL)) | ||
578 | { | 631 | { |
579 | uLong uSizeRead; | 632 | uLong uSizeRead; |
633 | |||
580 | if (file_info.size_file_extra<extraFieldBufferSize) | 634 | if (file_info.size_file_extra<extraFieldBufferSize) |
581 | uSizeRead = file_info.size_file_extra; | 635 | uSizeRead = file_info.size_file_extra; |
582 | else | 636 | else |
@@ -584,53 +638,55 @@ unzlocal_GetCurrentFileInfoInternal (struct EXTRACTOR_UnzipFile *s, | |||
584 | 638 | ||
585 | if (0 != lSeek) | 639 | if (0 != lSeek) |
586 | { | 640 | { |
587 | if (0 == ZSEEK (s->z_filefunc, lSeek, SEEK_CUR)) | 641 | if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR)) |
588 | lSeek = 0; | 642 | lSeek = 0; |
589 | else | 643 | else |
590 | err = EXTRACTOR_UNZIP_ERRNO; | 644 | return EXTRACTOR_UNZIP_ERRNO; |
591 | } | 645 | } |
592 | if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) | 646 | if ( (file_info.size_file_extra > 0) && |
593 | if (ZREAD(s->z_filefunc, extraField,uSizeRead)!=uSizeRead) | 647 | (extraFieldBufferSize > 0) && |
594 | err=EXTRACTOR_UNZIP_ERRNO; | 648 | (ZREAD (file->z_filefunc, |
649 | extraField, | ||
650 | uSizeRead) != uSizeRead) ) | ||
651 | return EXTRACTOR_UNZIP_ERRNO; | ||
595 | lSeek += file_info.size_file_extra - uSizeRead; | 652 | lSeek += file_info.size_file_extra - uSizeRead; |
596 | } | 653 | } |
597 | else | 654 | else |
598 | lSeek+=file_info.size_file_extra; | 655 | lSeek += file_info.size_file_extra; |
599 | |||
600 | 656 | ||
601 | if ((err==EXTRACTOR_UNZIP_OK) && (szComment!=NULL)) | 657 | if (NULL != szComment) |
602 | { | 658 | { |
603 | uLong uSizeRead ; | 659 | uLong uSizeRead; |
604 | if (file_info.size_file_comment<commentBufferSize) | 660 | |
661 | if (file_info.size_file_comment < commentBufferSize) | ||
605 | { | 662 | { |
606 | *(szComment+file_info.size_file_comment)='\0'; | 663 | *(szComment+file_info.size_file_comment) = '\0'; |
607 | uSizeRead = file_info.size_file_comment; | 664 | uSizeRead = file_info.size_file_comment; |
608 | } | 665 | } |
609 | else | 666 | else |
610 | uSizeRead = commentBufferSize; | 667 | uSizeRead = commentBufferSize; |
611 | 668 | ||
612 | if (lSeek!=0) | 669 | if (0 != lSeek) |
613 | { | 670 | { |
614 | if (ZSEEK(s->z_filefunc, lSeek, SEEK_CUR)==0) | 671 | if (0 == ZSEEK (file->z_filefunc, lSeek, SEEK_CUR)) |
615 | lSeek=0; | 672 | lSeek = 0; |
616 | else | 673 | else |
617 | err=EXTRACTOR_UNZIP_ERRNO; | 674 | return EXTRACTOR_UNZIP_ERRNO; |
618 | } | 675 | } |
619 | if ((file_info.size_file_comment>0) && (commentBufferSize>0)) | 676 | if ( (file_info.size_file_comment > 0) && |
620 | if (ZREAD(s->z_filefunc, szComment,uSizeRead)!=uSizeRead) | 677 | (commentBufferSize > 0) && |
621 | err=EXTRACTOR_UNZIP_ERRNO; | 678 | (ZREAD (file->z_filefunc, szComment, uSizeRead) != uSizeRead) ) |
622 | lSeek+=file_info.size_file_comment - uSizeRead; | 679 | return EXTRACTOR_UNZIP_ERRNO; |
680 | lSeek += file_info.size_file_comment - uSizeRead; | ||
623 | } | 681 | } |
624 | else | 682 | else |
625 | lSeek+=file_info.size_file_comment; | 683 | lSeek += file_info.size_file_comment; |
626 | 684 | ||
627 | if ((err==EXTRACTOR_UNZIP_OK) && (pfile_info!=NULL)) | 685 | if (NULL != pfile_info) |
628 | *pfile_info=file_info; | 686 | *pfile_info = file_info; |
629 | 687 | if (NULL != pfile_info_internal) | |
630 | if ((err==EXTRACTOR_UNZIP_OK) && (pfile_info_internal!=NULL)) | 688 | *pfile_info_internal = file_info_internal; |
631 | *pfile_info_internal=file_info_internal; | 689 | return EXTRACTOR_UNZIP_OK; |
632 | |||
633 | return err; | ||
634 | } | 690 | } |
635 | 691 | ||
636 | 692 | ||
@@ -649,11 +705,11 @@ EXTRACTOR_common_unzip_go_to_first_file (struct EXTRACTOR_UnzipFile *file) | |||
649 | return EXTRACTOR_UNZIP_PARAMERROR; | 705 | return EXTRACTOR_UNZIP_PARAMERROR; |
650 | file->pos_in_central_dir = file->offset_central_dir; | 706 | file->pos_in_central_dir = file->offset_central_dir; |
651 | file->num_file = 0; | 707 | file->num_file = 0; |
652 | err = unzlocal_GetCurrentFileInfoInternal (file, | 708 | err = get_current_file_info (file, |
653 | &file->cur_file_info, | 709 | &file->cur_file_info, |
654 | &file->cur_file_info_internal, | 710 | &file->cur_file_info_internal, |
655 | NULL, 0, NULL, 0, NULL, 0); | 711 | NULL, 0, NULL, 0, NULL, 0); |
656 | file->current_file_ok = (err == EXTRACTOR_UNZIP_OK); | 712 | file->current_file_ok = (EXTRACTOR_UNZIP_OK == err); |
657 | return err; | 713 | return err; |
658 | } | 714 | } |
659 | 715 | ||
@@ -661,14 +717,14 @@ EXTRACTOR_common_unzip_go_to_first_file (struct EXTRACTOR_UnzipFile *file) | |||
661 | /** | 717 | /** |
662 | * Open a Zip file. | 718 | * Open a Zip file. |
663 | * | 719 | * |
664 | * @param pzlib_filefunc_def IO functions | 720 | * @param ffd IO functions |
665 | * @return NULL on error | 721 | * @return NULL on error |
666 | */ | 722 | */ |
667 | static struct EXTRACTOR_UnzipFile * | 723 | static struct EXTRACTOR_UnzipFile * |
668 | EXTRACTOR_common_unzip_open2 (struct EXTRACTOR_UnzipFileFuncDefs *pzlib_filefunc_def) | 724 | unzip_open_using_ffd (struct FileFuncDefs *ffd) |
669 | { | 725 | { |
670 | struct EXTRACTOR_UnzipFile us; | 726 | struct EXTRACTOR_UnzipFile us; |
671 | struct EXTRACTOR_UnzipFile *s; | 727 | struct EXTRACTOR_UnzipFile *file; |
672 | uLong central_pos; | 728 | uLong central_pos; |
673 | uLong uL; | 729 | uLong uL; |
674 | uLong number_disk; /* number of the current dist, used for | 730 | uLong number_disk; /* number of the current dist, used for |
@@ -678,78 +734,76 @@ EXTRACTOR_common_unzip_open2 (struct EXTRACTOR_UnzipFileFuncDefs *pzlib_filefunc | |||
678 | uLong number_entry_CD; /* total number of entries in | 734 | uLong number_entry_CD; /* total number of entries in |
679 | the central dir | 735 | the central dir |
680 | (same than number_entry on nospan) */ | 736 | (same than number_entry on nospan) */ |
681 | |||
682 | int err = EXTRACTOR_UNZIP_OK; | ||
683 | 737 | ||
684 | memset (&us, 0, sizeof(us)); | 738 | memset (&us, 0, sizeof(us)); |
685 | us.z_filefunc = *pzlib_filefunc_def; | 739 | us.z_filefunc = *ffd; |
686 | 740 | central_pos = locate_central_directory (&us.z_filefunc); | |
687 | central_pos = unzlocal_SearchCentralDir (&us.z_filefunc); | 741 | if (0 == central_pos) |
688 | if (central_pos==0) | 742 | return NULL; |
689 | err=EXTRACTOR_UNZIP_ERRNO; | 743 | if (0 != ZSEEK (us.z_filefunc, |
690 | 744 | central_pos, SEEK_SET)) | |
691 | if (ZSEEK(us.z_filefunc, | 745 | return NULL; |
692 | central_pos, SEEK_SET)!=0) | ||
693 | err=EXTRACTOR_UNZIP_ERRNO; | ||
694 | 746 | ||
695 | /* the signature, already checked */ | 747 | /* the signature, already checked */ |
696 | if (unzlocal_getLong(&us.z_filefunc, &uL)!=EXTRACTOR_UNZIP_OK) | 748 | if (EXTRACTOR_UNZIP_OK != |
697 | err=EXTRACTOR_UNZIP_ERRNO; | 749 | read_long_from_ffd (&us.z_filefunc, &uL)) |
750 | return NULL; | ||
698 | 751 | ||
699 | /* number of this disk */ | 752 | /* number of this disk */ |
700 | if (unzlocal_getShort(&us.z_filefunc, &number_disk)!=EXTRACTOR_UNZIP_OK) | 753 | if (EXTRACTOR_UNZIP_OK != |
701 | err=EXTRACTOR_UNZIP_ERRNO; | 754 | read_short_from_ffd (&us.z_filefunc, &number_disk)) |
755 | return NULL; | ||
702 | 756 | ||
703 | /* number of the disk with the start of the central directory */ | 757 | /* number of the disk with the start of the central directory */ |
704 | if (unzlocal_getShort(&us.z_filefunc, &number_disk_with_CD)!=EXTRACTOR_UNZIP_OK) | 758 | if (EXTRACTOR_UNZIP_OK != |
705 | err=EXTRACTOR_UNZIP_ERRNO; | 759 | read_short_from_ffd (&us.z_filefunc, &number_disk_with_CD)) |
760 | return NULL; | ||
706 | 761 | ||
707 | /* total number of entries in the central dir on this disk */ | 762 | /* total number of entries in the central dir on this disk */ |
708 | if (unzlocal_getShort(&us.z_filefunc, &us.gi.number_entry)!=EXTRACTOR_UNZIP_OK) | 763 | if (EXTRACTOR_UNZIP_OK != |
709 | err=EXTRACTOR_UNZIP_ERRNO; | 764 | read_short_from_ffd (&us.z_filefunc, &us.gi.number_entry)) |
765 | return NULL; | ||
710 | 766 | ||
711 | /* total number of entries in the central dir */ | 767 | /* total number of entries in the central dir */ |
712 | if (unzlocal_getShort(&us.z_filefunc, &number_entry_CD)!=EXTRACTOR_UNZIP_OK) | 768 | if (EXTRACTOR_UNZIP_OK != |
713 | err=EXTRACTOR_UNZIP_ERRNO; | 769 | read_short_from_ffd (&us.z_filefunc, &number_entry_CD)) |
770 | return NULL; | ||
714 | 771 | ||
715 | if ((number_entry_CD!=us.gi.number_entry) || | 772 | if ( (number_entry_CD != us.gi.number_entry) || |
716 | (number_disk_with_CD!=0) || | 773 | (0 != number_disk_with_CD) || |
717 | (number_disk!=0)) | 774 | (0 != number_disk) ) |
718 | err=EXTRACTOR_UNZIP_BADZIPFILE; | 775 | return NULL; |
719 | 776 | ||
720 | /* size of the central directory */ | 777 | /* size of the central directory */ |
721 | if (unzlocal_getLong(&us.z_filefunc, &us.size_central_dir)!=EXTRACTOR_UNZIP_OK) | 778 | if (EXTRACTOR_UNZIP_OK != |
722 | err=EXTRACTOR_UNZIP_ERRNO; | 779 | read_long_from_ffd (&us.z_filefunc, &us.size_central_dir)) |
780 | return NULL; | ||
723 | 781 | ||
724 | /* offset of start of central directory with respect to the | 782 | /* offset of start of central directory with respect to the |
725 | starting disk number */ | 783 | starting disk number */ |
726 | if (unzlocal_getLong(&us.z_filefunc, &us.offset_central_dir)!=EXTRACTOR_UNZIP_OK) | 784 | if (EXTRACTOR_UNZIP_OK != |
727 | err=EXTRACTOR_UNZIP_ERRNO; | 785 | read_long_from_ffd (&us.z_filefunc, &us.offset_central_dir)) |
786 | return NULL; | ||
728 | 787 | ||
729 | /* zipfile comment length */ | 788 | /* zipfile comment length */ |
730 | if (unzlocal_getShort(&us.z_filefunc, &us.gi.size_comment)!=EXTRACTOR_UNZIP_OK) | 789 | if (EXTRACTOR_UNZIP_OK != |
731 | err=EXTRACTOR_UNZIP_ERRNO; | 790 | read_short_from_ffd (&us.z_filefunc, &us.gi.size_comment)) |
732 | 791 | return NULL; | |
733 | if ((central_pos<us.offset_central_dir+us.size_central_dir) && | 792 | us.gi.offset_comment = ZTELL (us.z_filefunc); |
734 | (err==EXTRACTOR_UNZIP_OK)) | 793 | if ((central_pos < us.offset_central_dir + us.size_central_dir)) |
735 | err=EXTRACTOR_UNZIP_BADZIPFILE; | 794 | return NULL; |
736 | 795 | ||
737 | if (err!=EXTRACTOR_UNZIP_OK) | ||
738 | { | ||
739 | return NULL; | ||
740 | } | ||
741 | |||
742 | us.byte_before_the_zipfile = central_pos - | 796 | us.byte_before_the_zipfile = central_pos - |
743 | (us.offset_central_dir+us.size_central_dir); | 797 | (us.offset_central_dir + us.size_central_dir); |
744 | us.central_pos = central_pos; | 798 | us.central_pos = central_pos; |
745 | us.pfile_in_zip_read = NULL; | 799 | us.pfile_in_zip_read = NULL; |
746 | us.encrypted = 0; | 800 | us.encrypted = 0; |
747 | 801 | ||
748 | if (NULL == (s = malloc (sizeof(struct EXTRACTOR_UnzipFile)))) | 802 | if (NULL == (file = malloc (sizeof(struct EXTRACTOR_UnzipFile)))) |
749 | return NULL; | 803 | return NULL; |
750 | *s=us; | 804 | *file = us; |
751 | EXTRACTOR_common_unzip_go_to_first_file(s); | 805 | EXTRACTOR_common_unzip_go_to_first_file (file); |
752 | return s; | 806 | return file; |
753 | } | 807 | } |
754 | 808 | ||
755 | 809 | ||
@@ -759,48 +813,32 @@ EXTRACTOR_common_unzip_open2 (struct EXTRACTOR_UnzipFileFuncDefs *pzlib_filefunc | |||
759 | * @return EXTRACTOR_UNZIP_CRCERROR if all the file was read but the CRC is not good | 813 | * @return EXTRACTOR_UNZIP_CRCERROR if all the file was read but the CRC is not good |
760 | */ | 814 | */ |
761 | int | 815 | int |
762 | EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile * file) | 816 | EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile *file) |
763 | { | 817 | { |
764 | int err=EXTRACTOR_UNZIP_OK; | 818 | struct FileInZipReadInfo* pfile_in_zip_read_info; |
765 | 819 | int err = EXTRACTOR_UNZIP_OK; | |
766 | struct EXTRACTOR_UnzipFile* s; | 820 | |
767 | struct FileInZipReadInfo* pfile_in_zip_read_info; | 821 | if (NULL == file) |
768 | if (file==NULL) | 822 | return EXTRACTOR_UNZIP_PARAMERROR; |
769 | return EXTRACTOR_UNZIP_PARAMERROR; | 823 | if (NULL == (pfile_in_zip_read_info = file->pfile_in_zip_read)) |
770 | s=(struct EXTRACTOR_UnzipFile*)file; | 824 | return EXTRACTOR_UNZIP_PARAMERROR; |
771 | pfile_in_zip_read_info=s->pfile_in_zip_read; | 825 | if ( (0 == pfile_in_zip_read_info->rest_read_uncompressed) && |
772 | 826 | (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) ) | |
773 | if (pfile_in_zip_read_info==NULL) | 827 | err = EXTRACTOR_UNZIP_CRCERROR; |
774 | return EXTRACTOR_UNZIP_PARAMERROR; | 828 | if (NULL != pfile_in_zip_read_info->read_buffer) |
775 | 829 | free (pfile_in_zip_read_info->read_buffer); | |
776 | 830 | pfile_in_zip_read_info->read_buffer = NULL; | |
777 | if (pfile_in_zip_read_info->rest_read_uncompressed == 0) | 831 | if (pfile_in_zip_read_info->stream_initialised) |
778 | { | 832 | inflateEnd (&pfile_in_zip_read_info->stream); |
779 | if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) | 833 | pfile_in_zip_read_info->stream_initialised = 0; |
780 | err=EXTRACTOR_UNZIP_CRCERROR; | 834 | free (pfile_in_zip_read_info); |
781 | } | 835 | file->pfile_in_zip_read = NULL; |
782 | 836 | return err; | |
783 | |||
784 | if (NULL != pfile_in_zip_read_info->read_buffer) | ||
785 | free(pfile_in_zip_read_info->read_buffer); | ||
786 | pfile_in_zip_read_info->read_buffer = NULL; | ||
787 | if (pfile_in_zip_read_info->stream_initialised) | ||
788 | inflateEnd(&pfile_in_zip_read_info->stream); | ||
789 | |||
790 | pfile_in_zip_read_info->stream_initialised = 0; | ||
791 | free(pfile_in_zip_read_info); | ||
792 | |||
793 | s->pfile_in_zip_read=NULL; | ||
794 | |||
795 | return err; | ||
796 | } | 837 | } |
797 | 838 | ||
798 | 839 | ||
799 | /** | 840 | /** |
800 | * Close a ZipFile. If there is files inside the .Zip opened with | 841 | * Close a ZipFile. |
801 | * EXTRACTOR_common_unzip_open_current_file, these files MUST be | ||
802 | * closed with EXTRACTOR_common_unzip_close_current_file before | ||
803 | * calling EXTRACTOR_common_unzip_close. | ||
804 | * | 842 | * |
805 | * @param file zip file to close | 843 | * @param file zip file to close |
806 | * @return EXTRACTOR_UNZIP_OK if there is no problem. | 844 | * @return EXTRACTOR_UNZIP_OK if there is no problem. |
@@ -808,17 +846,40 @@ EXTRACTOR_common_unzip_close_current_file (struct EXTRACTOR_UnzipFile * file) | |||
808 | int | 846 | int |
809 | EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file) | 847 | EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file) |
810 | { | 848 | { |
811 | struct EXTRACTOR_UnzipFile* s; | 849 | if (NULL == file) |
812 | |||
813 | if (file==NULL) | ||
814 | return EXTRACTOR_UNZIP_PARAMERROR; | 850 | return EXTRACTOR_UNZIP_PARAMERROR; |
815 | s=(struct EXTRACTOR_UnzipFile*)file; | 851 | if (NULL != file->pfile_in_zip_read) |
816 | 852 | EXTRACTOR_common_unzip_close_current_file (file); | |
817 | if (s->pfile_in_zip_read!=NULL) | 853 | free (file); |
818 | EXTRACTOR_common_unzip_close_current_file(file); | 854 | return EXTRACTOR_UNZIP_OK; |
855 | } | ||
856 | |||
819 | 857 | ||
820 | free(s); | 858 | /** |
821 | return EXTRACTOR_UNZIP_OK; | 859 | * Obtain the global comment from a ZIP file. |
860 | * | ||
861 | * @param file unzip file to inspect | ||
862 | * @param comment where to copy the comment | ||
863 | * @param comment_len maximum number of bytes available in comment | ||
864 | * @return EXTRACTOR_UNZIP_OK on success | ||
865 | */ | ||
866 | int | ||
867 | EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file, | ||
868 | char *comment, | ||
869 | size_t comment_len) | ||
870 | { | ||
871 | if (NULL == file) | ||
872 | return EXTRACTOR_UNZIP_PARAMERROR; | ||
873 | if (comment_len > file->gi.size_comment) | ||
874 | comment_len = file->gi.size_comment + 1; | ||
875 | if (0 != | ||
876 | ZSEEK (file->z_filefunc, file->gi.offset_comment, SEEK_SET)) | ||
877 | return EXTRACTOR_UNZIP_ERRNO; | ||
878 | if (comment_len - 1 != | ||
879 | ZREAD (file->z_filefunc, comment, comment_len - 1)) | ||
880 | return EXTRACTOR_UNZIP_ERRNO; | ||
881 | comment[comment_len - 1] = '\0'; | ||
882 | return EXTRACTOR_UNZIP_OK; | ||
822 | } | 883 | } |
823 | 884 | ||
824 | 885 | ||
@@ -827,6 +888,7 @@ EXTRACTOR_common_unzip_close (struct EXTRACTOR_UnzipFile *file) | |||
827 | * No preparation of the structure is needed. | 888 | * No preparation of the structure is needed. |
828 | * | 889 | * |
829 | * @param file zipfile to manipulate | 890 | * @param file zipfile to manipulate |
891 | * @param pfile_info file information to initialize | ||
830 | * @param szFileName where to write the name of the current file | 892 | * @param szFileName where to write the name of the current file |
831 | * @param fileNameBufferSize number of bytes available in szFileName | 893 | * @param fileNameBufferSize number of bytes available in szFileName |
832 | * @param extraField where to write extra data | 894 | * @param extraField where to write extra data |
@@ -845,10 +907,10 @@ EXTRACTOR_common_unzip_get_current_file_info (struct EXTRACTOR_UnzipFile * file, | |||
845 | char *szComment, | 907 | char *szComment, |
846 | uLong commentBufferSize) | 908 | uLong commentBufferSize) |
847 | { | 909 | { |
848 | return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, | 910 | return get_current_file_info (file, pfile_info, NULL, |
849 | szFileName,fileNameBufferSize, | 911 | szFileName, fileNameBufferSize, |
850 | extraField,extraFieldBufferSize, | 912 | extraField, extraFieldBufferSize, |
851 | szComment,commentBufferSize); | 913 | szComment, commentBufferSize); |
852 | } | 914 | } |
853 | 915 | ||
854 | 916 | ||
@@ -860,27 +922,25 @@ EXTRACTOR_common_unzip_get_current_file_info (struct EXTRACTOR_UnzipFile * file, | |||
860 | * EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the actual file was the latest. | 922 | * EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE if the actual file was the latest. |
861 | */ | 923 | */ |
862 | int | 924 | int |
863 | EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile * file) | 925 | EXTRACTOR_common_unzip_go_to_next_file (struct EXTRACTOR_UnzipFile *file) |
864 | { | 926 | { |
865 | struct EXTRACTOR_UnzipFile* s; | 927 | int err; |
866 | int err; | 928 | |
867 | 929 | if (NULL == file) | |
868 | if (file==NULL) | 930 | return EXTRACTOR_UNZIP_PARAMERROR; |
869 | return EXTRACTOR_UNZIP_PARAMERROR; | 931 | if (! file->current_file_ok) |
870 | s=(struct EXTRACTOR_UnzipFile*)file; | 932 | return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; |
871 | if (!s->current_file_ok) | 933 | if (file->num_file + 1 == file->gi.number_entry) |
872 | return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; | 934 | return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; |
873 | if (s->num_file+1==s->gi.number_entry) | 935 | file->pos_in_central_dir += SIZECENTRALDIRITEM + file->cur_file_info.size_filename + |
874 | return EXTRACTOR_UNZIP_END_OF_LIST_OF_FILE; | 936 | file->cur_file_info.size_file_extra + file->cur_file_info.size_file_comment; |
875 | 937 | file->num_file++; | |
876 | s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + | 938 | err = get_current_file_info (file, |
877 | s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; | 939 | &file->cur_file_info, |
878 | s->num_file++; | 940 | &file->cur_file_info_internal, |
879 | err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, | 941 | NULL, 0, NULL, 0, NULL, 0); |
880 | &s->cur_file_info_internal, | 942 | file->current_file_ok = (EXTRACTOR_UNZIP_OK == err); |
881 | NULL,0,NULL,0,NULL,0); | 943 | return err; |
882 | s->current_file_ok = (err == EXTRACTOR_UNZIP_OK); | ||
883 | return err; | ||
884 | } | 944 | } |
885 | 945 | ||
886 | 946 | ||
@@ -925,20 +985,20 @@ EXTRACTOR_common_unzip_go_find_local_file (struct EXTRACTOR_UnzipFile *file, | |||
925 | 985 | ||
926 | while (EXTRACTOR_UNZIP_OK == err) | 986 | while (EXTRACTOR_UNZIP_OK == err) |
927 | { | 987 | { |
928 | char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; | 988 | char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1]; |
929 | 989 | ||
930 | err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL, | 990 | if (EXTRACTOR_UNZIP_OK != |
931 | szCurrentFileName, sizeof (szCurrentFileName) - 1, | 991 | (err = EXTRACTOR_common_unzip_get_current_file_info (file, NULL, |
932 | NULL, 0, NULL, 0); | 992 | szCurrentFileName, |
933 | if (EXTRACTOR_UNZIP_OK == err) | 993 | sizeof (szCurrentFileName) - 1, |
934 | { | 994 | NULL, 0, NULL, 0))) |
935 | if (0 == | 995 | break; |
936 | EXTRACTOR_common_unzip_string_file_name_compare (szCurrentFileName, | 996 | if (0 == |
937 | szFileName, | 997 | EXTRACTOR_common_unzip_string_file_name_compare (szCurrentFileName, |
938 | iCaseSensitivity)) | 998 | szFileName, |
939 | return EXTRACTOR_UNZIP_OK; | 999 | iCaseSensitivity)) |
940 | err = EXTRACTOR_common_unzip_go_to_next_file (file); | 1000 | return EXTRACTOR_UNZIP_OK; |
941 | } | 1001 | err = EXTRACTOR_common_unzip_go_to_next_file (file); |
942 | } | 1002 | } |
943 | 1003 | ||
944 | /* We failed, so restore the state of the 'current file' to where we | 1004 | /* We failed, so restore the state of the 'current file' to where we |
@@ -969,7 +1029,7 @@ EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, | |||
969 | { | 1029 | { |
970 | int err = EXTRACTOR_UNZIP_OK; | 1030 | int err = EXTRACTOR_UNZIP_OK; |
971 | uInt iRead = 0; | 1031 | uInt iRead = 0; |
972 | struct FileInZipReadInfo* pfile_in_zip_read_info; | 1032 | struct FileInZipReadInfo *pfile_in_zip_read_info; |
973 | 1033 | ||
974 | if (NULL == file) | 1034 | if (NULL == file) |
975 | return EXTRACTOR_UNZIP_PARAMERROR; | 1035 | return EXTRACTOR_UNZIP_PARAMERROR; |
@@ -980,7 +1040,7 @@ EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, | |||
980 | if (0 == len) | 1040 | if (0 == len) |
981 | return 0; | 1041 | return 0; |
982 | 1042 | ||
983 | pfile_in_zip_read_info->stream.next_out = (Bytef*) buf; | 1043 | pfile_in_zip_read_info->stream.next_out = (Bytef *) buf; |
984 | pfile_in_zip_read_info->stream.avail_out = (uInt) len; | 1044 | pfile_in_zip_read_info->stream.avail_out = (uInt) len; |
985 | if (len > pfile_in_zip_read_info->rest_read_uncompressed) | 1045 | if (len > pfile_in_zip_read_info->rest_read_uncompressed) |
986 | pfile_in_zip_read_info->stream.avail_out = | 1046 | pfile_in_zip_read_info->stream.avail_out = |
@@ -989,14 +1049,14 @@ EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, | |||
989 | while (pfile_in_zip_read_info->stream.avail_out > 0) | 1049 | while (pfile_in_zip_read_info->stream.avail_out > 0) |
990 | { | 1050 | { |
991 | if ( (0 == pfile_in_zip_read_info->stream.avail_in) && | 1051 | if ( (0 == pfile_in_zip_read_info->stream.avail_in) && |
992 | (pfile_in_zip_read_info->rest_read_compressed>0) ) | 1052 | (pfile_in_zip_read_info->rest_read_compressed > 0) ) |
993 | { | 1053 | { |
994 | uInt uReadThis = UNZ_BUFSIZE; | 1054 | uInt uReadThis = UNZ_BUFSIZE; |
995 | if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) | 1055 | if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) |
996 | uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed; | 1056 | uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed; |
997 | if (0 == uReadThis) | 1057 | if (0 == uReadThis) |
998 | return EXTRACTOR_UNZIP_EOF; | 1058 | return EXTRACTOR_UNZIP_EOF; |
999 | if (0 != | 1059 | if (0 != |
1000 | ZSEEK (pfile_in_zip_read_info->z_filefunc, | 1060 | ZSEEK (pfile_in_zip_read_info->z_filefunc, |
1001 | pfile_in_zip_read_info->pos_in_zipfile + | 1061 | pfile_in_zip_read_info->pos_in_zipfile + |
1002 | pfile_in_zip_read_info->byte_before_the_zipfile, | 1062 | pfile_in_zip_read_info->byte_before_the_zipfile, |
@@ -1008,78 +1068,75 @@ EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, | |||
1008 | return EXTRACTOR_UNZIP_ERRNO; | 1068 | return EXTRACTOR_UNZIP_ERRNO; |
1009 | 1069 | ||
1010 | pfile_in_zip_read_info->pos_in_zipfile += uReadThis; | 1070 | pfile_in_zip_read_info->pos_in_zipfile += uReadThis; |
1011 | pfile_in_zip_read_info->rest_read_compressed-=uReadThis; | 1071 | pfile_in_zip_read_info->rest_read_compressed -= uReadThis; |
1012 | pfile_in_zip_read_info->stream.next_in = | 1072 | pfile_in_zip_read_info->stream.next_in = |
1013 | (Bytef*)pfile_in_zip_read_info->read_buffer; | 1073 | (Bytef *) pfile_in_zip_read_info->read_buffer; |
1014 | pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; | 1074 | pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis; |
1015 | } | 1075 | } |
1016 | 1076 | ||
1017 | if (pfile_in_zip_read_info->compression_method==0) | 1077 | if (0 == pfile_in_zip_read_info->compression_method) |
1018 | { | 1078 | { |
1019 | uInt uDoCopy; | 1079 | uInt uDoCopy; |
1020 | uInt i; | 1080 | |
1021 | 1081 | if ( (0 == pfile_in_zip_read_info->stream.avail_in) && | |
1022 | if ((pfile_in_zip_read_info->stream.avail_in == 0) && | 1082 | (0 == pfile_in_zip_read_info->rest_read_compressed) ) |
1023 | (pfile_in_zip_read_info->rest_read_compressed == 0)) | 1083 | return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead; |
1024 | return (iRead==0) ? EXTRACTOR_UNZIP_EOF : iRead; | 1084 | |
1025 | 1085 | if (pfile_in_zip_read_info->stream.avail_out < | |
1026 | if (pfile_in_zip_read_info->stream.avail_out < | 1086 | pfile_in_zip_read_info->stream.avail_in) |
1027 | pfile_in_zip_read_info->stream.avail_in) | 1087 | uDoCopy = pfile_in_zip_read_info->stream.avail_out; |
1028 | uDoCopy = pfile_in_zip_read_info->stream.avail_out ; | 1088 | else |
1029 | else | 1089 | uDoCopy = pfile_in_zip_read_info->stream.avail_in; |
1030 | uDoCopy = pfile_in_zip_read_info->stream.avail_in ; | 1090 | memcpy (pfile_in_zip_read_info->stream.next_out, |
1031 | 1091 | pfile_in_zip_read_info->stream.next_in, | |
1032 | for (i=0;i<uDoCopy;i++) | 1092 | uDoCopy); |
1033 | *(pfile_in_zip_read_info->stream.next_out+i) = | 1093 | pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, |
1034 | *(pfile_in_zip_read_info->stream.next_in+i); | 1094 | pfile_in_zip_read_info->stream.next_out, |
1035 | 1095 | uDoCopy); | |
1036 | pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, | 1096 | pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy; |
1037 | pfile_in_zip_read_info->stream.next_out, | 1097 | pfile_in_zip_read_info->stream.avail_in -= uDoCopy; |
1038 | uDoCopy); | 1098 | pfile_in_zip_read_info->stream.avail_out -= uDoCopy; |
1039 | pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; | 1099 | pfile_in_zip_read_info->stream.next_out += uDoCopy; |
1040 | pfile_in_zip_read_info->stream.avail_in -= uDoCopy; | 1100 | pfile_in_zip_read_info->stream.next_in += uDoCopy; |
1041 | pfile_in_zip_read_info->stream.avail_out -= uDoCopy; | 1101 | pfile_in_zip_read_info->stream.total_out += uDoCopy; |
1042 | pfile_in_zip_read_info->stream.next_out += uDoCopy; | 1102 | iRead += uDoCopy; |
1043 | pfile_in_zip_read_info->stream.next_in += uDoCopy; | 1103 | } |
1044 | pfile_in_zip_read_info->stream.total_out += uDoCopy; | 1104 | else |
1045 | iRead += uDoCopy; | 1105 | { |
1046 | } | 1106 | uLong uTotalOutBefore; |
1047 | else | 1107 | uLong uTotalOutAfter; |
1048 | { | 1108 | const Bytef *bufBefore; |
1049 | uLong uTotalOutBefore; | 1109 | uLong uOutThis; |
1050 | uLong uTotalOutAfter; | 1110 | int flush = Z_SYNC_FLUSH; |
1051 | const Bytef *bufBefore; | 1111 | |
1052 | uLong uOutThis; | 1112 | uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; |
1053 | int flush = Z_SYNC_FLUSH; | 1113 | bufBefore = pfile_in_zip_read_info->stream.next_out; |
1054 | 1114 | ||
1055 | uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; | 1115 | /* |
1056 | bufBefore = pfile_in_zip_read_info->stream.next_out; | 1116 | if ((pfile_in_zip_read_info->rest_read_uncompressed == |
1057 | 1117 | pfile_in_zip_read_info->stream.avail_out) && | |
1058 | /* | 1118 | (pfile_in_zip_read_info->rest_read_compressed == 0)) |
1059 | if ((pfile_in_zip_read_info->rest_read_uncompressed == | 1119 | flush = Z_FINISH; |
1060 | pfile_in_zip_read_info->stream.avail_out) && | 1120 | */ |
1061 | (pfile_in_zip_read_info->rest_read_compressed == 0)) | 1121 | err = inflate (&pfile_in_zip_read_info->stream, flush); |
1062 | flush = Z_FINISH; | 1122 | |
1063 | */ | 1123 | uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; |
1064 | err = inflate(&pfile_in_zip_read_info->stream,flush); | 1124 | uOutThis = uTotalOutAfter-uTotalOutBefore; |
1065 | 1125 | ||
1066 | uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; | 1126 | pfile_in_zip_read_info->crc32 = |
1067 | uOutThis = uTotalOutAfter-uTotalOutBefore; | 1127 | crc32 (pfile_in_zip_read_info->crc32, bufBefore, |
1068 | 1128 | (uInt) (uOutThis)); | |
1069 | pfile_in_zip_read_info->crc32 = | 1129 | |
1070 | crc32(pfile_in_zip_read_info->crc32,bufBefore, | 1130 | pfile_in_zip_read_info->rest_read_uncompressed -= |
1071 | (uInt)(uOutThis)); | 1131 | uOutThis; |
1072 | 1132 | ||
1073 | pfile_in_zip_read_info->rest_read_uncompressed -= | 1133 | iRead += (uInt) (uTotalOutAfter - uTotalOutBefore); |
1074 | uOutThis; | 1134 | |
1075 | 1135 | if (Z_STREAM_END == err) | |
1076 | iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); | 1136 | return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead; |
1077 | 1137 | if (Z_OK != err) | |
1078 | if (Z_STREAM_END == err) | 1138 | break; |
1079 | return (0 == iRead) ? EXTRACTOR_UNZIP_EOF : iRead; | 1139 | } |
1080 | if (Z_OK != err) | ||
1081 | break; | ||
1082 | } | ||
1083 | } | 1140 | } |
1084 | 1141 | ||
1085 | if (Z_OK == err) | 1142 | if (Z_OK == err) |
@@ -1089,24 +1146,28 @@ EXTRACTOR_common_unzip_read_current_file (struct EXTRACTOR_UnzipFile *file, | |||
1089 | 1146 | ||
1090 | 1147 | ||
1091 | /** | 1148 | /** |
1092 | * Read the local header of the current zipfile | 1149 | * Read the local header of the current zipfile. Check the coherency of |
1093 | * Check the coherency of the local header and info in the end of central | 1150 | * the local header and info in the end of central directory about |
1094 | * directory about this file | 1151 | * this file. Store in *piSizeVar the size of extra info in local |
1095 | * store in *piSizeVar the size of extra info in local header | 1152 | * header (filename and size of extra field data) |
1096 | * (filename and size of extra field data) | 1153 | * |
1154 | * @param file zipfile to process | ||
1155 | * @param piSizeVar where to store the size of the extra info | ||
1156 | * @param poffset_local_extrafield where to store the offset of the local extrafield | ||
1157 | * @param psoze_local_extrafield where to store the size of the local extrafield | ||
1158 | * @return EXTRACTOR_UNZIP_OK on success | ||
1097 | */ | 1159 | */ |
1098 | static int | 1160 | static int |
1099 | unzlocal_CheckCurrentFileCoherencyHeader (struct EXTRACTOR_UnzipFile *file, | 1161 | parse_current_file_coherency_header (struct EXTRACTOR_UnzipFile *file, |
1100 | uInt *piSizeVar, | 1162 | uInt *piSizeVar, |
1101 | uLong *poffset_local_extrafield, | 1163 | uLong *poffset_local_extrafield, |
1102 | uInt *psize_local_extrafield) | 1164 | uInt *psize_local_extrafield) |
1103 | { | 1165 | { |
1104 | uLong uMagic; | 1166 | uLong uMagic; |
1105 | uLong uData; | 1167 | uLong uData; |
1106 | uLong uFlags; | 1168 | uLong uFlags; |
1107 | uLong size_filename; | 1169 | uLong size_filename; |
1108 | uLong size_extra_field; | 1170 | uLong size_extra_field; |
1109 | int err = EXTRACTOR_UNZIP_OK; | ||
1110 | 1171 | ||
1111 | *piSizeVar = 0; | 1172 | *piSizeVar = 0; |
1112 | *poffset_local_extrafield = 0; | 1173 | *poffset_local_extrafield = 0; |
@@ -1118,76 +1179,61 @@ unzlocal_CheckCurrentFileCoherencyHeader (struct EXTRACTOR_UnzipFile *file, | |||
1118 | SEEK_SET)) | 1179 | SEEK_SET)) |
1119 | return EXTRACTOR_UNZIP_ERRNO; | 1180 | return EXTRACTOR_UNZIP_ERRNO; |
1120 | if (EXTRACTOR_UNZIP_OK != | 1181 | if (EXTRACTOR_UNZIP_OK != |
1121 | unzlocal_getLong (&file->z_filefunc, | 1182 | read_long_from_ffd (&file->z_filefunc, |
1122 | &uMagic)) | 1183 | &uMagic)) |
1123 | err = EXTRACTOR_UNZIP_ERRNO; | 1184 | return EXTRACTOR_UNZIP_ERRNO; |
1124 | else if (0x04034b50 != uMagic) | 1185 | if (0x04034b50 != uMagic) |
1125 | err = EXTRACTOR_UNZIP_BADZIPFILE; | 1186 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1126 | if ( (EXTRACTOR_UNZIP_OK != | 1187 | if ( (EXTRACTOR_UNZIP_OK != |
1127 | unzlocal_getShort (&file->z_filefunc, &uData)) || | 1188 | read_short_from_ffd (&file->z_filefunc, &uData)) || |
1128 | (EXTRACTOR_UNZIP_OK != | 1189 | (EXTRACTOR_UNZIP_OK != |
1129 | unzlocal_getShort (&file->z_filefunc, &uFlags)) ) | 1190 | read_short_from_ffd (&file->z_filefunc, &uFlags)) ) |
1130 | err = EXTRACTOR_UNZIP_ERRNO; | 1191 | return EXTRACTOR_UNZIP_ERRNO; |
1131 | 1192 | if (EXTRACTOR_UNZIP_OK != read_short_from_ffd (&file->z_filefunc, &uData)) | |
1132 | if (EXTRACTOR_UNZIP_OK != unzlocal_getShort (&file->z_filefunc, &uData)) | 1193 | return EXTRACTOR_UNZIP_ERRNO; |
1133 | err = EXTRACTOR_UNZIP_ERRNO; | 1194 | if (uData != file->cur_file_info.compression_method) |
1134 | else if ((EXTRACTOR_UNZIP_OK == err) && | 1195 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1135 | (uData != file->cur_file_info.compression_method)) | 1196 | if ( (0 != file->cur_file_info.compression_method) && |
1136 | err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1137 | |||
1138 | if ( (EXTRACTOR_UNZIP_OK == err) && | ||
1139 | (0 != file->cur_file_info.compression_method) && | ||
1140 | (Z_DEFLATED != file->cur_file_info.compression_method) ) | 1197 | (Z_DEFLATED != file->cur_file_info.compression_method) ) |
1141 | err = EXTRACTOR_UNZIP_BADZIPFILE; | 1198 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1142 | |||
1143 | if (EXTRACTOR_UNZIP_OK != | 1199 | if (EXTRACTOR_UNZIP_OK != |
1144 | unzlocal_getLong (&file->z_filefunc, &uData)) /* date/time */ | 1200 | read_long_from_ffd (&file->z_filefunc, &uData)) /* date/time */ |
1145 | err = EXTRACTOR_UNZIP_ERRNO; | 1201 | return EXTRACTOR_UNZIP_ERRNO; |
1146 | |||
1147 | if (EXTRACTOR_UNZIP_OK != | 1202 | if (EXTRACTOR_UNZIP_OK != |
1148 | unzlocal_getLong (&file->z_filefunc, &uData)) /* crc */ | 1203 | read_long_from_ffd (&file->z_filefunc, &uData)) /* crc */ |
1149 | err = EXTRACTOR_UNZIP_ERRNO; | 1204 | return EXTRACTOR_UNZIP_ERRNO; |
1150 | else if ( (EXTRACTOR_UNZIP_OK == err) && | 1205 | if ( (uData != file->cur_file_info.crc) && |
1151 | (uData != file->cur_file_info.crc) && | 1206 | (0 == (uFlags & 8)) ) |
1152 | (0 == (uFlags & 8)) ) | 1207 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1153 | err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1154 | |||
1155 | if (EXTRACTOR_UNZIP_OK != | 1208 | if (EXTRACTOR_UNZIP_OK != |
1156 | unzlocal_getLong(&file->z_filefunc, &uData)) /* size compr */ | 1209 | read_long_from_ffd(&file->z_filefunc, &uData)) /* size compr */ |
1157 | err = EXTRACTOR_UNZIP_ERRNO; | 1210 | return EXTRACTOR_UNZIP_ERRNO; |
1158 | else if ( (EXTRACTOR_UNZIP_OK == err) && | 1211 | if ( (uData != file->cur_file_info.compressed_size) && |
1159 | (uData != file->cur_file_info.compressed_size) && | 1212 | (0 == (uFlags & 8)) ) |
1160 | (0 == (uFlags & 8)) ) | 1213 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1161 | err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1162 | |||
1163 | if (EXTRACTOR_UNZIP_OK != | 1214 | if (EXTRACTOR_UNZIP_OK != |
1164 | unzlocal_getLong (&file->z_filefunc, | 1215 | read_long_from_ffd (&file->z_filefunc, |
1165 | &uData)) /* size uncompr */ | 1216 | &uData)) /* size uncompr */ |
1166 | err = EXTRACTOR_UNZIP_ERRNO; | 1217 | return EXTRACTOR_UNZIP_ERRNO; |
1167 | else if ( (EXTRACTOR_UNZIP_OK == err) && | 1218 | if ( (uData != file->cur_file_info.uncompressed_size) && |
1168 | (uData != file->cur_file_info.uncompressed_size) && | 1219 | (0 == (uFlags & 8))) |
1169 | (0 == (uFlags & 8))) | 1220 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1170 | err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1171 | |||
1172 | if (EXTRACTOR_UNZIP_OK != | 1221 | if (EXTRACTOR_UNZIP_OK != |
1173 | unzlocal_getShort (&file->z_filefunc, &size_filename)) | 1222 | read_short_from_ffd (&file->z_filefunc, &size_filename)) |
1174 | err = EXTRACTOR_UNZIP_ERRNO; | 1223 | return EXTRACTOR_UNZIP_ERRNO; |
1175 | else if ( (EXTRACTOR_UNZIP_OK == err) && | 1224 | if (size_filename != file->cur_file_info.size_filename) |
1176 | (size_filename != file->cur_file_info.size_filename) ) | 1225 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1177 | err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1178 | |||
1179 | *piSizeVar += (uInt) size_filename; | 1226 | *piSizeVar += (uInt) size_filename; |
1180 | |||
1181 | if (EXTRACTOR_UNZIP_OK != | 1227 | if (EXTRACTOR_UNZIP_OK != |
1182 | unzlocal_getShort (&file->z_filefunc, | 1228 | read_short_from_ffd (&file->z_filefunc, |
1183 | &size_extra_field)) | 1229 | &size_extra_field)) |
1184 | err = EXTRACTOR_UNZIP_ERRNO; | 1230 | return EXTRACTOR_UNZIP_ERRNO; |
1185 | *poffset_local_extrafield = file->cur_file_info_internal.offset_curfile + | 1231 | *poffset_local_extrafield = file->cur_file_info_internal.offset_curfile + |
1186 | SIZEZIPLOCALHEADER + size_filename; | 1232 | SIZEZIPLOCALHEADER + size_filename; |
1187 | *psize_local_extrafield = (uInt) size_extra_field; | 1233 | *psize_local_extrafield = (uInt) size_extra_field; |
1188 | *piSizeVar += (uInt)size_extra_field; | 1234 | *piSizeVar += (uInt)size_extra_field; |
1189 | 1235 | ||
1190 | return err; | 1236 | return EXTRACTOR_UNZIP_OK; |
1191 | } | 1237 | } |
1192 | 1238 | ||
1193 | 1239 | ||
@@ -1200,7 +1246,7 @@ unzlocal_CheckCurrentFileCoherencyHeader (struct EXTRACTOR_UnzipFile *file, | |||
1200 | int | 1246 | int |
1201 | EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) | 1247 | EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) |
1202 | { | 1248 | { |
1203 | int err = EXTRACTOR_UNZIP_OK; | 1249 | int err; |
1204 | uInt iSizeVar; | 1250 | uInt iSizeVar; |
1205 | struct FileInZipReadInfo *pfile_in_zip_read_info; | 1251 | struct FileInZipReadInfo *pfile_in_zip_read_info; |
1206 | uLong offset_local_extrafield; /* offset of the local extra field */ | 1252 | uLong offset_local_extrafield; /* offset of the local extra field */ |
@@ -1213,14 +1259,14 @@ EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) | |||
1213 | if (NULL != file->pfile_in_zip_read) | 1259 | if (NULL != file->pfile_in_zip_read) |
1214 | EXTRACTOR_common_unzip_close_current_file (file); | 1260 | EXTRACTOR_common_unzip_close_current_file (file); |
1215 | if (EXTRACTOR_UNZIP_OK != | 1261 | if (EXTRACTOR_UNZIP_OK != |
1216 | unzlocal_CheckCurrentFileCoherencyHeader (file, | 1262 | parse_current_file_coherency_header (file, |
1217 | &iSizeVar, | 1263 | &iSizeVar, |
1218 | &offset_local_extrafield, | 1264 | &offset_local_extrafield, |
1219 | &size_local_extrafield)) | 1265 | &size_local_extrafield)) |
1220 | return EXTRACTOR_UNZIP_BADZIPFILE; | 1266 | return EXTRACTOR_UNZIP_BADZIPFILE; |
1221 | if (NULL == (pfile_in_zip_read_info = malloc(sizeof(struct FileInZipReadInfo)))) | 1267 | if (NULL == (pfile_in_zip_read_info = malloc (sizeof(struct FileInZipReadInfo)))) |
1222 | return EXTRACTOR_UNZIP_INTERNALERROR; | 1268 | return EXTRACTOR_UNZIP_INTERNALERROR; |
1223 | if (NULL == (pfile_in_zip_read_info->read_buffer = malloc(UNZ_BUFSIZE))) | 1269 | if (NULL == (pfile_in_zip_read_info->read_buffer = malloc (UNZ_BUFSIZE))) |
1224 | { | 1270 | { |
1225 | free (pfile_in_zip_read_info); | 1271 | free (pfile_in_zip_read_info); |
1226 | return EXTRACTOR_UNZIP_INTERNALERROR; | 1272 | return EXTRACTOR_UNZIP_INTERNALERROR; |
@@ -1232,7 +1278,11 @@ EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) | |||
1232 | 1278 | ||
1233 | if ( (0 != file->cur_file_info.compression_method) && | 1279 | if ( (0 != file->cur_file_info.compression_method) && |
1234 | (Z_DEFLATED != file->cur_file_info.compression_method) ) | 1280 | (Z_DEFLATED != file->cur_file_info.compression_method) ) |
1235 | err = EXTRACTOR_UNZIP_BADZIPFILE; | 1281 | { |
1282 | // err = EXTRACTOR_UNZIP_BADZIPFILE; | ||
1283 | // FIXME: we don't do anything with this 'err' code. | ||
1284 | // Can this happen? Should we abort in this case? | ||
1285 | } | ||
1236 | 1286 | ||
1237 | pfile_in_zip_read_info->crc32_wait = file->cur_file_info.crc; | 1287 | pfile_in_zip_read_info->crc32_wait = file->cur_file_info.crc; |
1238 | pfile_in_zip_read_info->crc32 = 0; | 1288 | pfile_in_zip_read_info->crc32 = 0; |
@@ -1240,8 +1290,7 @@ EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) | |||
1240 | pfile_in_zip_read_info->z_filefunc = file->z_filefunc; | 1290 | pfile_in_zip_read_info->z_filefunc = file->z_filefunc; |
1241 | pfile_in_zip_read_info->byte_before_the_zipfile = file->byte_before_the_zipfile; | 1291 | pfile_in_zip_read_info->byte_before_the_zipfile = file->byte_before_the_zipfile; |
1242 | pfile_in_zip_read_info->stream.total_out = 0; | 1292 | pfile_in_zip_read_info->stream.total_out = 0; |
1243 | 1293 | if (Z_DEFLATED == file->cur_file_info.compression_method) | |
1244 | if (file->cur_file_info.compression_method==Z_DEFLATED) | ||
1245 | { | 1294 | { |
1246 | pfile_in_zip_read_info->stream.zalloc = (alloc_func) NULL; | 1295 | pfile_in_zip_read_info->stream.zalloc = (alloc_func) NULL; |
1247 | pfile_in_zip_read_info->stream.zfree = (free_func) NULL; | 1296 | pfile_in_zip_read_info->stream.zfree = (free_func) NULL; |
@@ -1270,11 +1319,19 @@ EXTRACTOR_common_unzip_open_current_file (struct EXTRACTOR_UnzipFile *file) | |||
1270 | iSizeVar; | 1319 | iSizeVar; |
1271 | pfile_in_zip_read_info->stream.avail_in = 0; | 1320 | pfile_in_zip_read_info->stream.avail_in = 0; |
1272 | file->pfile_in_zip_read = pfile_in_zip_read_info; | 1321 | file->pfile_in_zip_read = pfile_in_zip_read_info; |
1273 | |||
1274 | return EXTRACTOR_UNZIP_OK; | 1322 | return EXTRACTOR_UNZIP_OK; |
1275 | } | 1323 | } |
1276 | 1324 | ||
1277 | 1325 | ||
1326 | /** | ||
1327 | * Callback to perform read operation using LE API. | ||
1328 | * Note that partial reads are not allowed. | ||
1329 | * | ||
1330 | * @param opaque the 'struct EXTRACTOR_ExtractContext' | ||
1331 | * @param buf where to write bytes read | ||
1332 | * @param size number of bytes desired | ||
1333 | * @return number of bytes copied to buf | ||
1334 | */ | ||
1278 | static uLong | 1335 | static uLong |
1279 | ec_read_file_func (voidpf opaque, | 1336 | ec_read_file_func (voidpf opaque, |
1280 | void* buf, | 1337 | void* buf, |
@@ -1283,17 +1340,29 @@ ec_read_file_func (voidpf opaque, | |||
1283 | struct EXTRACTOR_ExtractContext *ec = opaque; | 1340 | struct EXTRACTOR_ExtractContext *ec = opaque; |
1284 | void *ptr; | 1341 | void *ptr; |
1285 | ssize_t ret; | 1342 | ssize_t ret; |
1343 | uLong done; | ||
1286 | 1344 | ||
1287 | ret = ec->read (ec->cls, | 1345 | done = 0; |
1288 | &ptr, | 1346 | while (done < size) |
1289 | size); | 1347 | { |
1290 | if (ret > 0) | 1348 | ret = ec->read (ec->cls, |
1291 | memcpy (buf, ptr, ret); | 1349 | &ptr, |
1292 | // FIXME: partial reads are not allowed, need to possibly read more | 1350 | size); |
1293 | return ret; | 1351 | if (ret <= 0) |
1352 | return done; | ||
1353 | memcpy (buf + done, ptr, ret); | ||
1354 | done += ret; | ||
1355 | } | ||
1356 | return done; | ||
1294 | } | 1357 | } |
1295 | 1358 | ||
1296 | 1359 | ||
1360 | /** | ||
1361 | * Callback to obtain current offset in file using LE API. | ||
1362 | * | ||
1363 | * @param opaque the 'struct EXTRACTOR_ExtractContext' | ||
1364 | * @return current offset in file, -1 on error | ||
1365 | */ | ||
1297 | static long | 1366 | static long |
1298 | ec_tell_file_func (voidpf opaque) | 1367 | ec_tell_file_func (voidpf opaque) |
1299 | { | 1368 | { |
@@ -1303,6 +1372,14 @@ ec_tell_file_func (voidpf opaque) | |||
1303 | } | 1372 | } |
1304 | 1373 | ||
1305 | 1374 | ||
1375 | /** | ||
1376 | * Callback to perform seek operation using LE API. | ||
1377 | * | ||
1378 | * @param opaque the 'struct EXTRACTOR_ExtractContext' | ||
1379 | * @param offset where to seek | ||
1380 | * @param origin relative to where should we seek | ||
1381 | * @return EXTRACTOR_UNZIP_OK on success | ||
1382 | */ | ||
1306 | static long | 1383 | static long |
1307 | ec_seek_file_func (voidpf opaque, | 1384 | ec_seek_file_func (voidpf opaque, |
1308 | uLong offset, | 1385 | uLong offset, |
@@ -1326,14 +1403,14 @@ ec_seek_file_func (voidpf opaque, | |||
1326 | struct EXTRACTOR_UnzipFile * | 1403 | struct EXTRACTOR_UnzipFile * |
1327 | EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec) | 1404 | EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec) |
1328 | { | 1405 | { |
1329 | struct EXTRACTOR_UnzipFileFuncDefs io; | 1406 | struct FileFuncDefs ffd; |
1330 | 1407 | ||
1331 | io.zread_file = &ec_read_file_func; | 1408 | ffd.zread_file = &ec_read_file_func; |
1332 | io.ztell_file = &ec_tell_file_func; | 1409 | ffd.ztell_file = &ec_tell_file_func; |
1333 | io.zseek_file = &ec_seek_file_func; | 1410 | ffd.zseek_file = &ec_seek_file_func; |
1334 | io.opaque = ec; | 1411 | ffd.opaque = ec; |
1335 | 1412 | ||
1336 | return EXTRACTOR_common_unzip_open2 (&io); | 1413 | return unzip_open_using_ffd (&ffd); |
1337 | } | 1414 | } |
1338 | 1415 | ||
1339 | /* end of unzip.c */ | 1416 | /* end of unzip.c */ |
diff --git a/src/common/unzip.h b/src/common/unzip.h index d490eea..831c894 100644 --- a/src/common/unzip.h +++ b/src/common/unzip.h | |||
@@ -208,10 +208,21 @@ EXTRACTOR_common_unzip_open (struct EXTRACTOR_ExtractContext *ec); | |||
208 | 208 | ||
209 | 209 | ||
210 | /** | 210 | /** |
211 | * Close a ZipFile. If there is files inside the .Zip opened with | 211 | * Obtain the global comment from a ZIP file. |
212 | * EXTRACTOR_common_unzip_open_current_file, these files MUST be | 212 | * |
213 | * closed with EXTRACTOR_common_unzip_close_current_file before | 213 | * @param file unzip file to inspect |
214 | * calling EXTRACTOR_common_unzip_close. | 214 | * @param comment where to copy the comment |
215 | * @param comment_len maximum number of bytes available in comment | ||
216 | * @return EXTRACTOR_UNZIP_OK on success | ||
217 | */ | ||
218 | int | ||
219 | EXTRACTOR_common_unzip_get_global_comment (struct EXTRACTOR_UnzipFile *file, | ||
220 | char *comment, | ||
221 | size_t comment_len); | ||
222 | |||
223 | |||
224 | /** | ||
225 | * Close a ZipFile. | ||
215 | * | 226 | * |
216 | * @param file zip file to close | 227 | * @param file zip file to close |
217 | * @return EXTRACTOR_UNZIP_OK if there is no problem. | 228 | * @return EXTRACTOR_UNZIP_OK if there is no problem. |
@@ -263,6 +274,7 @@ EXTRACTOR_common_unzip_go_find_local_file (struct EXTRACTOR_UnzipFile *file, | |||
263 | * No preparation of the structure is needed. | 274 | * No preparation of the structure is needed. |
264 | * | 275 | * |
265 | * @param file zipfile to manipulate | 276 | * @param file zipfile to manipulate |
277 | * @param pfile_info file information to initialize | ||
266 | * @param szFileName where to write the name of the current file | 278 | * @param szFileName where to write the name of the current file |
267 | * @param fileNameBufferSize number of bytes available in szFileName | 279 | * @param fileNameBufferSize number of bytes available in szFileName |
268 | * @param extraField where to write extra data | 280 | * @param extraField where to write extra data |
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 07b0560..8e2af6b 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am | |||
@@ -30,7 +30,9 @@ EXTRA_DIST = template_extractor.c \ | |||
30 | testdata/ole2_starwriter40.sdw \ | 30 | testdata/ole2_starwriter40.sdw \ |
31 | testdata/ole2_blair.doc \ | 31 | testdata/ole2_blair.doc \ |
32 | testdata/ole2_excel.xls \ | 32 | testdata/ole2_excel.xls \ |
33 | testdata/png_image.png | 33 | testdata/png_image.png \ |
34 | testdata/odf_cg.odt \ | ||
35 | testdata/deb_bzip2.deb | ||
34 | 36 | ||
35 | if HAVE_VORBISFILE | 37 | if HAVE_VORBISFILE |
36 | PLUGIN_OGG=libextractor_ogg.la | 38 | PLUGIN_OGG=libextractor_ogg.la |
@@ -77,13 +79,23 @@ PLUGIN_GSF=libextractor_ole2.la | |||
77 | TEST_GSF=test_ole2 | 79 | TEST_GSF=test_ole2 |
78 | endif | 80 | endif |
79 | 81 | ||
82 | if HAVE_ZLIB | ||
83 | PLUGIN_ZLIB=libextractor_deb.la | ||
84 | TEST_ZLIB=test_deb | ||
85 | endif | ||
80 | 86 | ||
81 | plugin_LTLIBRARIES = \ | 87 | plugin_LTLIBRARIES = \ |
82 | libextractor_it.la \ | 88 | libextractor_it.la \ |
89 | libextractor_nsf.la \ | ||
90 | libextractor_nsfe.la \ | ||
91 | libextractor_odf.la \ | ||
83 | libextractor_png.la \ | 92 | libextractor_png.la \ |
84 | libextractor_xm.la \ | 93 | libextractor_xm.la \ |
85 | libextractor_s3m.la \ | 94 | libextractor_s3m.la \ |
95 | libextractor_sid.la \ | ||
86 | libextractor_wav.la \ | 96 | libextractor_wav.la \ |
97 | libextractor_zip.la \ | ||
98 | $(PLUGIN_ZLIB) \ | ||
87 | $(PLUGIN_OGG) \ | 99 | $(PLUGIN_OGG) \ |
88 | $(PLUGIN_MIME) \ | 100 | $(PLUGIN_MIME) \ |
89 | $(PLUGIN_GIF) \ | 101 | $(PLUGIN_GIF) \ |
@@ -103,6 +115,9 @@ check_PROGRAMS = \ | |||
103 | test_it \ | 115 | test_it \ |
104 | test_s3m \ | 116 | test_s3m \ |
105 | test_png \ | 117 | test_png \ |
118 | test_odf \ | ||
119 | test_zip \ | ||
120 | $(TEST_ZLIB) \ | ||
106 | $(TEST_OGG) \ | 121 | $(TEST_OGG) \ |
107 | $(TEST_MIME) \ | 122 | $(TEST_MIME) \ |
108 | $(TEST_GIF) \ | 123 | $(TEST_GIF) \ |
@@ -133,6 +148,55 @@ libextractor_xm_la_LDFLAGS = \ | |||
133 | $(PLUGINFLAGS) | 148 | $(PLUGINFLAGS) |
134 | 149 | ||
135 | 150 | ||
151 | libextractor_deb_la_SOURCES = \ | ||
152 | deb_extractor.c | ||
153 | libextractor_deb_la_LDFLAGS = \ | ||
154 | $(PLUGINFLAGS) -lz | ||
155 | |||
156 | test_deb_SOURCES = \ | ||
157 | test_deb.c | ||
158 | test_deb_LDADD = \ | ||
159 | $(top_builddir)/src/plugins/libtest.la | ||
160 | |||
161 | |||
162 | libextractor_nsf_la_SOURCES = \ | ||
163 | nsf_extractor.c | ||
164 | libextractor_nsf_la_LDFLAGS = \ | ||
165 | $(PLUGINFLAGS) | ||
166 | |||
167 | |||
168 | libextractor_nsfe_la_SOURCES = \ | ||
169 | nsfe_extractor.c | ||
170 | libextractor_nsfe_la_LDFLAGS = \ | ||
171 | $(PLUGINFLAGS) | ||
172 | |||
173 | |||
174 | libextractor_odf_la_SOURCES = \ | ||
175 | odf_extractor.c | ||
176 | libextractor_odf_la_LDFLAGS = \ | ||
177 | $(PLUGINFLAGS) | ||
178 | libextractor_odf_la_LIBADD = \ | ||
179 | $(top_builddir)/src/common/libextractor_common.la | ||
180 | |||
181 | test_odf_SOURCES = \ | ||
182 | test_odf.c | ||
183 | test_odf_LDADD = \ | ||
184 | $(top_builddir)/src/plugins/libtest.la | ||
185 | |||
186 | |||
187 | libextractor_zip_la_SOURCES = \ | ||
188 | zip_extractor.c | ||
189 | libextractor_zip_la_LDFLAGS = \ | ||
190 | $(PLUGINFLAGS) | ||
191 | libextractor_zip_la_LIBADD = \ | ||
192 | $(top_builddir)/src/common/libextractor_common.la | ||
193 | |||
194 | test_zip_SOURCES = \ | ||
195 | test_zip.c | ||
196 | test_zip_LDADD = \ | ||
197 | $(top_builddir)/src/plugins/libtest.la | ||
198 | |||
199 | |||
136 | libextractor_png_la_SOURCES = \ | 200 | libextractor_png_la_SOURCES = \ |
137 | png_extractor.c | 201 | png_extractor.c |
138 | libextractor_png_la_LDFLAGS = \ | 202 | libextractor_png_la_LDFLAGS = \ |
@@ -157,6 +221,11 @@ test_it_LDADD = \ | |||
157 | $(top_builddir)/src/plugins/libtest.la | 221 | $(top_builddir)/src/plugins/libtest.la |
158 | 222 | ||
159 | 223 | ||
224 | libextractor_sid_la_SOURCES = \ | ||
225 | sid_extractor.c | ||
226 | libextractor_sid_la_LDFLAGS = \ | ||
227 | $(PLUGINFLAGS) | ||
228 | |||
160 | libextractor_s3m_la_SOURCES = \ | 229 | libextractor_s3m_la_SOURCES = \ |
161 | s3m_extractor.c | 230 | s3m_extractor.c |
162 | libextractor_s3m_la_LDFLAGS = \ | 231 | libextractor_s3m_la_LDFLAGS = \ |
diff --git a/src/plugins/deb_extractor.c b/src/plugins/deb_extractor.c index 2bb90c5..955657e 100644 --- a/src/plugins/deb_extractor.c +++ b/src/plugins/deb_extractor.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libextractor. | 2 | This file is part of libextractor. |
3 | (C) 2002, 2003, 2004 Vidyut Samanta and Christian Grothoff | 3 | (C) 2002, 2003, 2004, 2012 Vidyut Samanta and Christian Grothoff |
4 | 4 | ||
5 | libextractor is free software; you can redistribute it and/or modify | 5 | libextractor is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
7 | by the Free Software Foundation; either version 2, or (at your | 7 | by the Free Software Foundation; either version 3, or (at your |
8 | option) any later version. | 8 | option) any later version. |
9 | 9 | ||
10 | libextractor is distributed in the hope that it will be useful, but | 10 | libextractor is distributed in the hope that it will be useful, but |
@@ -17,12 +17,11 @@ | |||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | /** | |
21 | #include "platform.h" | 21 | * @file plugins/deb_extractor.c |
22 | #include "extractor.h" | 22 | * @brief plugin to support Debian archives |
23 | #include <zlib.h> | 23 | * @author Christian Grothoff |
24 | 24 | * | |
25 | /* | ||
26 | * The .deb is an ar-chive file. It contains a tar.gz file | 25 | * The .deb is an ar-chive file. It contains a tar.gz file |
27 | * named "control.tar.gz" which then contains a file 'control' | 26 | * named "control.tar.gz" which then contains a file 'control' |
28 | * that has the meta-data. And which variant of the various | 27 | * that has the meta-data. And which variant of the various |
@@ -33,14 +32,33 @@ | |||
33 | * http://lists.debian.org/debian-policy/2003/12/msg00000.html | 32 | * http://lists.debian.org/debian-policy/2003/12/msg00000.html |
34 | * http://www.opengroup.org/onlinepubs/009695399/utilities/ar.html | 33 | * http://www.opengroup.org/onlinepubs/009695399/utilities/ar.html |
35 | */ | 34 | */ |
35 | #include "platform.h" | ||
36 | #include "extractor.h" | ||
37 | #include <zlib.h> | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Maximum file size we allow for control.tar.gz files. | ||
42 | * This is a sanity check to avoid allocating huge amounts | ||
43 | * of memory. | ||
44 | */ | ||
45 | #define MAX_CONTROL_SIZE (1024 * 1024) | ||
36 | 46 | ||
37 | 47 | ||
48 | /** | ||
49 | * Re-implementation of 'strndup'. | ||
50 | * | ||
51 | * @param str string to duplicate | ||
52 | * @param n maximum number of bytes to copy | ||
53 | * @return NULL on error, otherwise 0-terminated copy of 'str' | ||
54 | * with at most n characters | ||
55 | */ | ||
38 | static char * | 56 | static char * |
39 | stndup (const char *str, size_t n) | 57 | stndup (const char *str, size_t n) |
40 | { | 58 | { |
41 | char *tmp; | 59 | char *tmp; |
42 | tmp = malloc (n + 1); | 60 | |
43 | if (tmp == NULL) | 61 | if (NULL == (tmp = malloc (n + 1))) |
44 | return NULL; | 62 | return NULL; |
45 | tmp[n] = '\0'; | 63 | tmp[n] = '\0'; |
46 | memcpy (tmp, str, n); | 64 | memcpy (tmp, str, n); |
@@ -48,15 +66,29 @@ stndup (const char *str, size_t n) | |||
48 | } | 66 | } |
49 | 67 | ||
50 | 68 | ||
51 | 69 | /** | |
52 | typedef struct | 70 | * Entry in the mapping from control data to LE types. |
71 | */ | ||
72 | struct Matches | ||
53 | { | 73 | { |
74 | /** | ||
75 | * Key in the Debian control file. | ||
76 | */ | ||
54 | const char *text; | 77 | const char *text; |
78 | |||
79 | /** | ||
80 | * Corresponding type in LE. | ||
81 | */ | ||
55 | enum EXTRACTOR_MetaType type; | 82 | enum EXTRACTOR_MetaType type; |
56 | } Matches; | 83 | }; |
84 | |||
57 | 85 | ||
58 | /* see also: "man 5 deb-control" */ | 86 | /** |
59 | static Matches tmap[] = { | 87 | * Map from deb-control entries to LE types. |
88 | * | ||
89 | * see also: "man 5 deb-control" | ||
90 | */ | ||
91 | static struct Matches tmap[] = { | ||
60 | {"Package: ", EXTRACTOR_METATYPE_PACKAGE_NAME}, | 92 | {"Package: ", EXTRACTOR_METATYPE_PACKAGE_NAME}, |
61 | {"Version: ", EXTRACTOR_METATYPE_PACKAGE_VERSION}, | 93 | {"Version: ", EXTRACTOR_METATYPE_PACKAGE_VERSION}, |
62 | {"Section: ", EXTRACTOR_METATYPE_SECTION}, | 94 | {"Section: ", EXTRACTOR_METATYPE_SECTION}, |
@@ -79,7 +111,13 @@ static Matches tmap[] = { | |||
79 | 111 | ||
80 | 112 | ||
81 | /** | 113 | /** |
82 | * Process the control file. | 114 | * Process the "control" file from the control.tar.gz |
115 | * | ||
116 | * @param data decompressed control data | ||
117 | * @param size number of bytes in data | ||
118 | * @param proc function to call with meta data | ||
119 | * @param proc_cls closure for 'proc' | ||
120 | * @return 0 to continue extracting, 1 if we are done | ||
83 | */ | 121 | */ |
84 | static int | 122 | static int |
85 | processControl (const char *data, | 123 | processControl (const char *data, |
@@ -90,62 +128,52 @@ processControl (const char *data, | |||
90 | size_t pos; | 128 | size_t pos; |
91 | char *key; | 129 | char *key; |
92 | char *val; | 130 | char *val; |
93 | 131 | size_t colon; | |
132 | size_t eol; | ||
133 | unsigned int i; | ||
134 | |||
94 | pos = 0; | 135 | pos = 0; |
95 | while (pos < size) | 136 | while (pos < size) |
96 | { | 137 | { |
97 | size_t colon; | 138 | for (colon = pos; ':' != data[colon]; colon++) |
98 | size_t eol; | 139 | if ((colon > size) || ('\n' == data[colon])) |
99 | int i; | 140 | return 0; |
100 | |||
101 | colon = pos; | ||
102 | while (data[colon] != ':') | ||
103 | { | ||
104 | if ((colon > size) || (data[colon] == '\n')) | ||
105 | return 0; | ||
106 | colon++; | ||
107 | } | ||
108 | colon++; | 141 | colon++; |
109 | while ((colon < size) && (isspace ((unsigned char) data[colon]))) | 142 | while ((colon < size) && (isspace ((unsigned char) data[colon]))) |
110 | colon++; | 143 | colon++; |
111 | eol = colon; | 144 | eol = colon; |
112 | while ((eol < size) && | 145 | while ((eol < size) && |
113 | ((data[eol] != '\n') || | 146 | (('\n' != data[eol]) || |
114 | ((eol + 1 < size) && (data[eol + 1] == ' ')))) | 147 | ((eol + 1 < size) && (' ' == data[eol + 1])))) |
115 | eol++; | 148 | eol++; |
116 | if ((eol == colon) || (eol > size)) | 149 | if ((eol == colon) || (eol > size)) |
117 | return 0; | 150 | return 0; |
118 | key = stndup (&data[pos], colon - pos); | 151 | if (NULL == (key = stndup (&data[pos], colon - pos))) |
119 | if (key == NULL) | ||
120 | return 0; | 152 | return 0; |
121 | i = 0; | 153 | for (i = 0; NULL != tmap[i].text; i++) |
122 | while (tmap[i].text != NULL) | ||
123 | { | 154 | { |
124 | if (0 == strcmp (key, tmap[i].text)) | 155 | if (0 != strcmp (key, tmap[i].text)) |
125 | { | 156 | continue; |
126 | val = stndup (&data[colon], eol - colon); | 157 | if (NULL == (val = stndup (&data[colon], eol - colon))) |
127 | if (val == NULL) | 158 | { |
128 | { | 159 | free (key); |
129 | free (key); | 160 | return 0; |
130 | return 0; | 161 | } |
131 | } | 162 | if (0 != proc (proc_cls, |
132 | if (0 != proc (proc_cls, | 163 | "deb", |
133 | "deb", | 164 | tmap[i].type, |
134 | tmap[i].type, | 165 | EXTRACTOR_METAFORMAT_UTF8, |
135 | EXTRACTOR_METAFORMAT_UTF8, | 166 | "text/plain", |
136 | "text/plain", | 167 | val, |
137 | val, | 168 | strlen(val) + 1)) |
138 | strlen(val) + 1)) | 169 | { |
139 | { | ||
140 | free (val); | ||
141 | free (key); | ||
142 | return 1; | ||
143 | } | ||
144 | free (val); | 170 | free (val); |
145 | break; | 171 | free (key); |
146 | } | 172 | return 1; |
147 | i++; | 173 | } |
148 | } | 174 | free (val); |
175 | break; | ||
176 | } | ||
149 | free (key); | 177 | free (key); |
150 | pos = eol + 1; | 178 | pos = eol + 1; |
151 | } | 179 | } |
@@ -153,62 +181,142 @@ processControl (const char *data, | |||
153 | } | 181 | } |
154 | 182 | ||
155 | 183 | ||
156 | typedef struct | 184 | /** |
185 | * Header of an entry in a TAR file. | ||
186 | */ | ||
187 | struct TarHeader | ||
157 | { | 188 | { |
189 | /** | ||
190 | * Filename. | ||
191 | */ | ||
158 | char name[100]; | 192 | char name[100]; |
193 | |||
194 | /** | ||
195 | * File access modes. | ||
196 | */ | ||
159 | char mode[8]; | 197 | char mode[8]; |
198 | |||
199 | /** | ||
200 | * Owner of the file. | ||
201 | */ | ||
160 | char userId[8]; | 202 | char userId[8]; |
203 | |||
204 | /** | ||
205 | * Group of the file. | ||
206 | */ | ||
161 | char groupId[8]; | 207 | char groupId[8]; |
208 | |||
209 | /** | ||
210 | * Size of the file, in octal. | ||
211 | */ | ||
162 | char filesize[12]; | 212 | char filesize[12]; |
213 | |||
214 | /** | ||
215 | * Last modification time. | ||
216 | */ | ||
163 | char lastModTime[12]; | 217 | char lastModTime[12]; |
218 | |||
219 | /** | ||
220 | * Checksum of the file. | ||
221 | */ | ||
164 | char chksum[8]; | 222 | char chksum[8]; |
223 | |||
224 | /** | ||
225 | * Is the file a link? | ||
226 | */ | ||
165 | char link; | 227 | char link; |
228 | |||
229 | /** | ||
230 | * Destination of the link. | ||
231 | */ | ||
166 | char linkName[100]; | 232 | char linkName[100]; |
167 | } TarHeader; | 233 | }; |
234 | |||
168 | 235 | ||
169 | typedef struct | 236 | /** |
237 | * Extended TAR header for USTar format. | ||
238 | */ | ||
239 | struct USTarHeader | ||
170 | { | 240 | { |
171 | TarHeader tar; | 241 | /** |
242 | * Original TAR header. | ||
243 | */ | ||
244 | struct TarHeader tar; | ||
245 | |||
246 | /** | ||
247 | * Additinal magic for USTar. | ||
248 | */ | ||
172 | char magic[6]; | 249 | char magic[6]; |
250 | |||
251 | /** | ||
252 | * Format version. | ||
253 | */ | ||
173 | char version[2]; | 254 | char version[2]; |
255 | |||
256 | /** | ||
257 | * User name. | ||
258 | */ | ||
174 | char uname[32]; | 259 | char uname[32]; |
260 | |||
261 | /** | ||
262 | * Group name. | ||
263 | */ | ||
175 | char gname[32]; | 264 | char gname[32]; |
265 | |||
266 | /** | ||
267 | * Device major number. | ||
268 | */ | ||
176 | char devmajor[8]; | 269 | char devmajor[8]; |
270 | |||
271 | /** | ||
272 | * Device minor number. | ||
273 | */ | ||
177 | char devminor[8]; | 274 | char devminor[8]; |
275 | |||
276 | /** | ||
277 | * Unknown (padding?). | ||
278 | */ | ||
178 | char prefix[155]; | 279 | char prefix[155]; |
179 | } USTarHeader; | 280 | }; |
281 | |||
180 | 282 | ||
181 | /** | 283 | /** |
182 | * Process the control.tar file. | 284 | * Process the control.tar file. |
285 | * | ||
286 | * @param data the deflated control.tar file data | ||
287 | * @param size number of bytes in data | ||
288 | * @param proc function to call with meta data | ||
289 | * @param proc_cls closure for 'proc' | ||
290 | * @return 0 to continue extracting, 1 if we are done | ||
183 | */ | 291 | */ |
184 | static int | 292 | static int |
185 | processControlTar (const char *data, | 293 | processControlTar (const char *data, |
186 | const size_t size, | 294 | size_t size, |
187 | EXTRACTOR_MetaDataProcessor proc, | 295 | EXTRACTOR_MetaDataProcessor proc, |
188 | void *proc_cls) | 296 | void *proc_cls) |
189 | { | 297 | { |
190 | TarHeader *tar; | 298 | struct TarHeader *tar; |
191 | USTarHeader *ustar; | 299 | struct USTarHeader *ustar; |
192 | size_t pos; | 300 | size_t pos; |
193 | 301 | ||
194 | pos = 0; | 302 | pos = 0; |
195 | while (pos + sizeof (TarHeader) < size) | 303 | while (pos + sizeof (struct TarHeader) < size) |
196 | { | 304 | { |
197 | unsigned long long fsize; | 305 | unsigned long long fsize; |
198 | char buf[13]; | 306 | char buf[13]; |
199 | 307 | ||
200 | tar = (TarHeader *) & data[pos]; | 308 | tar = (struct TarHeader *) & data[pos]; |
201 | if (pos + sizeof (USTarHeader) < size) | 309 | if (pos + sizeof (struct USTarHeader) < size) |
202 | { | 310 | { |
203 | ustar = (USTarHeader *) & data[pos]; | 311 | ustar = (struct USTarHeader *) & data[pos]; |
204 | if (0 == strncmp ("ustar", &ustar->magic[0], strlen ("ustar"))) | 312 | if (0 == strncmp ("ustar", &ustar->magic[0], strlen ("ustar"))) |
205 | pos += 512; /* sizeof(USTarHeader); */ | 313 | pos += 512; /* sizeof (struct USTarHeader); */ |
206 | else | 314 | else |
207 | pos += 257; /* sizeof(TarHeader); minus gcc alignment... */ | 315 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ |
208 | } | 316 | } |
209 | else | 317 | else |
210 | { | 318 | { |
211 | pos += 257; /* sizeof(TarHeader); minus gcc alignment... */ | 319 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ |
212 | } | 320 | } |
213 | 321 | ||
214 | memcpy (buf, &tar->filesize[0], 12); | 322 | memcpy (buf, &tar->filesize[0], 12); |
@@ -220,9 +328,10 @@ processControlTar (const char *data, | |||
220 | 328 | ||
221 | if (0 == strncmp (&tar->name[0], "./control", strlen ("./control"))) | 329 | if (0 == strncmp (&tar->name[0], "./control", strlen ("./control"))) |
222 | { | 330 | { |
331 | /* found the 'control' file we were looking for */ | ||
223 | return processControl (&data[pos], fsize, proc, proc_cls); | 332 | return processControl (&data[pos], fsize, proc, proc_cls); |
224 | } | 333 | } |
225 | if ((fsize & 511) != 0) | 334 | if (0 != (fsize & 511)) |
226 | fsize = (fsize | 511) + 1; /* round up! */ | 335 | fsize = (fsize | 511) + 1; /* round up! */ |
227 | if (pos + fsize < pos) | 336 | if (pos + fsize < pos) |
228 | return 0; | 337 | return 0; |
@@ -231,137 +340,184 @@ processControlTar (const char *data, | |||
231 | return 0; | 340 | return 0; |
232 | } | 341 | } |
233 | 342 | ||
234 | #define MAX_CONTROL_SIZE (1024 * 1024) | ||
235 | |||
236 | static voidpf | ||
237 | Emalloc (voidpf opaque, uInt items, uInt size) | ||
238 | { | ||
239 | if (SIZE_MAX / size <= items) | ||
240 | return NULL; | ||
241 | return malloc (size * items); | ||
242 | } | ||
243 | |||
244 | static void | ||
245 | Efree (voidpf opaque, voidpf ptr) | ||
246 | { | ||
247 | free (ptr); | ||
248 | } | ||
249 | 343 | ||
250 | /** | 344 | /** |
251 | * Process the control.tar.gz file. | 345 | * Process the control.tar.gz file. |
346 | * | ||
347 | * @param ec extractor context with control.tar.gz at current read position | ||
348 | * @param size number of bytes in the control file | ||
349 | * @return 0 to continue extracting, 1 if we are done | ||
252 | */ | 350 | */ |
253 | static int | 351 | static int |
254 | processControlTGZ (const unsigned char *data, | 352 | processControlTGZ (struct EXTRACTOR_ExtractContext *ec, |
255 | size_t size, | 353 | unsigned long long size) |
256 | EXTRACTOR_MetaDataProcessor proc, | ||
257 | void *proc_cls) | ||
258 | { | 354 | { |
259 | uint32_t bufSize; | 355 | uint32_t bufSize; |
260 | char *buf; | 356 | char *buf; |
357 | void *data; | ||
358 | unsigned char *cdata; | ||
261 | z_stream strm; | 359 | z_stream strm; |
262 | int ret; | 360 | int ret; |
361 | ssize_t sret; | ||
362 | unsigned long long off; | ||
263 | 363 | ||
264 | bufSize = data[size - 4] + (data[size - 3] << 8) + (data[size - 2] << 16) + (data[size - 1] << 24); | 364 | if (size > MAX_CONTROL_SIZE) |
265 | if (bufSize > MAX_CONTROL_SIZE) | 365 | return 0; |
366 | if (NULL == (cdata = malloc (size))) | ||
266 | return 0; | 367 | return 0; |
368 | off = 0; | ||
369 | while (off < size) | ||
370 | { | ||
371 | if (0 >= (sret = ec->read (ec->cls, &data, size - off))) | ||
372 | { | ||
373 | free (cdata); | ||
374 | return 0; | ||
375 | } | ||
376 | memcpy (&cdata[off], data, sret); | ||
377 | off += sret; | ||
378 | } | ||
379 | bufSize = cdata[size - 4] + (cdata[size - 3] << 8) + (cdata[size - 2] << 16) + (cdata[size - 1] << 24); | ||
380 | if (bufSize > MAX_CONTROL_SIZE) | ||
381 | { | ||
382 | free (cdata); | ||
383 | return 0; | ||
384 | } | ||
385 | if (NULL == (buf = malloc (bufSize))) | ||
386 | { | ||
387 | free (cdata); | ||
388 | return 0; | ||
389 | } | ||
390 | ret = 0; | ||
267 | memset (&strm, 0, sizeof (z_stream)); | 391 | memset (&strm, 0, sizeof (z_stream)); |
268 | strm.next_in = (Bytef *) data; | 392 | strm.next_in = (Bytef *) data; |
269 | strm.avail_in = size; | 393 | strm.avail_in = size; |
270 | strm.total_in = 0; | ||
271 | strm.zalloc = &Emalloc; | ||
272 | strm.zfree = &Efree; | ||
273 | strm.opaque = NULL; | ||
274 | |||
275 | if (Z_OK == inflateInit2 (&strm, 15 + 32)) | 394 | if (Z_OK == inflateInit2 (&strm, 15 + 32)) |
276 | { | 395 | { |
277 | buf = malloc (bufSize); | ||
278 | if (buf == NULL) | ||
279 | { | ||
280 | inflateEnd (&strm); | ||
281 | return 0; | ||
282 | } | ||
283 | strm.next_out = (Bytef *) buf; | 396 | strm.next_out = (Bytef *) buf; |
284 | strm.avail_out = bufSize; | 397 | strm.avail_out = bufSize; |
285 | inflate (&strm, Z_FINISH); | 398 | inflate (&strm, Z_FINISH); |
286 | if (strm.total_out > 0) | 399 | if (strm.total_out > 0) |
287 | { | 400 | ret = processControlTar (buf, strm.total_out, |
288 | ret = processControlTar (buf, strm.total_out, proc, proc_cls); | 401 | ec->proc, ec->cls); |
289 | inflateEnd (&strm); | ||
290 | free (buf); | ||
291 | return ret; | ||
292 | } | ||
293 | free (buf); | ||
294 | inflateEnd (&strm); | 402 | inflateEnd (&strm); |
295 | } | 403 | } |
296 | return 0; | 404 | free (buf); |
405 | free (cdata); | ||
406 | return ret; | ||
297 | } | 407 | } |
298 | 408 | ||
299 | typedef struct | 409 | |
410 | /** | ||
411 | * Header of an object in an "AR"chive file. | ||
412 | */ | ||
413 | struct ObjectHeader | ||
300 | { | 414 | { |
415 | /** | ||
416 | * Name of the file. | ||
417 | */ | ||
301 | char name[16]; | 418 | char name[16]; |
419 | |||
420 | /** | ||
421 | * Last modification time for the file. | ||
422 | */ | ||
302 | char lastModTime[12]; | 423 | char lastModTime[12]; |
424 | |||
425 | /** | ||
426 | * User ID of the owner. | ||
427 | */ | ||
303 | char userId[6]; | 428 | char userId[6]; |
429 | |||
430 | /** | ||
431 | * Group ID of the owner. | ||
432 | */ | ||
304 | char groupId[6]; | 433 | char groupId[6]; |
434 | |||
435 | /** | ||
436 | * File access modes. | ||
437 | */ | ||
305 | char modeInOctal[8]; | 438 | char modeInOctal[8]; |
439 | |||
440 | /** | ||
441 | * Size of the file (as decimal string) | ||
442 | */ | ||
306 | char filesize[10]; | 443 | char filesize[10]; |
444 | |||
445 | /** | ||
446 | * Tailer of the object header ("`\n") | ||
447 | */ | ||
307 | char trailer[2]; | 448 | char trailer[2]; |
308 | } ObjectHeader; | 449 | }; |
309 | 450 | ||
310 | 451 | ||
311 | int | 452 | /** |
312 | EXTRACTOR_deb_extract (const char *data, | 453 | * Main entry method for the DEB extraction plugin. |
313 | size_t size, | 454 | * |
314 | EXTRACTOR_MetaDataProcessor proc, | 455 | * @param ec extraction context provided to the plugin |
315 | void *proc_cls, | 456 | */ |
316 | const char *options) | 457 | void |
458 | EXTRACTOR_deb_extract_method (struct EXTRACTOR_ExtractContext *ec) | ||
317 | { | 459 | { |
318 | size_t pos; | 460 | uint64_t pos; |
319 | int done = 0; | 461 | int done = 0; |
320 | ObjectHeader *hdr; | 462 | const struct ObjectHeader *hdr; |
321 | unsigned long long fsize; | 463 | uint64_t fsize; |
464 | unsigned long long csize; | ||
322 | char buf[11]; | 465 | char buf[11]; |
323 | 466 | void *data; | |
324 | if (size < 128) | 467 | |
325 | return 0; | 468 | fsize = ec->get_size (ec->cls); |
326 | if (0 != strncmp ("!<arch>\n", data, strlen ("!<arch>\n"))) | 469 | if (fsize < 128) |
327 | return 0; | 470 | return; |
328 | pos = strlen ("!<arch>\n"); | 471 | if (8 != |
329 | while (pos + sizeof (ObjectHeader) < size) | 472 | ec->read (ec->cls, &data, 8)) |
473 | return; | ||
474 | if (0 != strncmp ("!<arch>\n", data, 8)) | ||
475 | return; | ||
476 | pos = 8; | ||
477 | while (pos + sizeof (struct ObjectHeader) < fsize) | ||
330 | { | 478 | { |
331 | hdr = (ObjectHeader *) & data[pos]; | 479 | if (pos != |
480 | ec->seek (ec->cls, pos, SEEK_SET)) | ||
481 | return; | ||
482 | if (sizeof (struct ObjectHeader) != | ||
483 | ec->read (ec->cls, &data, sizeof (struct ObjectHeader))) | ||
484 | return; | ||
485 | hdr = data; | ||
332 | if (0 != strncmp (&hdr->trailer[0], "`\n", 2)) | 486 | if (0 != strncmp (&hdr->trailer[0], "`\n", 2)) |
333 | return 0; | 487 | return; |
334 | memcpy (buf, &hdr->filesize[0], 10); | 488 | memcpy (buf, &hdr->filesize[0], 10); |
335 | buf[10] = '\0'; | 489 | buf[10] = '\0'; |
336 | if (1 != sscanf (buf, "%10llu", &fsize)) | 490 | if (1 != sscanf (buf, "%10llu", &csize)) |
337 | return 0; | 491 | return; |
338 | pos += sizeof (ObjectHeader); | 492 | pos += sizeof (struct ObjectHeader); |
339 | if ((pos + fsize > size) || (fsize > size) || (pos + fsize < pos)) | 493 | if ((pos + csize > fsize) || (csize > fsize) || (pos + csize < pos)) |
340 | return 0; | 494 | return; |
341 | if (0 == strncmp (&hdr->name[0], | 495 | if (0 == strncmp (&hdr->name[0], |
342 | "control.tar.gz", strlen ("control.tar.gz"))) | 496 | "control.tar.gz", |
497 | strlen ("control.tar.gz"))) | ||
343 | { | 498 | { |
344 | if (0 != processControlTGZ ((const unsigned char *) &data[pos], | 499 | if (0 != processControlTGZ (ec, |
345 | fsize, proc, proc_cls)) | 500 | csize)) |
346 | return 1; | 501 | return; |
347 | done++; | 502 | done++; |
348 | } | 503 | } |
349 | if (0 == strncmp (&hdr->name[0], | 504 | if (0 == strncmp (&hdr->name[0], |
350 | "debian-binary", strlen ("debian-binary"))) | 505 | "debian-binary", strlen ("debian-binary"))) |
351 | { | 506 | { |
352 | if (0 != proc (proc_cls, | 507 | if (0 != ec->proc (ec->cls, |
353 | "deb", | 508 | "deb", |
354 | EXTRACTOR_METATYPE_MIMETYPE, | 509 | EXTRACTOR_METATYPE_MIMETYPE, |
355 | EXTRACTOR_METAFORMAT_UTF8, | 510 | EXTRACTOR_METAFORMAT_UTF8, |
356 | "text/plain", | 511 | "text/plain", |
357 | "application/x-debian-package", | 512 | "application/x-debian-package", |
358 | strlen ("application/x-debian-package")+1)) | 513 | strlen ("application/x-debian-package")+1)) |
359 | return 1; | 514 | return; |
360 | done++; | 515 | done++; |
361 | } | 516 | } |
362 | pos += fsize; | 517 | pos += csize; |
363 | if (done == 2) | 518 | if (2 == done) |
364 | break; /* no need to process the rest of the archive */ | 519 | break; /* no need to process the rest of the archive */ |
365 | } | 520 | } |
366 | return 0; | ||
367 | } | 521 | } |
522 | |||
523 | /* end of deb_extractor.c */ | ||
diff --git a/src/plugins/nsf_extractor.c b/src/plugins/nsf_extractor.c index 448b99d..2475214 100644 --- a/src/plugins/nsf_extractor.c +++ b/src/plugins/nsf_extractor.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of libextractor. | 2 | * This file is part of libextractor. |
3 | * (C) 2006, 2009 Toni Ruottu | 3 | * (C) 2006, 2009, 2012 Toni Ruottu and Christian Grothoff |
4 | * | 4 | * |
5 | * libextractor is free software; you can redistribute it and/or modify | 5 | * libextractor is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
7 | * by the Free Software Foundation; either version 2, or (at your | 7 | * by the Free Software Foundation; either version 3, or (at your |
8 | * option) any later version. | 8 | * option) any later version. |
9 | * | 9 | * |
10 | * libextractor is distributed in the hope that it will be useful, but | 10 | * libextractor is distributed in the hope that it will be useful, but |
@@ -18,21 +18,22 @@ | |||
18 | * Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | /** | |
22 | * @file plugins/nsf_extractor.c | ||
23 | * @brief plugin to support Nes Sound Format files | ||
24 | * @author Toni Ruottu | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
22 | #include "platform.h" | 27 | #include "platform.h" |
23 | #include "extractor.h" | 28 | #include "extractor.h" |
24 | #include "convert.h" | ||
25 | 29 | ||
26 | 30 | ||
27 | #define HEADER_SIZE 0x80 | ||
28 | 31 | ||
29 | /* television system flags */ | 32 | /* television system flags */ |
30 | |||
31 | #define PAL_FLAG 0x01 | 33 | #define PAL_FLAG 0x01 |
32 | #define DUAL_FLAG 0x02 | 34 | #define DUAL_FLAG 0x02 |
33 | 35 | ||
34 | /* sound chip flags */ | 36 | /* sound chip flags */ |
35 | |||
36 | #define VRCVI_FLAG 0x01 | 37 | #define VRCVI_FLAG 0x01 |
37 | #define VRCVII_FLAG 0x02 | 38 | #define VRCVII_FLAG 0x02 |
38 | #define FDS_FLAG 0x04 | 39 | #define FDS_FLAG 0x04 |
@@ -40,43 +41,108 @@ | |||
40 | #define NAMCO_FLAG 0x10 | 41 | #define NAMCO_FLAG 0x10 |
41 | #define SUNSOFT_FLAG 0x20 | 42 | #define SUNSOFT_FLAG 0x20 |
42 | 43 | ||
43 | #define UINT16 unsigned short | ||
44 | 44 | ||
45 | /** | ||
46 | * Header of an NSF file. | ||
47 | */ | ||
45 | struct header | 48 | struct header |
46 | { | 49 | { |
50 | /** | ||
51 | * Magic code. | ||
52 | */ | ||
47 | char magicid[5]; | 53 | char magicid[5]; |
54 | |||
55 | /** | ||
56 | * NSF version number. | ||
57 | */ | ||
48 | char nsfversion; | 58 | char nsfversion; |
49 | char songs; | 59 | |
50 | char firstsong; | 60 | /** |
51 | UINT16 loadaddr; | 61 | * Number of songs. |
52 | UINT16 initaddr; | 62 | */ |
53 | UINT16 playaddr; | 63 | unsigned char songs; |
64 | |||
65 | /** | ||
66 | * Starting song. | ||
67 | */ | ||
68 | unsigned char firstsong; | ||
69 | |||
70 | /** | ||
71 | * Unknown. | ||
72 | */ | ||
73 | uint16_t loadaddr; | ||
74 | |||
75 | /** | ||
76 | * Unknown. | ||
77 | */ | ||
78 | uint16_t initaddr; | ||
79 | |||
80 | /** | ||
81 | * Unknown. | ||
82 | */ | ||
83 | uint16_t playaddr; | ||
84 | |||
85 | /** | ||
86 | * Album title. | ||
87 | */ | ||
54 | char title[32]; | 88 | char title[32]; |
89 | |||
90 | /** | ||
91 | * Artist name. | ||
92 | */ | ||
55 | char artist[32]; | 93 | char artist[32]; |
94 | |||
95 | /** | ||
96 | * Copyright information. | ||
97 | */ | ||
56 | char copyright[32]; | 98 | char copyright[32]; |
57 | UINT16 ntscspeed; | 99 | |
100 | /** | ||
101 | * Unknown. | ||
102 | */ | ||
103 | uint16_t ntscspeed; | ||
104 | |||
105 | /** | ||
106 | * Unknown. | ||
107 | */ | ||
58 | char bankswitch[8]; | 108 | char bankswitch[8]; |
59 | UINT16 palspeed; | 109 | |
110 | /** | ||
111 | * Unknown. | ||
112 | */ | ||
113 | uint16_t palspeed; | ||
114 | |||
115 | /** | ||
116 | * Flags for TV encoding. | ||
117 | */ | ||
60 | char tvflags; | 118 | char tvflags; |
119 | |||
120 | /** | ||
121 | * Flags about the decoder chip. | ||
122 | */ | ||
61 | char chipflags; | 123 | char chipflags; |
62 | }; | 124 | }; |
63 | 125 | ||
64 | #define ADD(s,t) do { if (0 != proc (proc_cls, "nsf", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0) | 126 | |
127 | /** | ||
128 | * Give metadata to LE; return if 'proc' returns non-zero. | ||
129 | * | ||
130 | * @param s metadata value as UTF8 | ||
131 | * @param t metadata type to use | ||
132 | */ | ||
133 | #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "nsf", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return; } while (0) | ||
65 | 134 | ||
66 | 135 | ||
67 | /* "extract" keyword from a Nes Sound Format file | 136 | /** |
137 | * "extract" meta data from a Nes Sound Format file | ||
68 | * | 138 | * |
69 | * NSF specification version 1.61 was used, | 139 | * NSF specification version 1.61 was used, while this piece of |
70 | * while this piece of software was originally | 140 | * software was originally written. |
71 | * written. | ||
72 | * | 141 | * |
142 | * @param ec extraction context | ||
73 | */ | 143 | */ |
74 | int | 144 | void |
75 | EXTRACTOR_nsf_extract (const unsigned char *data, | 145 | EXTRACTOR_nsf_extract_method (struct EXTRACTOR_ExtractContext *ec) |
76 | size_t size, | ||
77 | EXTRACTOR_MetaDataProcessor proc, | ||
78 | void *proc_cls, | ||
79 | const char *options) | ||
80 | { | 146 | { |
81 | char album[33]; | 147 | char album[33]; |
82 | char artist[33]; | 148 | char artist[33]; |
@@ -85,12 +151,18 @@ EXTRACTOR_nsf_extract (const unsigned char *data, | |||
85 | char startingsong[32]; | 151 | char startingsong[32]; |
86 | char nsfversion[32]; | 152 | char nsfversion[32]; |
87 | const struct header *head; | 153 | const struct header *head; |
88 | 154 | void *data; | |
89 | if (size < HEADER_SIZE) | 155 | |
90 | return 0; | 156 | if (sizeof (struct header) > |
91 | head = (const struct header *) data; | 157 | ec->read (ec->cls, |
158 | &data, | ||
159 | sizeof (struct header))) | ||
160 | return; | ||
161 | head = data; | ||
162 | |||
163 | /* Check "magic" id bytes */ | ||
92 | if (memcmp (head->magicid, "NESM\x1a", 5)) | 164 | if (memcmp (head->magicid, "NESM\x1a", 5)) |
93 | return 0; | 165 | return; |
94 | ADD ("audio/x-nsf", EXTRACTOR_METATYPE_MIMETYPE); | 166 | ADD ("audio/x-nsf", EXTRACTOR_METATYPE_MIMETYPE); |
95 | snprintf (nsfversion, | 167 | snprintf (nsfversion, |
96 | sizeof(nsfversion), | 168 | sizeof(nsfversion), |
@@ -100,50 +172,48 @@ EXTRACTOR_nsf_extract (const unsigned char *data, | |||
100 | snprintf (songs, | 172 | snprintf (songs, |
101 | sizeof(songs), | 173 | sizeof(songs), |
102 | "%d", | 174 | "%d", |
103 | head->songs); | 175 | (int) head->songs); |
104 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); | 176 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); |
105 | snprintf (startingsong, | 177 | snprintf (startingsong, |
106 | sizeof(startingsong), | 178 | sizeof(startingsong), |
107 | "%d", | 179 | "%d", |
108 | head->firstsong); | 180 | (int) head->firstsong); |
109 | ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG); | 181 | ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG); |
110 | |||
111 | memcpy (&album, head->title, 32); | 182 | memcpy (&album, head->title, 32); |
112 | album[32] = '\0'; | 183 | album[32] = '\0'; |
113 | ADD (album, EXTRACTOR_METATYPE_ALBUM); | 184 | ADD (album, EXTRACTOR_METATYPE_ALBUM); |
114 | |||
115 | memcpy (&artist, head->artist, 32); | 185 | memcpy (&artist, head->artist, 32); |
116 | artist[32] = '\0'; | 186 | artist[32] = '\0'; |
117 | ADD (artist, EXTRACTOR_METATYPE_ARTIST); | 187 | ADD (artist, EXTRACTOR_METATYPE_ARTIST); |
118 | |||
119 | memcpy (©right, head->copyright, 32); | 188 | memcpy (©right, head->copyright, 32); |
120 | copyright[32] = '\0'; | 189 | copyright[32] = '\0'; |
121 | ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT); | 190 | ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT); |
122 | 191 | ||
123 | if (head->tvflags & DUAL_FLAG) | 192 | if (0 != (head->tvflags & DUAL_FLAG)) |
124 | { | 193 | { |
125 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 194 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
126 | } | 195 | } |
127 | else | 196 | else |
128 | { | 197 | { |
129 | if (head->tvflags & PAL_FLAG) | 198 | if (0 != (head->tvflags & PAL_FLAG)) |
130 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 199 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
131 | else | 200 | else |
132 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 201 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
133 | } | 202 | } |
134 | 203 | ||
135 | /* Detect Extra Sound Chips needed to play the files */ | 204 | /* Detect Extra Sound Chips needed to play the files */ |
136 | if (head->chipflags & VRCVI_FLAG) | 205 | if (0 != (head->chipflags & VRCVI_FLAG)) |
137 | ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 206 | ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
138 | if (head->chipflags & VRCVII_FLAG) | 207 | if (0 != (head->chipflags & VRCVII_FLAG)) |
139 | ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 208 | ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
140 | if (head->chipflags & FDS_FLAG) | 209 | if (0 != (head->chipflags & FDS_FLAG)) |
141 | ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 210 | ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
142 | if (head->chipflags & MMC5_FLAG) | 211 | if (0 != (head->chipflags & MMC5_FLAG)) |
143 | ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 212 | ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
144 | if (head->chipflags & NAMCO_FLAG) | 213 | if (0 != (head->chipflags & NAMCO_FLAG)) |
145 | ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 214 | ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
146 | if (head->chipflags & SUNSOFT_FLAG) | 215 | if (0 != (head->chipflags & SUNSOFT_FLAG)) |
147 | ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 216 | ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
148 | return 0; | ||
149 | } | 217 | } |
218 | |||
219 | /* end of nsf_extractor.c */ | ||
diff --git a/src/plugins/nsfe_extractor.c b/src/plugins/nsfe_extractor.c index ffd5ded..16c4980 100644 --- a/src/plugins/nsfe_extractor.c +++ b/src/plugins/nsfe_extractor.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of libextractor. | 2 | * This file is part of libextractor. |
3 | * (C) 2007, 2009 Toni Ruottu | 3 | * (C) 2007, 2009, 2012 Toni Ruottu and Christian Grothoff |
4 | * | 4 | * |
5 | * libextractor is free software; you can redistribute it and/or modify | 5 | * libextractor is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
7 | * by the Free Software Foundation; either version 2, or (at your | 7 | * by the Free Software Foundation; either version 3, or (at your |
8 | * option) any later version. | 8 | * option) any later version. |
9 | * | 9 | * |
10 | * libextractor is distributed in the hope that it will be useful, but | 10 | * libextractor is distributed in the hope that it will be useful, but |
@@ -18,20 +18,22 @@ | |||
18 | * Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | /** | |
22 | * @file plugins/nsfe_extractor.c | ||
23 | * @brief plugin to support Nes Sound Format files | ||
24 | * @author Toni Ruottu | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
22 | #include "platform.h" | 27 | #include "platform.h" |
23 | #include "extractor.h" | 28 | #include "extractor.h" |
24 | #include "convert.h" | 29 | #include "convert.h" |
25 | 30 | ||
26 | #define HEADER_SIZE 0x04 | ||
27 | 31 | ||
28 | /* television system flags */ | 32 | /* television system flags */ |
29 | |||
30 | #define PAL_FLAG 0x01 | 33 | #define PAL_FLAG 0x01 |
31 | #define DUAL_FLAG 0x02 | 34 | #define DUAL_FLAG 0x02 |
32 | 35 | ||
33 | /* sound chip flags */ | 36 | /* sound chip flags */ |
34 | |||
35 | #define VRCVI_FLAG 0x01 | 37 | #define VRCVI_FLAG 0x01 |
36 | #define VRCVII_FLAG 0x02 | 38 | #define VRCVII_FLAG 0x02 |
37 | #define FDS_FLAG 0x04 | 39 | #define FDS_FLAG 0x04 |
@@ -39,29 +41,26 @@ | |||
39 | #define NAMCO_FLAG 0x10 | 41 | #define NAMCO_FLAG 0x10 |
40 | #define SUNSOFT_FLAG 0x20 | 42 | #define SUNSOFT_FLAG 0x20 |
41 | 43 | ||
42 | #define UINT16 unsigned short | 44 | /** |
43 | 45 | * "Header" of an NSFE file. | |
46 | */ | ||
44 | struct header | 47 | struct header |
45 | { | 48 | { |
46 | char magicid[4]; | 49 | char magicid[4]; |
47 | }; | 50 | }; |
48 | 51 | ||
49 | struct infochunk | ||
50 | { | ||
51 | UINT16 loadaddr; | ||
52 | UINT16 initaddr; | ||
53 | UINT16 playaddr; | ||
54 | char tvflags; | ||
55 | char chipflags; | ||
56 | char songs; | ||
57 | char firstsong; | ||
58 | }; | ||
59 | 52 | ||
60 | static int | 53 | /** |
54 | * Read an unsigned integer at the current offset. | ||
55 | * | ||
56 | * @param data input data to parse | ||
57 | * @return parsed integer | ||
58 | */ | ||
59 | static uint32_t | ||
61 | nsfeuint (const char *data) | 60 | nsfeuint (const char *data) |
62 | { | 61 | { |
63 | int i; | 62 | int i; |
64 | int value = 0; | 63 | uint32_t value = 0; |
65 | 64 | ||
66 | for (i = 3; i > 0; i--) | 65 | for (i = 3; i > 0; i--) |
67 | { | 66 | { |
@@ -73,8 +72,17 @@ nsfeuint (const char *data) | |||
73 | } | 72 | } |
74 | 73 | ||
75 | 74 | ||
75 | /** | ||
76 | * Copy string starting at 'data' with at most | ||
77 | * 'size' bytes. (strndup). | ||
78 | * | ||
79 | * @param data input data to copy | ||
80 | * @param size number of bytes in 'data' | ||
81 | * @return copy of the string at data | ||
82 | */ | ||
76 | static char * | 83 | static char * |
77 | nsfestring (const char *data, size_t size) | 84 | nsfestring (const char *data, |
85 | size_t size) | ||
78 | { | 86 | { |
79 | char *s; | 87 | char *s; |
80 | size_t length; | 88 | size_t length; |
@@ -83,105 +91,210 @@ nsfestring (const char *data, size_t size) | |||
83 | while ( (length < size) && | 91 | while ( (length < size) && |
84 | (data[length] != '\0') ) | 92 | (data[length] != '\0') ) |
85 | length++; | 93 | length++; |
86 | s = malloc (length + 1); | 94 | if (NULL == (s = malloc (length + 1))) |
87 | if (s == NULL) | ||
88 | return NULL; | 95 | return NULL; |
89 | strncpy (s, data, length); | 96 | memcpy (s, data, length); |
90 | s[strlen (data)] = '\0'; | 97 | s[length] = '\0'; |
91 | return s; | 98 | return s; |
92 | } | 99 | } |
93 | 100 | ||
94 | #define ADD(s,t) do { if (0 != proc (proc_cls, "nsfe", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0) | ||
95 | 101 | ||
96 | #define ADDF(s,t) do { if (0 != proc (proc_cls, "nsfe", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) { free(s); return 1; } free (s); } while (0) | 102 | /** |
103 | * Give metadata to LE; return if 'proc' returns non-zero. | ||
104 | * | ||
105 | * @param s metadata value as UTF8 | ||
106 | * @param t metadata type to use | ||
107 | */ | ||
108 | #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return 1; } while (0) | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Give metadata to LE; return if 'proc' returns non-zero. | ||
113 | * | ||
114 | * @param s metadata value as UTF8, free at the end | ||
115 | * @param t metadata type to use | ||
116 | */ | ||
117 | #define ADDF(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) { free (s); return 1; } free (s); } while (0) | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Format of an 'INFO' chunk. Last two bytes are optional. | ||
122 | */ | ||
123 | struct infochunk | ||
124 | { | ||
125 | /** | ||
126 | * Unknown. | ||
127 | */ | ||
128 | uint16_t loadaddr; | ||
129 | |||
130 | /** | ||
131 | * Unknown. | ||
132 | */ | ||
133 | uint16_t initaddr; | ||
134 | |||
135 | /** | ||
136 | * Unknown. | ||
137 | */ | ||
138 | uint16_t playaddr; | ||
139 | |||
140 | /** | ||
141 | * TV encoding flags. | ||
142 | */ | ||
143 | char tvflags; | ||
97 | 144 | ||
145 | /** | ||
146 | * Chipset encoding flags. | ||
147 | */ | ||
148 | char chipflags; | ||
149 | |||
150 | /** | ||
151 | * Number of songs. | ||
152 | */ | ||
153 | unsigned char songs; | ||
154 | |||
155 | /** | ||
156 | * Starting song. | ||
157 | */ | ||
158 | unsigned char firstsong; | ||
159 | }; | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Extract data from the INFO chunk. | ||
164 | * | ||
165 | * @param ec extraction context | ||
166 | * @param size number of bytes in INFO chunk | ||
167 | * @return 0 to continue extrating | ||
168 | */ | ||
98 | static int | 169 | static int |
99 | libextractor_nsfe_info_extract(const char *data, | 170 | info_extract (struct EXTRACTOR_ExtractContext *ec, |
100 | size_t size, | 171 | uint32_t size) |
101 | EXTRACTOR_MetaDataProcessor proc, | ||
102 | void *proc_cls) | ||
103 | { | 172 | { |
173 | void *data; | ||
104 | const struct infochunk *ichunk; | 174 | const struct infochunk *ichunk; |
105 | char songs[32]; | 175 | char songs[32]; |
106 | 176 | ||
107 | if (size < 8) | 177 | if (size < 8) |
108 | return 0; | 178 | return 0; |
109 | ichunk = (const struct infochunk *) data; | 179 | if (size > |
110 | if (ichunk->tvflags & DUAL_FLAG) | 180 | ec->read (ec->cls, |
181 | &data, | ||
182 | size)) | ||
183 | return 1; | ||
184 | ichunk = data; | ||
185 | |||
186 | if (0 != (ichunk->tvflags & DUAL_FLAG)) | ||
111 | { | 187 | { |
112 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 188 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
113 | } | 189 | } |
114 | else | 190 | else |
115 | { | 191 | { |
116 | if (ichunk->tvflags & PAL_FLAG) | 192 | if (0 != (ichunk->tvflags & PAL_FLAG)) |
117 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 193 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
118 | else | 194 | else |
119 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 195 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
120 | } | 196 | } |
121 | 197 | ||
122 | if (ichunk->chipflags & VRCVI_FLAG) | 198 | if (0 != (ichunk->chipflags & VRCVI_FLAG)) |
123 | ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 199 | ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
124 | if (ichunk->chipflags & VRCVII_FLAG) | 200 | if (0 != (ichunk->chipflags & VRCVII_FLAG)) |
125 | ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 201 | ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
126 | if (ichunk->chipflags & FDS_FLAG) | 202 | if (0 != (ichunk->chipflags & FDS_FLAG)) |
127 | ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 203 | ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
128 | if (ichunk->chipflags & MMC5_FLAG) | 204 | if (0 != (ichunk->chipflags & MMC5_FLAG)) |
129 | ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 205 | ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
130 | if (ichunk->chipflags & NAMCO_FLAG) | 206 | if (0 != (ichunk->chipflags & NAMCO_FLAG)) |
131 | ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 207 | ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
132 | if (ichunk->chipflags & SUNSOFT_FLAG) | 208 | if (0 != (ichunk->chipflags & SUNSOFT_FLAG)) |
133 | ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 209 | ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
134 | if (size < 9) | 210 | |
211 | if (size < sizeof (struct infochunk)) | ||
135 | { | 212 | { |
136 | ADD ("1", EXTRACTOR_METATYPE_SONG_COUNT); | 213 | ADD ("1", EXTRACTOR_METATYPE_SONG_COUNT); |
137 | return 0; | 214 | return 0; |
138 | } | 215 | } |
139 | snprintf (songs, | 216 | snprintf (songs, |
140 | sizeof(songs), | 217 | sizeof (songs), |
141 | "%d", | 218 | "%d", |
142 | ichunk->songs); | 219 | ichunk->songs); |
143 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); | 220 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); |
221 | snprintf (songs, | ||
222 | sizeof (songs), | ||
223 | "%d", | ||
224 | ichunk->firstsong); | ||
225 | ADD (songs, EXTRACTOR_METATYPE_STARTING_SONG); | ||
144 | return 0; | 226 | return 0; |
145 | } | 227 | } |
146 | 228 | ||
147 | 229 | ||
230 | /** | ||
231 | * Extract data from the TLBL chunk. | ||
232 | * | ||
233 | * @param ec extraction context | ||
234 | * @param size number of bytes in TLBL chunk | ||
235 | * @return 0 to continue extrating | ||
236 | */ | ||
148 | static int | 237 | static int |
149 | libextractor_nsfe_tlbl_extract(const char *data, | 238 | tlbl_extract (struct EXTRACTOR_ExtractContext *ec, |
150 | size_t size, | 239 | uint32_t size) |
151 | EXTRACTOR_MetaDataProcessor proc, | ||
152 | void *proc_cls) | ||
153 | |||
154 | { | 240 | { |
155 | char *title; | 241 | char *title; |
156 | ssize_t left; | 242 | ssize_t left; |
157 | size_t length; | 243 | size_t length; |
158 | 244 | void *data; | |
159 | for (left = size; left > 0; left -= length) | 245 | const char *cdata; |
246 | |||
247 | if (size > | ||
248 | ec->read (ec->cls, | ||
249 | &data, | ||
250 | size)) | ||
251 | return 1; | ||
252 | cdata = data; | ||
253 | |||
254 | left = size; | ||
255 | while (left > 0) | ||
160 | { | 256 | { |
161 | title = nsfestring (&data[size - left], left); | 257 | title = nsfestring (&cdata[size - left], left); |
162 | if (title == NULL) | 258 | if (NULL == title) |
163 | return 0; | 259 | return 0; |
164 | length = strlen (title) + 1; | 260 | length = strlen (title) + 1; |
165 | ADDF (title, EXTRACTOR_METATYPE_TITLE); | 261 | ADDF (title, EXTRACTOR_METATYPE_TITLE); |
262 | left -= length; | ||
166 | } | 263 | } |
167 | return 0; | 264 | return 0; |
168 | } | 265 | } |
169 | 266 | ||
267 | |||
268 | /** | ||
269 | * Extract data from the AUTH chunk. | ||
270 | * | ||
271 | * @param ec extraction context | ||
272 | * @param size number of bytes in AUTH chunk | ||
273 | * @return 0 to continue extrating | ||
274 | */ | ||
170 | static int | 275 | static int |
171 | libextractor_nsfe_auth_extract (const char *data, size_t size, | 276 | auth_extract (struct EXTRACTOR_ExtractContext *ec, |
172 | EXTRACTOR_MetaDataProcessor proc, | 277 | uint32_t size) |
173 | void *proc_cls) | ||
174 | { | 278 | { |
175 | char *album; | 279 | char *album; |
176 | char *artist; | 280 | char *artist; |
177 | char *copyright; | 281 | char *copyright; |
178 | char *ripper; | 282 | char *ripper; |
179 | int left = size; | 283 | uint32_t left = size; |
284 | void *data; | ||
285 | const char *cdata; | ||
180 | 286 | ||
181 | if (left < 1) | 287 | if (left < 1) |
182 | return 0; | 288 | return 0; |
183 | album = nsfestring (&data[size - left], left); | 289 | if (size > |
184 | if (album != NULL) | 290 | ec->read (ec->cls, |
291 | &data, | ||
292 | size)) | ||
293 | return 1; | ||
294 | cdata = data; | ||
295 | |||
296 | album = nsfestring (&cdata[size - left], left); | ||
297 | if (NULL != album) | ||
185 | { | 298 | { |
186 | left -= (strlen (album) + 1); | 299 | left -= (strlen (album) + 1); |
187 | ADDF (album, EXTRACTOR_METATYPE_ALBUM); | 300 | ADDF (album, EXTRACTOR_METATYPE_ALBUM); |
@@ -189,8 +302,8 @@ libextractor_nsfe_auth_extract (const char *data, size_t size, | |||
189 | return 0; | 302 | return 0; |
190 | } | 303 | } |
191 | 304 | ||
192 | artist = nsfestring (&data[size - left], left); | 305 | artist = nsfestring (&cdata[size - left], left); |
193 | if (artist != NULL) | 306 | if (NULL != artist) |
194 | { | 307 | { |
195 | left -= (strlen (artist) + 1); | 308 | left -= (strlen (artist) + 1); |
196 | ADDF (artist, EXTRACTOR_METATYPE_ARTIST); | 309 | ADDF (artist, EXTRACTOR_METATYPE_ARTIST); |
@@ -198,67 +311,78 @@ libextractor_nsfe_auth_extract (const char *data, size_t size, | |||
198 | return 0; | 311 | return 0; |
199 | } | 312 | } |
200 | 313 | ||
201 | copyright = nsfestring (&data[size - left], left); | 314 | copyright = nsfestring (&cdata[size - left], left); |
202 | if (copyright != NULL) | 315 | if (NULL != copyright) |
203 | { | 316 | { |
204 | left -= (strlen (copyright) + 1); | 317 | left -= (strlen (copyright) + 1); |
205 | ADDF (copyright, EXTRACTOR_METATYPE_COPYRIGHT); | 318 | ADDF (copyright, EXTRACTOR_METATYPE_COPYRIGHT); |
206 | if (left < 1) | 319 | if (left < 1) |
207 | return 0; | 320 | return 0; |
208 | } | 321 | } |
209 | ripper = nsfestring (&data[size - left], left); | 322 | ripper = nsfestring (&cdata[size - left], left); |
210 | if (ripper != NULL) | 323 | if (NULL != ripper) |
211 | ADDF (ripper, EXTRACTOR_METATYPE_RIPPER); | 324 | ADDF (ripper, EXTRACTOR_METATYPE_RIPPER); |
212 | return 0; | 325 | return 0; |
213 | } | 326 | } |
214 | 327 | ||
215 | 328 | ||
216 | /* "extract" keyword from an Extended Nintendo Sound Format file | 329 | /** |
330 | * "extract" meta data from an Extended Nintendo Sound Format file | ||
217 | * | 331 | * |
218 | * NSFE specification revision 2 (Sep. 3, 2003) | 332 | * NSFE specification revision 2 (Sep. 3, 2003) was used, while this |
219 | * was used, while this piece of software was | 333 | * piece of software was originally written. |
220 | * originally written. | ||
221 | * | 334 | * |
335 | * @param ec extraction context | ||
222 | */ | 336 | */ |
223 | int | 337 | void |
224 | EXTRACTOR_nsfe_extract (const char *data, | 338 | EXTRACTOR_nsfe_extract_method (struct EXTRACTOR_ExtractContext *ec) |
225 | size_t size, | ||
226 | EXTRACTOR_MetaDataProcessor proc, | ||
227 | void *proc_cls, | ||
228 | const char *options) | ||
229 | { | 339 | { |
230 | const struct header *head; | 340 | const struct header *head; |
231 | int i; | 341 | void *data; |
232 | char chunkid[5] = " "; | 342 | uint64_t off; |
343 | uint32_t chunksize; | ||
233 | int ret; | 344 | int ret; |
234 | 345 | ||
235 | if (size < HEADER_SIZE) | 346 | if (sizeof (struct header) > |
236 | return 0; | 347 | ec->read (ec->cls, |
237 | head = (const struct header *) data; | 348 | &data, |
238 | if (memcmp (head->magicid, "NSFE", 4)) | 349 | sizeof (struct header))) |
239 | return 0; | 350 | return; |
240 | ADD ("audio/x-nsfe", EXTRACTOR_METATYPE_MIMETYPE); | 351 | head = data; |
241 | i = 4; /* Jump over magic id */ | 352 | if (0 != memcmp (head->magicid, "NSFE", 4)) |
353 | return; | ||
354 | |||
355 | if (0 != ec->proc (ec->cls, | ||
356 | "nsfe", | ||
357 | EXTRACTOR_METATYPE_MIMETYPE, | ||
358 | EXTRACTOR_METAFORMAT_UTF8, | ||
359 | "text/plain", | ||
360 | "audio/x-nsfe", | ||
361 | strlen ("audio/x-nsfe") + 1)) | ||
362 | return; | ||
363 | off = sizeof (struct header); | ||
242 | ret = 0; | 364 | ret = 0; |
243 | while (i + 7 < size && strncmp (chunkid, "NEND", 4)) /* CHECK */ | 365 | while (0 == ret) |
244 | { | 366 | { |
245 | unsigned int chunksize = nsfeuint (&data[i]); | 367 | if (off != ec->seek (ec->cls, |
246 | 368 | off, | |
247 | i += 4; /* Jump over chunk size */ | 369 | SEEK_SET)) |
248 | memcpy (&chunkid, data + i, 4); | ||
249 | chunkid[4] = '\0'; | ||
250 | |||
251 | i += 4; /* Jump over chunk id */ | ||
252 | if (!strncmp (chunkid, "INFO", 4)) | ||
253 | ret = libextractor_nsfe_info_extract (data + i, chunksize, proc, proc_cls); | ||
254 | else if (!strncmp (chunkid, "auth", 4)) | ||
255 | ret = libextractor_nsfe_auth_extract (data + i, chunksize, proc, proc_cls); | ||
256 | else if (!strncmp (chunkid, "tlbl", 4)) | ||
257 | ret = libextractor_nsfe_tlbl_extract (data + i, chunksize, proc, proc_cls); | ||
258 | /* Ignored chunks: DATA, NEND, plst, time, fade, BANK */ | ||
259 | i += chunksize; | ||
260 | if (ret != 0) | ||
261 | break; | 370 | break; |
371 | if (8 > | ||
372 | ec->read (ec->cls, | ||
373 | &data, | ||
374 | sizeof (struct header))) | ||
375 | break; | ||
376 | chunksize = nsfeuint (data); | ||
377 | off += 4 + chunksize; | ||
378 | if (0 == memcmp (data + 4, "INFO", 4)) | ||
379 | ret = info_extract (ec, chunksize); | ||
380 | else if (0 == memcmp (data + 4, "auth", 4)) | ||
381 | ret = auth_extract (ec, chunksize); | ||
382 | else if (0 == memcmp (data + 4, "tlbl", 4)) | ||
383 | ret = tlbl_extract (ec, chunksize); | ||
384 | /* Ignored chunks: DATA, NEND, plst, time, fade, BANK */ | ||
262 | } | 385 | } |
263 | return ret; | ||
264 | } | 386 | } |
387 | |||
388 | /* end of nsfe_extractor.c */ | ||
diff --git a/src/plugins/odf_extractor.c b/src/plugins/odf_extractor.c index 7903ce5..06da7d8 100644 --- a/src/plugins/odf_extractor.c +++ b/src/plugins/odf_extractor.c | |||
@@ -28,11 +28,6 @@ | |||
28 | #include "unzip.h" | 28 | #include "unzip.h" |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Should filenames be treated as case sensitive? | ||
32 | */ | ||
33 | #define CASESENSITIVITY 0 | ||
34 | |||
35 | /** | ||
36 | * Maximum length of a filename allowed inside the ZIP archive. | 31 | * Maximum length of a filename allowed inside the ZIP archive. |
37 | */ | 32 | */ |
38 | #define MAXFILENAME 256 | 33 | #define MAXFILENAME 256 |
@@ -90,17 +85,17 @@ static struct Matches tmap[] = { | |||
90 | * @return NULL if no mimetype could be found, otherwise the mime type | 85 | * @return NULL if no mimetype could be found, otherwise the mime type |
91 | */ | 86 | */ |
92 | static char * | 87 | static char * |
93 | libextractor_oo_getmimetype (EXTRACTOR_unzip_file uf) | 88 | libextractor_oo_getmimetype (struct EXTRACTOR_UnzipFile * uf) |
94 | { | 89 | { |
95 | char filename_inzip[MAXFILENAME]; | 90 | char filename_inzip[MAXFILENAME]; |
96 | EXTRACTOR_unzip_file_info file_info; | 91 | struct EXTRACTOR_UnzipFileInfo file_info; |
97 | char *buf; | 92 | char *buf; |
98 | size_t buf_size; | 93 | size_t buf_size; |
99 | 94 | ||
100 | if (EXTRACTOR_UNZIP_OK != | 95 | if (EXTRACTOR_UNZIP_OK != |
101 | EXTRACTOR_common_unzip_local_file (uf, | 96 | EXTRACTOR_common_unzip_go_find_local_file (uf, |
102 | "mimetype", | 97 | "mimetype", |
103 | CASESENSITIVITY)) | 98 | 2)) |
104 | return NULL; | 99 | return NULL; |
105 | if (EXTRACTOR_UNZIP_OK != | 100 | if (EXTRACTOR_UNZIP_OK != |
106 | EXTRACTOR_common_unzip_get_current_file_info (uf, | 101 | EXTRACTOR_common_unzip_get_current_file_info (uf, |
@@ -113,11 +108,8 @@ libextractor_oo_getmimetype (EXTRACTOR_unzip_file uf) | |||
113 | 0)) | 108 | 0)) |
114 | return NULL; | 109 | return NULL; |
115 | if (EXTRACTOR_UNZIP_OK != | 110 | if (EXTRACTOR_UNZIP_OK != |
116 | EXTRACTOR_common_unzip_open_current_file3 (uf, NULL, NULL, 0)) | 111 | EXTRACTOR_common_unzip_open_current_file (uf)) |
117 | { | 112 | return NULL; |
118 | EXTRACTOR_common_unzip_close_current_file (uf); | ||
119 | return NULL; | ||
120 | } | ||
121 | buf_size = file_info.uncompressed_size; | 113 | buf_size = file_info.uncompressed_size; |
122 | if (buf_size > 1024) | 114 | if (buf_size > 1024) |
123 | { | 115 | { |
@@ -164,40 +156,25 @@ void | |||
164 | EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec) | 156 | EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec) |
165 | { | 157 | { |
166 | char filename_inzip[MAXFILENAME]; | 158 | char filename_inzip[MAXFILENAME]; |
167 | EXTRACTOR_unzip_file uf; | 159 | struct EXTRACTOR_UnzipFile *uf; |
168 | EXTRACTOR_unzip_file_info file_info; | 160 | struct EXTRACTOR_UnzipFileInfo file_info; |
169 | char *buf; | 161 | char *buf; |
170 | char *pbuf; | 162 | char *pbuf; |
171 | size_t buf_size; | 163 | size_t buf_size; |
172 | unsigned int i; | 164 | unsigned int i; |
173 | EXTRACTOR_unzip_filefunc_def io; | ||
174 | char *mimetype; | 165 | char *mimetype; |
175 | 166 | ||
176 | if (size < 100) | 167 | if (NULL == (uf = EXTRACTOR_common_unzip_open (ec))) |
177 | return 0; | ||
178 | if ( !( ('P'==data[0]) && ('K'==data[1]) && (0x03==data[2]) && (0x04==data[3])) ) | ||
179 | return 0; | ||
180 | |||
181 | io.zopen_file = &EXTRACTOR_common_unzip_zlib_open_file_func; | ||
182 | io.zread_file = &EXTRACTOR_common_unzip_zlib_read_file_func; | ||
183 | io.zwrite_file = NULL; | ||
184 | io.ztell_file = &EXTRACTOR_common_unzip_zlib_tell_file_func; | ||
185 | io.zseek_file = &EXTRACTOR_common_unzip_zlib_seek_file_func; | ||
186 | io.zclose_file = &EXTRACTOR_common_unzip_zlib_close_file_func; | ||
187 | io.zerror_file = &EXTRACTOR_common_unzip_zlib_testerror_file_func; | ||
188 | io.opaque = ec; | ||
189 | |||
190 | if (NULL == (uf = EXTRACTOR_common_unzip_open2 ("ERROR", &io))) | ||
191 | return; | 168 | return; |
192 | if (NULL != (mimetype = libextractor_oo_getmimetype (uf))) | 169 | if (NULL != (mimetype = libextractor_oo_getmimetype (uf))) |
193 | { | 170 | { |
194 | if (0 != proc (proc_cls, | 171 | if (0 != ec->proc (ec->cls, |
195 | "deb", | 172 | "odf", |
196 | EXTRACTOR_METATYPE_MIMETYPE, | 173 | EXTRACTOR_METATYPE_MIMETYPE, |
197 | EXTRACTOR_METAFORMAT_UTF8, | 174 | EXTRACTOR_METAFORMAT_UTF8, |
198 | "text/plain", | 175 | "text/plain", |
199 | mimetype, | 176 | mimetype, |
200 | strlen (mimetype) + 1)) | 177 | strlen (mimetype) + 1)) |
201 | { | 178 | { |
202 | EXTRACTOR_common_unzip_close (uf); | 179 | EXTRACTOR_common_unzip_close (uf); |
203 | free (mimetype); | 180 | free (mimetype); |
@@ -206,9 +183,9 @@ EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec) | |||
206 | free (mimetype); | 183 | free (mimetype); |
207 | } | 184 | } |
208 | if (EXTRACTOR_UNZIP_OK != | 185 | if (EXTRACTOR_UNZIP_OK != |
209 | EXTRACTOR_common_unzip_local_file (uf, | 186 | EXTRACTOR_common_unzip_go_find_local_file (uf, |
210 | METAFILE, | 187 | METAFILE, |
211 | CASESENSITIVITY)) | 188 | 2)) |
212 | { | 189 | { |
213 | /* metafile not found */ | 190 | /* metafile not found */ |
214 | EXTRACTOR_common_unzip_close (uf); | 191 | EXTRACTOR_common_unzip_close (uf); |
@@ -219,14 +196,14 @@ EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec) | |||
219 | &file_info, | 196 | &file_info, |
220 | filename_inzip, | 197 | filename_inzip, |
221 | sizeof (filename_inzip), | 198 | sizeof (filename_inzip), |
222 | NULL,0,NULL,0)) | 199 | NULL, 0, NULL, 0)) |
223 | { | 200 | { |
224 | /* problems accessing metafile */ | 201 | /* problems accessing metafile */ |
225 | EXTRACTOR_common_unzip_close (uf); | 202 | EXTRACTOR_common_unzip_close (uf); |
226 | return; | 203 | return; |
227 | } | 204 | } |
228 | if (EXTRACTOR_UNZIP_OK != | 205 | if (EXTRACTOR_UNZIP_OK != |
229 | EXTRACTOR_common_unzip_open_current_file3 (uf, NULL, NULL, 0)) | 206 | EXTRACTOR_common_unzip_open_current_file (uf)) |
230 | { | 207 | { |
231 | /* problems with unzip */ | 208 | /* problems with unzip */ |
232 | EXTRACTOR_common_unzip_close (uf); | 209 | EXTRACTOR_common_unzip_close (uf); |
@@ -320,16 +297,14 @@ EXTRACTOR_odf_extract_method (struct EXTRACTOR_ExtractContext *ec) | |||
320 | 297 | ||
321 | memcpy(key, spos, epos-spos); | 298 | memcpy(key, spos, epos-spos); |
322 | key[epos-spos] = '\0'; | 299 | key[epos-spos] = '\0'; |
323 | if (0 != proc (proc_cls, | 300 | if (0 != ec->proc (ec->cls, |
324 | "odf", | 301 | "odf", |
325 | tmap[i].type, | 302 | tmap[i].type, |
326 | EXTRACTOR_METAFORMAT_UTF8, | 303 | EXTRACTOR_METAFORMAT_UTF8, |
327 | "text/plain", | 304 | "text/plain", |
328 | key, | 305 | key, |
329 | epos - spos + 1)) | 306 | epos - spos + 1)) |
330 | { | 307 | goto CLEANUP; |
331 | goto CLEANUP; | ||
332 | } | ||
333 | pbuf = epos; | 308 | pbuf = epos; |
334 | } | 309 | } |
335 | else | 310 | else |
diff --git a/src/plugins/sid_extractor.c b/src/plugins/sid_extractor.c index 2465982..afc739b 100644 --- a/src/plugins/sid_extractor.c +++ b/src/plugins/sid_extractor.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of libextractor. | 2 | * This file is part of libextractor. |
3 | * (C) 2006, 2007 Toni Ruottu | 3 | * (C) 2006, 2007, 2012 Vidyut Samanta and Christian Grothoff |
4 | * | 4 | * |
5 | * libextractor is free software; you can redistribute it and/or modify | 5 | * libextractor is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
7 | * by the Free Software Foundation; either version 2, or (at your | 7 | * by the Free Software Foundation; either version 3, or (at your |
8 | * option) any later version. | 8 | * option) any later version. |
9 | * | 9 | * |
10 | * libextractor is distributed in the hope that it will be useful, but | 10 | * libextractor is distributed in the hope that it will be useful, but |
@@ -18,15 +18,17 @@ | |||
18 | * Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | /** | ||
22 | * @file plugins/sid_extractor.c | ||
23 | * @brief plugin to support Scream Tracker (S3M) files | ||
24 | * @author Toni Ruottu | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
21 | #include "platform.h" | 27 | #include "platform.h" |
22 | #include "extractor.h" | 28 | #include "extractor.h" |
23 | 29 | ||
24 | 30 | ||
25 | #define SID1_HEADER_SIZE 0x76 | 31 | /* SID flags */ |
26 | #define SID2_HEADER_SIZE 0x7c | ||
27 | |||
28 | /* flags */ | ||
29 | |||
30 | #define MUSPLAYER_FLAG 0x01 | 32 | #define MUSPLAYER_FLAG 0x01 |
31 | #define PLAYSID_FLAG 0x02 | 33 | #define PLAYSID_FLAG 0x02 |
32 | #define PAL_FLAG 0x04 | 34 | #define PAL_FLAG 0x04 |
@@ -34,51 +36,134 @@ | |||
34 | #define MOS6581_FLAG 0x10 | 36 | #define MOS6581_FLAG 0x10 |
35 | #define MOS8580_FLAG 0x20 | 37 | #define MOS8580_FLAG 0x20 |
36 | 38 | ||
39 | /** | ||
40 | * A "SID word". | ||
41 | */ | ||
37 | typedef char sidwrd[2]; | 42 | typedef char sidwrd[2]; |
43 | |||
44 | /** | ||
45 | * A "SID long". | ||
46 | */ | ||
38 | typedef char sidlongwrd[4]; | 47 | typedef char sidlongwrd[4]; |
39 | 48 | ||
49 | /** | ||
50 | * Header of a SID file. | ||
51 | */ | ||
40 | struct header | 52 | struct header |
41 | { | 53 | { |
54 | /** | ||
55 | * Magic string. | ||
56 | */ | ||
42 | char magicid[4]; | 57 | char magicid[4]; |
58 | |||
59 | /** | ||
60 | * Version number. | ||
61 | */ | ||
43 | sidwrd sidversion; | 62 | sidwrd sidversion; |
63 | |||
64 | /** | ||
65 | * Unknown. | ||
66 | */ | ||
44 | sidwrd dataoffset; | 67 | sidwrd dataoffset; |
68 | |||
69 | /** | ||
70 | * Unknown. | ||
71 | */ | ||
45 | sidwrd loadaddr; | 72 | sidwrd loadaddr; |
73 | |||
74 | /** | ||
75 | * Unknown. | ||
76 | */ | ||
46 | sidwrd initaddr; | 77 | sidwrd initaddr; |
78 | |||
79 | /** | ||
80 | * Unknown. | ||
81 | */ | ||
47 | sidwrd playaddr; | 82 | sidwrd playaddr; |
83 | |||
84 | /** | ||
85 | * Number of songs in file. | ||
86 | */ | ||
48 | sidwrd songs; | 87 | sidwrd songs; |
88 | |||
89 | /** | ||
90 | * Starting song. | ||
91 | */ | ||
49 | sidwrd firstsong; | 92 | sidwrd firstsong; |
93 | |||
94 | /** | ||
95 | * Unknown. | ||
96 | */ | ||
50 | sidlongwrd speed; | 97 | sidlongwrd speed; |
98 | |||
99 | /** | ||
100 | * Title of the album. | ||
101 | */ | ||
51 | char title[32]; | 102 | char title[32]; |
103 | |||
104 | /** | ||
105 | * Name of the artist. | ||
106 | */ | ||
52 | char artist[32]; | 107 | char artist[32]; |
108 | |||
109 | /** | ||
110 | * Copyright information. | ||
111 | */ | ||
53 | char copyright[32]; | 112 | char copyright[32]; |
54 | sidwrd flags; /* version 2 specific fields start */ | 113 | |
114 | /* version 2 specific fields start */ | ||
115 | |||
116 | /** | ||
117 | * Flags | ||
118 | */ | ||
119 | sidwrd flags; | ||
120 | |||
121 | /** | ||
122 | * Unknown. | ||
123 | */ | ||
55 | char startpage; | 124 | char startpage; |
125 | |||
126 | /** | ||
127 | * Unknown. | ||
128 | */ | ||
56 | char pagelength; | 129 | char pagelength; |
130 | |||
131 | /** | ||
132 | * Unknown. | ||
133 | */ | ||
57 | sidwrd reserved; | 134 | sidwrd reserved; |
58 | }; | 135 | }; |
59 | 136 | ||
137 | |||
138 | /** | ||
139 | * Convert a 'sidword' to an integer. | ||
140 | * | ||
141 | * @param data the sidword | ||
142 | * @return corresponding integer value | ||
143 | */ | ||
60 | static int | 144 | static int |
61 | sidword (const sidwrd data) | 145 | sidword (const sidwrd data) |
62 | { | 146 | { |
63 | int value = (unsigned char) data[0] * 0x100 + (unsigned char) data[1]; | 147 | return (unsigned char) data[0] * 0x100 + (unsigned char) data[1]; |
64 | return value; | ||
65 | |||
66 | } | 148 | } |
67 | 149 | ||
68 | #define ADD(s,t) do { if (0 != proc (proc_cls, "sid", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1)) return 1; } while (0) | ||
69 | 150 | ||
70 | /* "extract" keyword from a SID file | 151 | /** |
71 | * | 152 | * Give metadata to LE; return if 'proc' returns non-zero. |
72 | * This plugin is based on the nsf extractor | ||
73 | * | 153 | * |
154 | * @param s metadata value as UTF8 | ||
155 | * @param t metadata type to use | ||
74 | */ | 156 | */ |
157 | #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "sid", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return; } while (0) | ||
158 | |||
75 | 159 | ||
76 | int | 160 | /** |
77 | EXTRACTOR_sid_extract (const char *data, | 161 | * Extract metadata from SID files. |
78 | size_t size, | 162 | * |
79 | EXTRACTOR_MetaDataProcessor proc, | 163 | * @param ec extraction context |
80 | void *proc_cls, | 164 | */ |
81 | const char *options) | 165 | void |
166 | EXTRACTOR_sid_extract_method (struct EXTRACTOR_ExtractContext *ec) | ||
82 | { | 167 | { |
83 | unsigned int flags; | 168 | unsigned int flags; |
84 | int version; | 169 | int version; |
@@ -89,17 +174,19 @@ EXTRACTOR_sid_extract (const char *data, | |||
89 | char startingsong[32]; | 174 | char startingsong[32]; |
90 | char sidversion[32]; | 175 | char sidversion[32]; |
91 | const struct header *head; | 176 | const struct header *head; |
177 | void *data; | ||
92 | 178 | ||
93 | /* Check header size */ | 179 | if (sizeof (struct header) > |
94 | 180 | ec->read (ec->cls, | |
95 | if (size < SID1_HEADER_SIZE) | 181 | &data, |
96 | return 0; | 182 | sizeof (struct header))) |
97 | head = (const struct header *) data; | 183 | return; |
184 | head = data; | ||
98 | 185 | ||
99 | /* Check "magic" id bytes */ | 186 | /* Check "magic" id bytes */ |
100 | if (memcmp (head->magicid, "PSID", 4) && | 187 | if ( (0 != memcmp (head->magicid, "PSID", 4)) && |
101 | memcmp (head->magicid, "RSID", 4)) | 188 | (0 != memcmp (head->magicid, "RSID", 4)) ) |
102 | return 0; | 189 | return; |
103 | 190 | ||
104 | /* Mime-type */ | 191 | /* Mime-type */ |
105 | ADD ("audio/prs.sid", EXTRACTOR_METATYPE_MIMETYPE); | 192 | ADD ("audio/prs.sid", EXTRACTOR_METATYPE_MIMETYPE); |
@@ -107,25 +194,24 @@ EXTRACTOR_sid_extract (const char *data, | |||
107 | /* Version of SID format */ | 194 | /* Version of SID format */ |
108 | version = sidword (head->sidversion); | 195 | version = sidword (head->sidversion); |
109 | snprintf (sidversion, | 196 | snprintf (sidversion, |
110 | sizeof(sidversion), | 197 | sizeof (sidversion), |
111 | "%d", | 198 | "%d", |
112 | version); | 199 | version); |
113 | ADD (sidversion, EXTRACTOR_METATYPE_FORMAT_VERSION); | 200 | ADD (sidversion, EXTRACTOR_METATYPE_FORMAT_VERSION); |
114 | 201 | ||
115 | /* Get song count */ | 202 | /* Get song count */ |
116 | snprintf (songs, | 203 | snprintf (songs, |
117 | sizeof(songs), | 204 | sizeof (songs), |
118 | "%d", sidword (head->songs)); | 205 | "%d", sidword (head->songs)); |
119 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); | 206 | ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT); |
120 | 207 | ||
121 | /* Get number of the first song to be played */ | 208 | /* Get number of the first song to be played */ |
122 | snprintf (startingsong, | 209 | snprintf (startingsong, |
123 | sizeof(startingsong), | 210 | sizeof (startingsong), |
124 | "%d", | 211 | "%d", |
125 | sidword (head->firstsong)); | 212 | sidword (head->firstsong)); |
126 | ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG); | 213 | ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG); |
127 | 214 | ||
128 | |||
129 | /* name, artist, copyright fields */ | 215 | /* name, artist, copyright fields */ |
130 | memcpy (&album, head->title, 32); | 216 | memcpy (&album, head->title, 32); |
131 | album[32] = '\0'; | 217 | album[32] = '\0'; |
@@ -139,9 +225,8 @@ EXTRACTOR_sid_extract (const char *data, | |||
139 | copyright[32] = '\0'; | 225 | copyright[32] = '\0'; |
140 | ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT); | 226 | ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT); |
141 | 227 | ||
142 | 228 | if (version < 2) | |
143 | if ( (version < 2) || (size < SID2_HEADER_SIZE)) | 229 | return; |
144 | return 0; | ||
145 | 230 | ||
146 | /* Version 2 specific options follow | 231 | /* Version 2 specific options follow |
147 | * | 232 | * |
@@ -150,42 +235,25 @@ EXTRACTOR_sid_extract (const char *data, | |||
150 | */ | 235 | */ |
151 | flags = sidword (head->flags); | 236 | flags = sidword (head->flags); |
152 | /* MUS data */ | 237 | /* MUS data */ |
153 | if (flags & MUSPLAYER_FLAG) | 238 | if (0 != (flags & MUSPLAYER_FLAG)) |
154 | ADD ("Compute!'s Sidplayer", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE); | 239 | ADD ("Compute!'s Sidplayer", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE); |
155 | 240 | ||
156 | /* PlaySID data */ | 241 | /* PlaySID data */ |
157 | if (flags & PLAYSID_FLAG) | 242 | if (0 != (flags & PLAYSID_FLAG)) |
158 | ADD ("PlaySID", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE); | 243 | ADD ("PlaySID", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE); |
159 | 244 | ||
160 | 245 | ||
161 | /* PAL or NTSC */ | 246 | /* PAL or NTSC */ |
162 | 247 | if (0 != (flags & NTSC_FLAG)) | |
163 | if (flags & PAL_FLAG) | 248 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
164 | { | 249 | else if (0 != (flags & PAL_FLAG)) |
165 | if (flags & NTSC_FLAG) | 250 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
166 | ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | ||
167 | else | ||
168 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | ||
169 | } | ||
170 | else | ||
171 | { | ||
172 | if (flags & NTSC_FLAG) | ||
173 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | ||
174 | } | ||
175 | 251 | ||
176 | /* Detect SID Chips suitable for play the files */ | 252 | /* Detect SID Chips suitable for play the files */ |
177 | if (flags & MOS6581_FLAG) | 253 | if (0 != (flags & MOS8580_FLAG)) |
178 | { | 254 | ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
179 | if (flags & MOS8580_FLAG) | 255 | else if (0 != (flags & MOS6581_FLAG)) |
180 | ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | 256 | ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); |
181 | else | ||
182 | ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | if (flags & MOS8580_FLAG) | ||
187 | ADD ("MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | 257 | } |
258 | |||
259 | /* end of sid_extractor.c */ | ||
diff --git a/src/plugins/test_deb.c b/src/plugins/test_deb.c new file mode 100644 index 0000000..93a5586 --- /dev/null +++ b/src/plugins/test_deb.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | This file is part of libextractor. | ||
3 | (C) 2012 Vidyut Samanta and Christian Grothoff | ||
4 | |||
5 | libextractor is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | libextractor is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with libextractor; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file plugins/test_deb.c | ||
22 | * @brief testcase for deb plugin | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "test_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Main function for the DEB testcase. | ||
31 | * | ||
32 | * @param argc number of arguments (ignored) | ||
33 | * @param argv arguments (ignored) | ||
34 | * @return 0 on success | ||
35 | */ | ||
36 | int | ||
37 | main (int argc, char *argv[]) | ||
38 | { | ||
39 | struct SolutionData deb_bzip2_sol[] = | ||
40 | { | ||
41 | { | ||
42 | EXTRACTOR_METATYPE_MIMETYPE, | ||
43 | EXTRACTOR_METAFORMAT_UTF8, | ||
44 | "text/plain", | ||
45 | "application/x-debian-package", | ||
46 | strlen ("application/x-debian-package") + 1, | ||
47 | 0 | ||
48 | }, | ||
49 | { | ||
50 | EXTRACTOR_METATYPE_PACKAGE_NAME, | ||
51 | EXTRACTOR_METAFORMAT_UTF8, | ||
52 | "text/plain", | ||
53 | "bzip2", | ||
54 | strlen ("bzip2") + 1, | ||
55 | 0 | ||
56 | }, | ||
57 | { | ||
58 | EXTRACTOR_METATYPE_PACKAGE_VERSION, | ||
59 | EXTRACTOR_METAFORMAT_UTF8, | ||
60 | "text/plain", | ||
61 | "1.0.6-4", | ||
62 | strlen ("1.0.6-4") + 1, | ||
63 | 0 | ||
64 | }, | ||
65 | { | ||
66 | EXTRACTOR_METATYPE_TARGET_ARCHITECTURE, | ||
67 | EXTRACTOR_METAFORMAT_UTF8, | ||
68 | "text/plain", | ||
69 | "i386", | ||
70 | strlen ("i386") + 1, | ||
71 | 0 | ||
72 | }, | ||
73 | { | ||
74 | EXTRACTOR_METATYPE_PACKAGE_MAINTAINER, | ||
75 | EXTRACTOR_METAFORMAT_UTF8, | ||
76 | "text/plain", | ||
77 | "Anibal Monsalve Salazar <anibal@debian.org>", | ||
78 | strlen ("Anibal Monsalve Salazar <anibal@debian.org>") + 1, | ||
79 | 0 | ||
80 | }, | ||
81 | { | ||
82 | EXTRACTOR_METATYPE_PACKAGE_INSTALLED_SIZE, | ||
83 | EXTRACTOR_METAFORMAT_UTF8, | ||
84 | "text/plain", | ||
85 | "113", /* FIXME: should this be 'kb'? */ | ||
86 | strlen ("113") + 1, | ||
87 | 0 | ||
88 | }, | ||
89 | { | ||
90 | EXTRACTOR_METATYPE_PACKAGE_DEPENDENCY, | ||
91 | EXTRACTOR_METAFORMAT_UTF8, | ||
92 | "text/plain", | ||
93 | "libbz2-1.0 (= 1.0.6-4), libc6 (>= 2.4)", | ||
94 | strlen ("libbz2-1.0 (= 1.0.6-4), libc6 (>= 2.4)") + 1, | ||
95 | 0 | ||
96 | }, | ||
97 | { | ||
98 | EXTRACTOR_METATYPE_PACKAGE_SUGGESTS, | ||
99 | EXTRACTOR_METAFORMAT_UTF8, | ||
100 | "text/plain", | ||
101 | "bzip2-doc", | ||
102 | strlen ("bzip2-doc") + 1, | ||
103 | 0 | ||
104 | }, | ||
105 | { | ||
106 | EXTRACTOR_METATYPE_PACKAGE_REPLACES, | ||
107 | EXTRACTOR_METAFORMAT_UTF8, | ||
108 | "text/plain", | ||
109 | "libbz2 (<< 0.9.5d-3)", | ||
110 | strlen ("libbz2 (<< 0.9.5d-3)") + 1, | ||
111 | 0 | ||
112 | }, | ||
113 | { | ||
114 | EXTRACTOR_METATYPE_SECTION, | ||
115 | EXTRACTOR_METAFORMAT_UTF8, | ||
116 | "text/plain", | ||
117 | "utils", | ||
118 | strlen ("utils") + 1, | ||
119 | 0 | ||
120 | }, | ||
121 | { | ||
122 | EXTRACTOR_METATYPE_UPLOAD_PRIORITY, | ||
123 | EXTRACTOR_METAFORMAT_UTF8, | ||
124 | "text/plain", | ||
125 | "standard", | ||
126 | strlen ("standard") + 1, | ||
127 | 0 | ||
128 | }, | ||
129 | #if 0 | ||
130 | { | ||
131 | EXTRACTOR_METATYPE_DESCRIPTION, | ||
132 | EXTRACTOR_METAFORMAT_UTF8, | ||
133 | "text/plain", | ||
134 | "", | ||
135 | strlen ("") + 1, | ||
136 | 0 | ||
137 | }, | ||
138 | #endif | ||
139 | { 0, 0, NULL, NULL, 0, -1 } | ||
140 | }; | ||
141 | struct ProblemSet ps[] = | ||
142 | { | ||
143 | { "testdata/deb_bzip2.deb", | ||
144 | deb_bzip2_sol }, | ||
145 | { NULL, NULL } | ||
146 | }; | ||
147 | return ET_main ("deb", ps); | ||
148 | } | ||
149 | |||
150 | /* end of test_deb.c */ | ||
diff --git a/src/plugins/test_odf.c b/src/plugins/test_odf.c new file mode 100644 index 0000000..be5205b --- /dev/null +++ b/src/plugins/test_odf.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | This file is part of libextractor. | ||
3 | (C) 2012 Vidyut Samanta and Christian Grothoff | ||
4 | |||
5 | libextractor is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | libextractor is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with libextractor; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file plugins/test_odf.c | ||
22 | * @brief testcase for odf plugin | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "test_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Main function for the ODF testcase. | ||
31 | * | ||
32 | * @param argc number of arguments (ignored) | ||
33 | * @param argv arguments (ignored) | ||
34 | * @return 0 on success | ||
35 | */ | ||
36 | int | ||
37 | main (int argc, char *argv[]) | ||
38 | { | ||
39 | struct SolutionData odf_cg_sol[] = | ||
40 | { | ||
41 | { | ||
42 | EXTRACTOR_METATYPE_MIMETYPE, | ||
43 | EXTRACTOR_METAFORMAT_UTF8, | ||
44 | "text/plain", | ||
45 | "application/vnd.oasis.opendocument.text", | ||
46 | strlen ("application/vnd.oasis.opendocument.text") + 1, | ||
47 | 0 | ||
48 | }, | ||
49 | { | ||
50 | EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE, | ||
51 | EXTRACTOR_METAFORMAT_UTF8, | ||
52 | "text/plain", | ||
53 | "OpenOffice.org/3.2$Unix OpenOffice.org_project/320m12$Build-9483", | ||
54 | strlen ("OpenOffice.org/3.2$Unix OpenOffice.org_project/320m12$Build-9483") + 1, | ||
55 | 0 | ||
56 | }, | ||
57 | { | ||
58 | EXTRACTOR_METATYPE_PAGE_COUNT, | ||
59 | EXTRACTOR_METAFORMAT_UTF8, | ||
60 | "text/plain", | ||
61 | "1", | ||
62 | strlen ("1") + 1, | ||
63 | 0 | ||
64 | }, | ||
65 | { | ||
66 | EXTRACTOR_METATYPE_CREATION_DATE, | ||
67 | EXTRACTOR_METAFORMAT_UTF8, | ||
68 | "text/plain", | ||
69 | "2005-11-22T11:44:00", | ||
70 | strlen ("2005-11-22T11:44:00") + 1, | ||
71 | 0 | ||
72 | }, | ||
73 | { | ||
74 | EXTRACTOR_METATYPE_UNKNOWN_DATE, | ||
75 | EXTRACTOR_METAFORMAT_UTF8, | ||
76 | "text/plain", | ||
77 | "2010-06-09T13:09:34", | ||
78 | strlen ("2010-06-09T13:09:34") + 1, | ||
79 | 0 | ||
80 | }, | ||
81 | { | ||
82 | EXTRACTOR_METATYPE_TITLE, | ||
83 | EXTRACTOR_METAFORMAT_UTF8, | ||
84 | "text/plain", | ||
85 | "Anhang 1: Profile der beteiligten Wissenschaftler", | ||
86 | strlen ("Anhang 1: Profile der beteiligten Wissenschaftler") + 1, | ||
87 | 0 | ||
88 | }, | ||
89 | { 0, 0, NULL, NULL, 0, -1 } | ||
90 | }; | ||
91 | struct ProblemSet ps[] = | ||
92 | { | ||
93 | { "testdata/odf_cg.odt", | ||
94 | odf_cg_sol }, | ||
95 | { NULL, NULL } | ||
96 | }; | ||
97 | return ET_main ("odf", ps); | ||
98 | } | ||
99 | |||
100 | /* end of test_odf.c */ | ||
diff --git a/src/plugins/test_zip.c b/src/plugins/test_zip.c new file mode 100644 index 0000000..855a30f --- /dev/null +++ b/src/plugins/test_zip.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | This file is part of libextractor. | ||
3 | (C) 2012 Vidyut Samanta and Christian Grothoff | ||
4 | |||
5 | libextractor is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | libextractor is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with libextractor; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file plugins/test_zip.c | ||
22 | * @brief testcase for zip plugin | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "test_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Main function for the ZIP testcase. | ||
31 | * | ||
32 | * @param argc number of arguments (ignored) | ||
33 | * @param argv arguments (ignored) | ||
34 | * @return 0 on success | ||
35 | */ | ||
36 | int | ||
37 | main (int argc, char *argv[]) | ||
38 | { | ||
39 | struct SolutionData zip_test_sol[] = | ||
40 | { | ||
41 | { | ||
42 | EXTRACTOR_METATYPE_MIMETYPE, | ||
43 | EXTRACTOR_METAFORMAT_UTF8, | ||
44 | "text/plain", | ||
45 | "application/zip", | ||
46 | strlen ("application/zip") + 1, | ||
47 | 0 | ||
48 | }, | ||
49 | { | ||
50 | EXTRACTOR_METATYPE_COMMENT, | ||
51 | EXTRACTOR_METAFORMAT_C_STRING, | ||
52 | "text/plain", | ||
53 | "global zipfile comment", | ||
54 | strlen ("global zipfile comment") + 1, | ||
55 | 0 | ||
56 | }, | ||
57 | { | ||
58 | EXTRACTOR_METATYPE_FILENAME, | ||
59 | EXTRACTOR_METAFORMAT_C_STRING, | ||
60 | "text/plain", | ||
61 | "ChangeLog", | ||
62 | strlen ("ChangeLog") + 1, | ||
63 | 0 | ||
64 | }, | ||
65 | { | ||
66 | EXTRACTOR_METATYPE_FILENAME, | ||
67 | EXTRACTOR_METAFORMAT_C_STRING, | ||
68 | "text/plain", | ||
69 | "test.png", | ||
70 | strlen ("test.png") + 1, | ||
71 | 0 | ||
72 | }, | ||
73 | { | ||
74 | EXTRACTOR_METATYPE_COMMENT, | ||
75 | EXTRACTOR_METAFORMAT_C_STRING, | ||
76 | "text/plain", | ||
77 | "comment for test.png", | ||
78 | strlen ("comment for test.png") + 1, | ||
79 | 0 | ||
80 | }, | ||
81 | { | ||
82 | EXTRACTOR_METATYPE_FILENAME, | ||
83 | EXTRACTOR_METAFORMAT_C_STRING, | ||
84 | "text/plain", | ||
85 | "test.jpg", | ||
86 | strlen ("test.jpg") + 1, | ||
87 | 0 | ||
88 | }, | ||
89 | { | ||
90 | EXTRACTOR_METATYPE_COMMENT, | ||
91 | EXTRACTOR_METAFORMAT_C_STRING, | ||
92 | "text/plain", | ||
93 | "comment for test.jpg", | ||
94 | strlen ("comment for test.jpg") + 1, | ||
95 | 0 | ||
96 | }, | ||
97 | { 0, 0, NULL, NULL, 0, -1 } | ||
98 | }; | ||
99 | struct ProblemSet ps[] = | ||
100 | { | ||
101 | { "testdata/zip_test.zip", | ||
102 | zip_test_sol }, | ||
103 | { NULL, NULL } | ||
104 | }; | ||
105 | return ET_main ("zip", ps); | ||
106 | } | ||
107 | |||
108 | /* end of test_zip.c */ | ||
diff --git a/src/plugins/testdata/deb_bzip2.deb b/src/plugins/testdata/deb_bzip2.deb new file mode 100644 index 0000000..4b74b15 --- /dev/null +++ b/src/plugins/testdata/deb_bzip2.deb | |||
Binary files differ | |||
diff --git a/src/plugins/testdata/odf_cg.odt b/src/plugins/testdata/odf_cg.odt new file mode 100644 index 0000000..cfd40e5 --- /dev/null +++ b/src/plugins/testdata/odf_cg.odt | |||
Binary files differ | |||
diff --git a/src/plugins/testdata/zip_test.zip b/src/plugins/testdata/zip_test.zip new file mode 100644 index 0000000..564b43a --- /dev/null +++ b/src/plugins/testdata/zip_test.zip | |||
Binary files differ | |||
diff --git a/src/plugins/zip_extractor.c b/src/plugins/zip_extractor.c index 8738295..23da67c 100644 --- a/src/plugins/zip_extractor.c +++ b/src/plugins/zip_extractor.c | |||
@@ -1,50 +1,10 @@ | |||
1 | /** | ||
2 | zipextractor.c version 0.0.2 | ||
3 | |||
4 | Changes from 0.0.1 to 0.0.2 | ||
5 | -> Searches for central dir struct from end of file if this is a self-extracting executable | ||
6 | |||
7 | |||
8 | This file was based on mp3extractor.c (0.1.2) | ||
9 | |||
10 | Currently, this only returns a list of the filenames within a zipfile | ||
11 | and any comments on each file or the whole file itself. File sizes, | ||
12 | modification times, and crc's are currently ignored. | ||
13 | |||
14 | TODO: Break the comments up into small, atomically, searchable chunks (keywords) | ||
15 | - might need some knowledge of English? | ||
16 | |||
17 | It returns: | ||
18 | |||
19 | one EXTRACTOR_MIMETYPE | ||
20 | multiple EXTRACTOR_FILENAME | ||
21 | multiple EXTRACTOR_COMMENT | ||
22 | |||
23 | ... from a .ZIP file | ||
24 | |||
25 | TODO: EXTRACTOR_DATE, EXTRACTOR_DESCRIPTION, EXTRACTOR_KEYWORDS, others? | ||
26 | |||
27 | Does NOT test data integrity (CRCs etc.) | ||
28 | |||
29 | This version is not recursive (i.e. doesn't look inside zip | ||
30 | files within zip files) | ||
31 | |||
32 | TODO: Run extract on files inside of archive (?) (i.e. gif, mp3, etc.) | ||
33 | |||
34 | The current .ZIP format description: | ||
35 | ftp://ftp.pkware.com/appnote.zip | ||
36 | |||
37 | No Copyright 2003 Julia Wolf | ||
38 | |||
39 | */ | ||
40 | |||
41 | /* | 1 | /* |
42 | * This file is part of libextractor. | 2 | * This file is part of libextractor. |
43 | * (C) 2002, 2003, 2009 Vidyut Samanta and Christian Grothoff | 3 | * (C) 2012 Vidyut Samanta and Christian Grothoff |
44 | * | 4 | * |
45 | * libextractor is free software; you can redistribute it and/or modify | 5 | * libextractor is free software; you can redistribute it and/or modify |
46 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
47 | * by the Free Software Foundation; either version 2, or (at your | 7 | * by the Free Software Foundation; either version 3, or (at your |
48 | * option) any later version. | 8 | * option) any later version. |
49 | * | 9 | * |
50 | * libextractor is distributed in the hope that it will be useful, but | 10 | * libextractor is distributed in the hope that it will be useful, but |
@@ -57,354 +17,113 @@ | |||
57 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
58 | * Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
59 | */ | 19 | */ |
60 | 20 | /** | |
21 | * @file plugins/zip_extractor.c | ||
22 | * @brief plugin to support ZIP files | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
61 | #include "platform.h" | 25 | #include "platform.h" |
26 | #include <ctype.h> | ||
62 | #include "extractor.h" | 27 | #include "extractor.h" |
63 | 28 | #include "unzip.h" | |
64 | #define DEBUG_EXTRACT_ZIP 0 | ||
65 | |||
66 | /* In a zipfile there are two kinds of comments. One is a big one for the | ||
67 | entire .zip, it's usually a BBS ad. The other is a small comment on each | ||
68 | individual file; most people don't use this. | ||
69 | */ | ||
70 | |||
71 | /* TODO: zip_entry linked list is handeled kinda messily, should clean up (maybe) */ | ||
72 | typedef struct | ||
73 | { | ||
74 | char *filename; | ||
75 | char *comment; | ||
76 | void *next; | ||
77 | } zip_entry; | ||
78 | 29 | ||
79 | /* mimetype = application/zip */ | ||
80 | int | ||
81 | EXTRACTOR_zip_extract (const unsigned char *data, | ||
82 | size_t size, | ||
83 | EXTRACTOR_MetaDataProcessor proc, | ||
84 | void *proc_cls, | ||
85 | const char *options) | ||
86 | { | ||
87 | int ret; | ||
88 | void *tmp; | ||
89 | zip_entry * info; | ||
90 | zip_entry * start; | ||
91 | char *filecomment; | ||
92 | const unsigned char *pos; | ||
93 | unsigned int offset, stop; | ||
94 | unsigned int name_length; | ||
95 | unsigned int extra_length; | ||
96 | unsigned int comment_length; | ||
97 | unsigned int filecomment_length; | ||
98 | unsigned int entry_count; | ||
99 | #if DEBUG_EXTRACT_ZIP | ||
100 | unsigned int entry_total; | ||
101 | #endif | ||
102 | |||
103 | /* I think the smallest zipfile you can have is about 120 bytes */ | ||
104 | if ((NULL == data) || (size < 100)) | ||
105 | return 0; | ||
106 | if (! (('P' == data[0]) && ('K' == data[1]) && (0x03 == data[2]) | ||
107 | && (0x04 == data[3]))) | ||
108 | return 0; | ||
109 | |||
110 | /* The filenames for each file in a zipfile are stored in two locations. | ||
111 | * There is one at the start of each entry, just before the compressed data, | ||
112 | * and another at the end in a 'central directory structure'. | ||
113 | * | ||
114 | * In order to catch self-extracting executables, we scan backwards from the end | ||
115 | * of the file looking for the central directory structure. The previous version | ||
116 | * of this went forewards through the local headers, but that only works for plain | ||
117 | * vanilla zip's and I don't feel like writing a special case for each of the dozen | ||
118 | * self-extracting executable stubs. | ||
119 | * | ||
120 | * This assumes that the zip file is considered to be non-corrupt/non-truncated. | ||
121 | * If it is truncated then it's not considered to be a zip and skipped. | ||
122 | * | ||
123 | */ | ||
124 | |||
125 | /* From appnote.iz and appnote.txt (more or less) | ||
126 | * | ||
127 | * (this is why you always need to put in the last floppy if you span disks) | ||
128 | * | ||
129 | * 0- 3 end of central dir signature 4 bytes (0x06054b50) P K ^E ^F | ||
130 | * 4- 5 number of this disk 2 bytes | ||
131 | * 6- 7 number of the disk with the | ||
132 | * start of the central directory 2 bytes | ||
133 | * 8- 9 total number of entries in | ||
134 | * the central dir on this disk 2 bytes | ||
135 | * 10-11 total number of entries in | ||
136 | * the central dir 2 bytes | ||
137 | * 12-15 size of the central directory 4 bytes | ||
138 | * 16-19 offset of start of central | ||
139 | * directory with respect to | ||
140 | * the starting disk number 4 bytes | ||
141 | * 20-21 zipfile comment length 2 bytes | ||
142 | * 22-?? zipfile comment (variable size) max length 65536 bytes | ||
143 | */ | ||
144 | |||
145 | /* the signature can't be more than 22 bytes from the end */ | ||
146 | offset = size - 22; | ||
147 | pos = &data[offset]; | ||
148 | stop = 0; | ||
149 | if (((signed int) size - 65556) > 0) | ||
150 | stop = size - 65556; | ||
151 | |||
152 | /* not using int 0x06054b50 so that we don't have to deal with endianess issues. | ||
153 | break out if we go more than 64K backwards and havn't found it, or if we hit the | ||
154 | begining of the file. */ | ||
155 | while ((!(('P' == pos[0]) && ('K' == pos[1]) && (0x05 == pos[2]) | ||
156 | && (0x06 == pos[3]))) && (offset > stop)) | ||
157 | pos = &data[offset--]; | ||
158 | if (offset == stop) | ||
159 | { | ||
160 | #if DEBUG_EXTRACT_ZIP | ||
161 | fprintf (stderr, | ||
162 | "Did not find end of central directory structure signature. offset: %i\n", | ||
163 | offset); | ||
164 | |||
165 | #endif | ||
166 | return 0; | ||
167 | } | ||
168 | 30 | ||
169 | /* offset should now point to the start of the end-of-central directory structure */ | 31 | /** |
170 | /* and pos[0] should be pointing there too */ | 32 | * Main entry method for the 'application/zip' extraction plugin. |
171 | /* so slurp down filecomment while here... */ | 33 | * |
172 | filecomment_length = pos[20] + (pos[21] << 8); | 34 | * @param ec extraction context provided to the plugin |
173 | if (filecomment_length + offset + 22 > size) | 35 | */ |
174 | { | 36 | void |
175 | return 0; /* invalid zip file format! */ | 37 | EXTRACTOR_zip_extract_method (struct EXTRACTOR_ExtractContext *ec) |
176 | } | 38 | { |
177 | filecomment = NULL; | 39 | struct EXTRACTOR_UnzipFile *uf; |
178 | if (filecomment_length > 0) | 40 | struct EXTRACTOR_UnzipFileInfo fi; |
41 | char fname[256]; | ||
42 | char fcomment[256]; | ||
43 | |||
44 | if (NULL == (uf = EXTRACTOR_common_unzip_open (ec))) | ||
45 | return; | ||
46 | if ( (EXTRACTOR_UNZIP_OK == | ||
47 | EXTRACTOR_common_unzip_go_find_local_file (uf, | ||
48 | "meta.xml", | ||
49 | 2)) || | ||
50 | (EXTRACTOR_UNZIP_OK == | ||
51 | EXTRACTOR_common_unzip_go_find_local_file (uf, | ||
52 | "META-INF/MANIFEST.MF", | ||
53 | 2)) ) | ||
179 | { | 54 | { |
180 | filecomment = malloc (filecomment_length + 1); | 55 | /* not a normal zip, might be odf, jar, etc. */ |
181 | if (filecomment != NULL) | 56 | goto CLEANUP; |
182 | { | ||
183 | memcpy (filecomment, &pos[22], filecomment_length); | ||
184 | filecomment[filecomment_length] = '\0'; | ||
185 | } | ||
186 | } | 57 | } |
187 | 58 | if (EXTRACTOR_UNZIP_OK != | |
188 | #if DEBUG_EXTRACT_ZIP | 59 | EXTRACTOR_common_unzip_go_to_first_file (uf)) |
189 | if ((0 != pos[4]) && (0 != pos[5])) | 60 | { |
190 | fprintf (stderr, | 61 | /* zip malformed? */ |
191 | "WARNING: This seems to be the last disk in a multi-volume" | 62 | goto CLEANUP; |
192 | " ZIP archive, and so this might not work.\n"); | 63 | } |
193 | #endif | 64 | if (0 != |
194 | 65 | ec->proc (ec->cls, | |
195 | #if DEBUG_EXTRACT_ZIP | 66 | "zip", |
196 | if ((pos[8] != pos[10]) && (pos[9] != pos[11])) | 67 | EXTRACTOR_METATYPE_MIMETYPE, |
197 | fprintf (stderr, | 68 | EXTRACTOR_METAFORMAT_UTF8, |
198 | "WARNING: May not be able to find all the files in this" | 69 | "text/plain", |
199 | " ZIP archive (no multi-volume support right now).\n"); | 70 | "application/zip", |
200 | entry_total = pos[10] + (pos[11] << 8); | 71 | strlen ("application/zip") + 1)) |
201 | #endif | 72 | goto CLEANUP; |
202 | entry_count = 0; | 73 | if (EXTRACTOR_UNZIP_OK == |
203 | 74 | EXTRACTOR_common_unzip_get_global_comment (uf, | |
204 | /* jump to start of central directory, ASSUMING that the starting disk that it's on is disk 0 */ | 75 | fcomment, |
205 | /* starting disk would otherwise be pos[6]+pos[7]<<8 */ | 76 | sizeof (fcomment))) |
206 | offset = pos[16] + (pos[17] << 8) + (pos[18] << 16) + (pos[19] << 24); /* offset of cent-dir from start of disk 0 */ | ||
207 | |||
208 | /* stop = pos[12] + (pos[13]<<8) + (pos[14]<<16) + (pos[15]<<24); *//* length of central dir */ | ||
209 | if (offset + 46 > size) | ||
210 | { | 77 | { |
211 | 78 | if ( (0 != strlen (fcomment)) && | |
212 | /* not a zip */ | 79 | (0 != |
213 | if (filecomment != NULL) | 80 | ec->proc (ec->cls, |
214 | free (filecomment); | 81 | "zip", |
215 | return 0; | 82 | EXTRACTOR_METATYPE_COMMENT, |
83 | EXTRACTOR_METAFORMAT_C_STRING, | ||
84 | "text/plain", | ||
85 | fcomment, | ||
86 | strlen (fcomment) + 1))) | ||
87 | goto CLEANUP; | ||
216 | } | 88 | } |
217 | pos = &data[offset]; /* jump */ | ||
218 | |||
219 | /* we should now be at the begining of the central directory structure */ | ||
220 | |||
221 | /* from appnote.txt and appnote.iz (mostly) | ||
222 | * | ||
223 | * 0- 3 central file header signature 4 bytes (0x02014b50) | ||
224 | * 4- 5 version made by 2 bytes | ||
225 | * 6- 7 version needed to extract 2 bytes | ||
226 | * 8- 9 general purpose bit flag 2 bytes | ||
227 | * 10-11 compression method 2 bytes | ||
228 | * 12-13 last mod file time 2 bytes | ||
229 | * 14-15 last mod file date 2 bytes | ||
230 | * 16-19 crc-32 4 bytes | ||
231 | * 20-23 compressed size 4 bytes | ||
232 | * 24-27 uncompressed size 4 bytes | ||
233 | * 28-29 filename length 2 bytes | ||
234 | * 30-31 extra field length 2 bytes | ||
235 | * 32-33 file comment length 2 bytes | ||
236 | * 34-35 disk number start 2 bytes | ||
237 | * 36-37 internal file attributes 2 bytes | ||
238 | * 38-41 external file attributes 4 bytes | ||
239 | * 42-45 relative offset of local header 4 bytes | ||
240 | * | ||
241 | * 46-?? filename (variable size) | ||
242 | * ?- ? extra field (variable size) | ||
243 | * ?- ? file comment (variable size) | ||
244 | */ | ||
245 | if (!(('P' == pos[0]) && ('K' == pos[1]) && (0x01 == pos[2]) | ||
246 | && (0x02 == pos[3]))) | ||
247 | { | ||
248 | #if DEBUG_EXTRACT_ZIP | ||
249 | fprintf (stderr, | ||
250 | "Did not find central directory structure signature. offset: %i\n", | ||
251 | offset); | ||
252 | |||
253 | #endif | ||
254 | if (filecomment != NULL) | ||
255 | free (filecomment); | ||
256 | return 0; | ||
257 | } | ||
258 | start = NULL; | ||
259 | info = NULL; | ||
260 | |||
261 | do | 89 | do |
262 | { /* while ( (0x01==pos[2])&&(0x02==pos[3]) ) */ | ||
263 | entry_count++; /* check to make sure we found everything at the end */ | ||
264 | name_length = pos[28] + (pos[29] << 8); | ||
265 | extra_length = pos[30] + (pos[31] << 8); | ||
266 | comment_length = pos[32] + (pos[33] << 8); | ||
267 | if (name_length + extra_length + comment_length + offset + 46 > size) | ||
268 | { | ||
269 | |||
270 | /* ok, invalid, abort! */ | ||
271 | break; | ||
272 | } | ||
273 | |||
274 | #if DEBUG_EXTRACT_ZIP | ||
275 | fprintf (stderr, "Found filename length %i Comment length: %i\n", | ||
276 | name_length, comment_length); | ||
277 | |||
278 | #endif | ||
279 | /* yay, finally get filenames */ | ||
280 | if (start == NULL) | ||
281 | { | ||
282 | start = malloc (sizeof (zip_entry)); | ||
283 | if (start == NULL) | ||
284 | break; | ||
285 | start->next = NULL; | ||
286 | info = start; | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | info->next = malloc (sizeof (zip_entry)); | ||
291 | if (info->next == NULL) | ||
292 | break; | ||
293 | info = info->next; | ||
294 | info->next = NULL; | ||
295 | } | ||
296 | info->filename = malloc (name_length + 1); | ||
297 | info->comment = malloc (comment_length + 1); | ||
298 | |||
299 | /* (strings in zip files are not null terminated) */ | ||
300 | if (info->filename != NULL) | ||
301 | { | ||
302 | memcpy (info->filename, &pos[46], name_length); | ||
303 | info->filename[name_length] = '\0'; | ||
304 | } | ||
305 | if (info->comment != NULL) | ||
306 | { | ||
307 | memcpy (info->comment, &pos[46 + name_length + extra_length], | ||
308 | comment_length); | ||
309 | info->comment[comment_length] = '\0'; | ||
310 | } | ||
311 | offset += 46 + name_length + extra_length + comment_length; | ||
312 | pos = &data[offset]; | ||
313 | /* check for next header entry (0x02014b50) or (0x06054b50) if at end */ | ||
314 | if (('P' != pos[0]) && ('K' != pos[1])) | ||
315 | { | ||
316 | #if DEBUG_EXTRACT_ZIP | ||
317 | fprintf (stderr, | ||
318 | "Did not find next header in central directory.\n"); | ||
319 | |||
320 | #endif | ||
321 | info = start; | ||
322 | while (info != NULL) | ||
323 | { | ||
324 | start = info->next; | ||
325 | if (info->filename != NULL) | ||
326 | free (info->filename); | ||
327 | if (info->comment != NULL) | ||
328 | free (info->comment); | ||
329 | free (info); | ||
330 | info = start; | ||
331 | } | ||
332 | if (filecomment != NULL) | ||
333 | free (filecomment); | ||
334 | return 0; | ||
335 | } | ||
336 | } | ||
337 | while ((0x01 == pos[2]) && (0x02 == pos[3])); | ||
338 | |||
339 | /* end list */ | ||
340 | |||
341 | /* TODO: should this return an error? indicates corrupt zipfile (or | ||
342 | disk missing in middle of multi-disk)? */ | ||
343 | #if DEBUG_EXTRACT_ZIP | ||
344 | if (entry_count != entry_total) | ||
345 | fprintf (stderr, | ||
346 | "WARNING: Did not find all of the zipfile entries that we should have.\n"); | ||
347 | #endif | ||
348 | |||
349 | ret = proc (proc_cls, | ||
350 | "zip", | ||
351 | EXTRACTOR_METATYPE_MIMETYPE, | ||
352 | EXTRACTOR_METAFORMAT_UTF8, | ||
353 | "text/plain", | ||
354 | "application/zip", | ||
355 | strlen ("application/zip")+1); | ||
356 | if ( (filecomment != NULL) && (ret != 0) ) | ||
357 | { | ||
358 | ret = proc (proc_cls, | ||
359 | "zip", | ||
360 | EXTRACTOR_METATYPE_MIMETYPE, | ||
361 | EXTRACTOR_METAFORMAT_UTF8, | ||
362 | "text/plain", | ||
363 | filecomment, | ||
364 | strlen (filecomment)+1); | ||
365 | } | ||
366 | if (filecomment != NULL) | ||
367 | free (filecomment); | ||
368 | |||
369 | |||
370 | /* if we've gotten to here then there is at least one zip entry (see get_zipinfo call above) */ | ||
371 | /* note: this free()'s the info list as it goes */ | ||
372 | info = start; | ||
373 | while (NULL != info) | ||
374 | { | 90 | { |
375 | if (info->filename != NULL) | 91 | if (EXTRACTOR_UNZIP_OK == |
376 | { | 92 | EXTRACTOR_common_unzip_get_current_file_info (uf, |
377 | if ( (ret == 0) && (strlen (info->filename)) ) | 93 | &fi, |
378 | { | 94 | fname, |
379 | ret = proc (proc_cls, | 95 | sizeof (fname), |
96 | NULL, 0, | ||
97 | fcomment, | ||
98 | sizeof (fcomment))) | ||
99 | { | ||
100 | if ( (0 != strlen (fname)) && | ||
101 | (0 != | ||
102 | ec->proc (ec->cls, | ||
380 | "zip", | 103 | "zip", |
381 | EXTRACTOR_METATYPE_FILENAME, | 104 | EXTRACTOR_METATYPE_FILENAME, |
382 | EXTRACTOR_METAFORMAT_UTF8, | 105 | EXTRACTOR_METAFORMAT_C_STRING, |
383 | "text/plain", | 106 | "text/plain", |
384 | info->filename, | 107 | fname, |
385 | strlen (info->filename)+1); | 108 | strlen (fname) + 1))) |
386 | } | 109 | goto CLEANUP; |
387 | free (info->filename); | 110 | if ( (0 != strlen (fcomment)) && |
388 | } | 111 | (0 != |
389 | if (info->comment != NULL) | 112 | ec->proc (ec->cls, |
390 | { | ||
391 | if ( (ret == 0) && (strlen (info->comment) > 0) ) | ||
392 | { | ||
393 | ret = proc (proc_cls, | ||
394 | "zip", | 113 | "zip", |
395 | EXTRACTOR_METATYPE_FILENAME, | 114 | EXTRACTOR_METATYPE_COMMENT, |
396 | EXTRACTOR_METAFORMAT_UTF8, | 115 | EXTRACTOR_METAFORMAT_C_STRING, |
397 | "text/plain", | 116 | "text/plain", |
398 | info->comment, | 117 | fcomment, |
399 | strlen (info->comment)+1); | 118 | strlen (fcomment) + 1))) |
400 | } | 119 | goto CLEANUP; |
401 | free (info->comment); | 120 | } |
402 | } | ||
403 | tmp = info; | ||
404 | info = info->next; | ||
405 | free (tmp); | ||
406 | } | 121 | } |
407 | return ret; | 122 | while (EXTRACTOR_UNZIP_OK == |
123 | EXTRACTOR_common_unzip_go_to_next_file (uf)); | ||
124 | |||
125 | CLEANUP: | ||
126 | (void) EXTRACTOR_common_unzip_close (uf); | ||
408 | } | 127 | } |
409 | 128 | ||
410 | 129 | /* end of zip_extractor.c */ | |