Jay Blanchard wrote:
I am in need of a PHP class or script or something that will allow me to

like Richard mentioned - exec out to the shell and zip there....

I wrote a little/simple class when I was bored, here you go, HIH -
(sorry about the linewrapping)

I use the class in backoffice setting and it is actually used to
zip up PDF files, which is does just fine. (using zip on a RHES box)

<?php
/**
 * Zipper.class.php :: wrapper for the system command 'zip'
 *
 * @author      Jochem Maas <[EMAIL PROTECTED]>
 * @version     0.1
 * @copyright   Copyright 2003-2004 iamjochem
 *
 * $Header: include/class/core/Zipper.class.php,v 1.2 2005/04/12 11:36:21 
jochem Exp $
 */

abstract class Zipper
{
    const ARC_RECURSE   = 0x1; // zip will recurse the from directory for files 
to include
    const ARC_APPEND    = 0x2; // zip will append to the given archive (if it 
exists), rather than overwrite
    const ARC_MOVE      = 0x4; // zip will delete the archived files upon 
success
const ARC_TEST = 0x8; // the generated cmdline will be returned as the first item of the output array instead of being called - useful for checking what will happen (before you do it!)

    /*
     * WARNING: $pattern is the UNESCAPED file pattern  to archive (defaults to 
'./*')
     * DO NOT ALLOW USER INPUT IN HERE WITHOUT SANITATION (e.g. 
escapeshellargs() - bare in mind that
     * strings which are quoted in the strings will not have globbing 
performed, I say this
     * because that is exactly the result of performing escapeshellargs())
     *
     * e.g. "'./*.xml'" instead of "./*.xml"
     */
static public function archiveData($fromdir, $todir, $filename, $pattern = '', $flags = self::ARC_RECURSE, &$output = null)
    {
        static $msgs;

        $fromdir    = realpath($fromdir);
        $todir      = realpath($todir);

        if (!is_dir($todir)) {
            $output = array('"to" dir - directory not found');
            return 19;
        }

        if (!is_dir($fromdir)) {
            $output = array('"from" dir - directory not found');
            return 19;
        }

        if (!self::checkforZIP()) {
            $output = array('zip - command not found');
            return -1;
        }

        /* could be localized via the Lang class */
        if (!isset($msgs)) {
            $msgs[  0 ] = 'normal; no errors or warnings detected.';
            $msgs[  2 ] = 'unexpected end of zip file.';
$msgs[ 3 ] = 'a generic error in the zipfile format was detected. Processing may have completed successfully anyway; some broken zipfiles created by other archivers have simple work-arounds.';
            $msgs[  4 ] = 'zip was unable to allocate memory for one or more 
buffers during program initialization.';
            $msgs[  5 ] = 'a severe error in the zipfile format was detected.  
Processing probably failed immediately.';
            $msgs[  6 ] = 'entry too large to be split with zipsplit';
            $msgs[  7 ] = 'invalid comment format';
            $msgs[  8 ] = 'zip -T failed or out of memory';
            $msgs[  9 ] = 'the user aborted zip prematurely with control-C (or 
similar)';
            $msgs[ 10 ] = 'zip encountered an error while using a temp file';
            $msgs[ 11 ] = 'read or seek error';
            $msgs[ 12 ] = 'zip has nothing to do';
            $msgs[ 13 ] = 'missing or empty zip file';
            $msgs[ 14 ] = 'error writing to a file';
            $msgs[ 15 ] = 'zip was unable to create a file to write to';
            $msgs[ 16 ] = 'bad command line parameters';
            $msgs[ 18 ] = 'zip could not open a specified file to read';
        }

        /* check pattern - the pattern is meant to be expanded by the shell 
(not by the zip binary) */
        if (!($pattern = trim($pattern)) || $pattern == '.*') {
            $pattern = './*'; /* everything */
        }
        //$pattern = escapeshellarg($pattern);

        /* check flags */
        $flagStr = array();
        foreach(array(
                    self::ARC_RECURSE   => '-r',
                    self::ARC_APPEND    => '-u',
                    self::ARC_MOVE      => '-m',
                ) as $cnst => $flag)
        {
            if ($flags & $cnst) {
                $flagStr[] = $flag;
            }
        }
        $flagStr = count($flagStr) ? join(' ',$flagStr): '';

        $retval  = null;
        $cmd     = "cd {$fromdir}; zip -v -T {$flagStr} {$todir}/{$filename}.zip 
{$pattern}";

        if ($flags & self::ARC_TEST) {
            $output[] = $cmd;
        } else {
            @exec($cmd, $output, $retval);

            if ($retval > 0) {
                $output[] = '';
                if (isset($msgs[ $retval ])) {
                    $output[] = $msgs[ $retval ];
                } else {
                    $output[] = "\nunknown error [cmd: $cmd] (return: $retval)";
                }
            } else {
                $output[] = "\nfiles archived successfully to zip file (return: 
$retval)";
            }
        }

        return $retval;
    }

    /* checks for the zip executable (assumes its on the path)
     * the assumption is also made that the possible 'command not found' message
     * is output in english!
     */
    static private function checkforZIP()
    {
        static $check;

        $check = true;

        if (is_null($check)) {
            $output = $retval = null;
            @exec('zip -v', $output, $retval);

            if (!array($output) || !count($output)) {
                $check = false;
            } else {
                $check = stristr($output[ 0 ], 'command not found');
            }
        }

        return $check;
    }
}

designate a group of files to be zipped up, including PDF files,
automagically. It must be compatible with WinZip as that is what the
user will have access to. I have tried several things, a couple of
classes, and some other tricks to no avail. There seems to be an issue
with PDF's that I cannot figure out. The files are usually 1 byte too
short when you try to open them after unzipping them, and are therefore
corrupt.

If anyone is aware of something would you please let me know? I am even
willing at this point to add a couple of layers of abstraction to make
this work as long as the process is relatively invisible to the end
user. My desire is that it works like this;

User clicks link
[start automagic stuff]
*whirring* //determine which files should go into archive
*clicking* //put files in archive
[/end automagic stuff]
User presented with dialog box to save archive

Any and all clues are appreciated.


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to