2480
2480
/****************************************************************************
2482
*F ExtrArch(<bim>,<out>,<ovr>,<pre>,<arc>,<filec>,<files>) . extract members
2482
*F ExtrArch(<bim>,<out>,<ovr>,<pre>,<frc>,<arc>,<filec>,<files>) . extract members
2484
2484
** 'ExtrArch' extracts the members of the archive with the name <arc> that
2485
2485
** match one of the file name patterns '<files>[0] .. <files>[<filec>-1]'.
2491
2491
** stdout, i.e., to the screen. and if it is 2, the members are extracted.
2492
2492
** If <ovr> is 0, members will not overwrite existing files; otherwise they
2493
2493
** will. <pre> is a prefix that is prepended to all path names.
2494
** <frc> is 1 if the user requested extraction of members even if this would
2495
** result in a directory traversal.
2495
int ExtrArch ( bim, out, ovr, pre, arc, filec, files )
2497
int ExtrArch ( bim, out, ovr, pre, frc, arc, filec, files )
2496
2498
unsigned long bim;
2497
2499
unsigned long out;
2498
2500
unsigned long ovr;
2501
2504
unsigned long filec;
2502
2505
char * files [];
2588
/* check the path for directory traversal */
2590
/* but only if the user did not request otherwise */
2592
/* building the universal path of this member */
2593
char patu [sizeof(Entry.diru) + sizeof(Entry.namu) + 2];
2594
strcpy( patu, Entry.diru );
2595
if ( strlen(patu) && patu[strlen(patu)-1] != '/') strcat( patu, "/" );
2596
strcat( patu, (Entry.lnamu ? Entry.namu : Entry.nams) );
2600
if ( strstr( patu, "/../" )) {
2603
/* remove "/../" from the path */
2604
char tmp [sizeof(patu)];
2607
memset(tmp, 0, sizeof(tmp));
2610
while ( !strncmp(q, "/../", 4) ) {
2613
if (q[0] == '/') q++;
2615
while ((p = strstr( q, "/../" )) != NULL) {
2616
if (q[0] == '/') q++;
2617
if (p > q) strncat(tmp, q, p-q);
2618
if (tmp[strlen(tmp)-1] != '/') strcat(tmp, "/");
2622
strncat(tmp, q+1, patu + strlen(patu) - q);
2625
printf("unzoo: skipped \"/../\" path component(s) in '%s'\n", Entry.patl);
2627
if ( *patu == '/' && !strlen( pre ) ) {
2630
char *p = malloc(sizeof(patu));
2632
memset(p, 0, sizeof(patu));
2634
while ( q[0] == '/' ) q++;
2638
printf("unzoo: skipped root directory path component in '%s'\n", patl);
2640
if ( !strncmp( patu, "../", 3 )) {
2643
char tmp [sizeof(patu)];
2644
memset(tmp, 0, sizeof(tmp));
2645
strcpy(tmp, patu + 3);
2648
printf("unzoo: skipped \"../\" path component in '%s'\n", patl);
2652
/* patu contains the sanitized 'universal' path, i.e. */
2653
/* separated by '/' characters, including the file name. */
2655
char *f = strrchr( patu, '/' );
2657
/* Now, patu points to the directory part, f to the file */
2659
memset( Entry.diru, 0, sizeof(Entry.diru) );
2660
strncpy( Entry.diru, patu, sizeof(Entry.diru)-1 );
2661
if ( Entry.lnamu > 0 ) {
2662
memset( Entry.namu, 0, sizeof(Entry.namu) );
2663
strncpy( Entry.namu, f, sizeof(Entry.namu)-1 );
2665
memset( Entry.nams, 0, sizeof(Entry.nams) );
2666
strncpy( Entry.nams, f, sizeof(Entry.nams)-1 );
2669
/* convert the names to local format */
2670
if ( Entry.system == 0 || Entry.system == 2 ) {
2671
CONV_DIRE( Entry.dirl, Entry.diru );
2672
CONV_NAME( Entry.naml, (Entry.lnamu ? Entry.namu : Entry.nams) );
2675
strcpy( Entry.dirl, Entry.diru );
2676
strcpy( Entry.naml, (Entry.lnamu ? Entry.namu : Entry.nams) );
2678
/* sizeof(patl)=512, sizeof({dirl|naml}=256} */
2679
strcpy( Entry.patl, Entry.dirl );
2680
strcat( Entry.patl, Entry.naml );
2585
2684
/* check that such a file does not already exist */
2586
2685
strcpy( patl, pre ); strcat( patl, Entry.patl );
2587
2686
if ( out == 2 && ovr == 0 && OpenReadFile(patl,0L) ) {
2750
2849
printf(" -p: extract to stdout\n");
2751
2850
printf(" -o: extract over existing files\n");
2752
2851
printf(" -j: extract to '<prefix><membername>'\n");
2852
printf(" -f: force extraction of members to their original locations\n");
2853
printf(" even if this results in files extracted outside the\n");
2854
printf(" working directory. THIS COULD POTENTIALLY OVERWRITE\n");
2855
printf(" IMPORTANT FILES, SO USE WITH CARE!\n");
2753
2856
printf(" <file>: extract only files matching at least one pattern,\n");
2754
2857
printf(" '?' matches any char, '*' matches any string.\n");
2818
2923
res = ListArch( ver, argv[1],
2819
2924
(unsigned long)argc-2, argv+2 );
2820
2925
else if ( cmd == 2 && 1 < argc )
2821
res = ExtrArch( bim, out, ovr, pre, argv[1],
2926
res = ExtrArch( bim, out, ovr, pre, frc, argv[1],
2822
2927
(unsigned long)argc-2, argv+2 );
2824
2929
res = HelpArch();