Mantis - Quercus
Viewing Issue Advanced Details
3767 minor always 11-16-09 16:55 06-21-12 01:14
dobes_vandermeer  
nam  
normal  
closed 4.0.0  
fixed  
none    
none  
0003767: Zip methods process files in an unpredictable order, and don't process all files
The zip methods don't seem to be able to handle this particular zip file, for unknown reasons. An unpredictable number of files are returned; rarely does it return them all. It doesn't seem to be having this issue with ALL zip files, but I haven't tried with many others.
Here's a simple test case that illustrates the problem using the attached zip file:

{{{
<?php
$file = 'fresh-page.1.1.zip'; // Downloaded from http://downloads.wordpress.org/plugin/fresh-page.1.1.zip [^]
$zfd = zip_open($file);
for($count=0;;$count++){
    $zip_entry=zip_read($zfd);
    if($zip_entry === FALSE)
        break;
    $zname=zip_entry_name($zip_entry);
    $zip_fs = zip_entry_filesize($zip_entry);
    $zdir=dirname($zname);
    $zcfs = zip_entry_compressedsize($zip_entry);
    echo "
  • $count $zname from $file with size $zip_fs and compressed size $zcfs
  • \n";
    }

    ?>
    }}}

    The original PHP returns 264 entries (the last line shows:

  • 263 Unzipping fresh-page/RCCWP_CustomField.php from fresh-page.1.1.zip with size 15607 and compressed size 3352


  • In quercus I am seeing only 76 lines, the last of which is:

    75 Unzipping fresh-page/images/zone_grad.gif from fresh-page.1.1.zip with size 148 and compressed size 114

    The next one should have been:

  • 75 Unzipping fresh-page/images/zone_grad.gif from fresh-page.1.1.zip with size 148 and compressed size 114



  •  fresh-page.1.1.zip [^] (655,922 bytes) 11-16-09 16:55

    Notes
    (0004296)
    dobes_vandermeer   
    11-16-09 16:57   
    Note that this is using the version of Quercus included in Resin 4.0.1. I wasn't able to select 4.0.1 as the version, unfortunately.
    (0004298)
    dobes_vandermeer   
    11-16-09 20:56   
    What did work is to access a java class that extracts the files for me.

    Here's the class:

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;

    import org.apache.commons.io.IOUtils;

    /**
     * Extract a ZIP file into some folder.
     */
    public class ZipExtractor {
        public static void extract(String zip, String outputFolder) throws IOException {
            ZipFile zf = new ZipFile(zip);
            File of = new File(outputFolder).getAbsoluteFile();
            Enumeration<? extends ZipEntry> ee = zf.entries();
            while(ee.hasMoreElements()) {
                ZipEntry ze = ee.nextElement();
                String name = ze.getName();
                File outfile = new File(of, name);
                if(ze.isDirectory()) {
                    outfile.mkdirs();
                } else {
                    InputStream in = zf.getInputStream(ze);
                    outfile.getParentFile().mkdirs(); // Make sure the folder exists
                    FileOutputStream out = new FileOutputStream(outfile);
                    IOUtils.copy(in, out);
                }
            }
        }
    }


    Here's the way it can be invoked from PHP code in Quercus:

    function unzip_file($file, $to) {
        $util = java_class('books.util.ZipExtractor');
        $util->extract($file, $to);
        return true;
    }

    So ... if anyone else is looking for a workaround, here you go!
    (0005065)
    doogie   
    02-17-11 10:45   
    At a guess, when looking at that zip file, the zone_grad.gif is the first entry in the file that is actually *expanded* when it was added to the zip. It's compressed size is correctly reported as 114, but the real uncompressed size is supposed to be 63, *not* 148!.

    At a guess, this might be due to an abs() in the code(unlikely), or a signed vs. unsigned int problem(more likely). I haven't actually tried to dig into this codebase at all, just looking at the debug above and the zip file(unzip -lv).

    Also, once quercus thinks the file size is 148(which is too much), it then starts to overflow a buffer or something.
    (0005066)
    doogie   
    02-17-11 11:09   
    ZipModule.zip_entry_filesize returns Value, and uses LongValue.create() internally. ZipMmodule.zip_entry_compressedsize returns long directly. Maybe that is the problem.

    I really think those methods should be consistent.
    (0005916)
    nam   
    06-21-12 01:14   
    php/1v0z

    Fixed for 4.0.29.