Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/filestorage/zip_packer.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 
00028 defined('MOODLE_INTERNAL') || die();
00029 
00030 require_once("$CFG->libdir/filestorage/file_packer.php");
00031 require_once("$CFG->libdir/filestorage/zip_archive.php");
00032 
00041 class zip_packer extends file_packer {
00042 
00055     public function archive_to_storage($files, $contextid, $component, $filearea, $itemid, $filepath, $filename, $userid = NULL) {
00056         global $CFG;
00057 
00058         $fs = get_file_storage();
00059 
00060         check_dir_exists($CFG->tempdir.'/zip');
00061         $tmpfile = tempnam($CFG->tempdir.'/zip', 'zipstor');
00062 
00063         if ($result = $this->archive_to_pathname($files, $tmpfile)) {
00064             if ($file = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) {
00065                 if (!$file->delete()) {
00066                     @unlink($tmpfile);
00067                     return false;
00068                 }
00069             }
00070             $file_record = new stdClass();
00071             $file_record->contextid = $contextid;
00072             $file_record->component = $component;
00073             $file_record->filearea  = $filearea;
00074             $file_record->itemid    = $itemid;
00075             $file_record->filepath  = $filepath;
00076             $file_record->filename  = $filename;
00077             $file_record->userid    = $userid;
00078             $file_record->mimetype  = 'application/zip';
00079 
00080             $result = $fs->create_file_from_pathname($file_record, $tmpfile);
00081         }
00082         @unlink($tmpfile);
00083         return $result;
00084     }
00085 
00092     public function archive_to_pathname($files, $archivefile) {
00093         if (!is_array($files)) {
00094             return false;
00095         }
00096 
00097         $ziparch = new zip_archive();
00098         if (!$ziparch->open($archivefile, file_archive::OVERWRITE)) {
00099             return false;
00100         }
00101 
00102         foreach ($files as $archivepath => $file) {
00103             $archivepath = trim($archivepath, '/');
00104 
00105             if (is_null($file)) {
00106                 // empty directories have null as content
00107                 $ziparch->add_directory($archivepath.'/');
00108 
00109             } else if (is_string($file)) {
00110                 $this->archive_pathname($ziparch, $archivepath, $file);
00111 
00112             } else if (is_array($file)) {
00113                 $content = reset($file);
00114                 $ziparch->add_file_from_string($archivepath, $content);
00115 
00116             } else {
00117                 $this->archive_stored($ziparch, $archivepath, $file);
00118             }
00119         }
00120 
00121         return $ziparch->close();
00122     }
00123 
00124     private function archive_stored($ziparch, $archivepath, $file) {
00125         $file->archive_file($ziparch, $archivepath);
00126 
00127         if (!$file->is_directory()) {
00128             return;
00129         }
00130 
00131         $baselength = strlen($file->get_filepath());
00132         $fs = get_file_storage();
00133         $files = $fs->get_directory_files($file->get_contextid(), $file->get_component(), $file->get_filearea(), $file->get_itemid(),
00134                                           $file->get_filepath(), true, true);
00135         foreach ($files as $file) {
00136             $path = $file->get_filepath();
00137             $path = substr($path, $baselength);
00138             $path = $archivepath.'/'.$path;
00139             if (!$file->is_directory()) {
00140                 $path = $path.$file->get_filename();
00141             }
00142             $file->archive_file($ziparch, $path);
00143         }
00144     }
00145 
00146     private function archive_pathname($ziparch, $archivepath, $file) {
00147         if (!file_exists($file)) {
00148             return;
00149         }
00150 
00151         if (is_file($file)) {
00152             if (!is_readable($file)) {
00153                 return;
00154             }
00155             $ziparch->add_file_from_pathname($archivepath, $file);
00156             return;
00157         }
00158         if (is_dir($file)) {
00159             if ($archivepath !== '') {
00160                 $ziparch->add_directory($archivepath);
00161             }
00162             $files = new DirectoryIterator($file);
00163             foreach ($files as $file) {
00164                 if ($file->isDot()) {
00165                     continue;
00166                 }
00167                 $newpath = $archivepath.'/'.$file->getFilename();
00168                 $this->archive_pathname($ziparch, $newpath, $file->getPathname());
00169             }
00170             unset($files); //release file handles
00171             return;
00172         }
00173     }
00174 
00181     public function extract_to_pathname($archivefile, $pathname) {
00182         global $CFG;
00183 
00184         if (!is_string($archivefile)) {
00185             return $archivefile->extract_to_pathname($this, $pathname);
00186         }
00187 
00188         $processed = array();
00189 
00190         $pathname = rtrim($pathname, '/');
00191         if (!is_readable($archivefile)) {
00192             return false;
00193         }
00194        $ziparch = new zip_archive();
00195         if (!$ziparch->open($archivefile, file_archive::OPEN)) {
00196             return false;
00197         }
00198 
00199         foreach ($ziparch as $info) {
00200             $size = $info->size;
00201             $name = $info->pathname;
00202 
00203             if ($name === '' or array_key_exists($name, $processed)) {
00204                 //probably filename collisions caused by filename cleaning/conversion
00205                 continue;
00206             }
00207 
00208             if ($info->is_directory) {
00209                 $newdir = "$pathname/$name";
00210                 // directory
00211                 if (is_file($newdir) and !unlink($newdir)) {
00212                     $processed[$name] = 'Can not create directory, file already exists'; // TODO: localise
00213                     continue;
00214                 }
00215                 if (is_dir($newdir)) {
00216                     //dir already there
00217                     $processed[$name] = true;
00218                 } else {
00219                     if (mkdir($newdir, $CFG->directorypermissions, true)) {
00220                         $processed[$name] = true;
00221                     } else {
00222                         $processed[$name] = 'Can not create directory'; // TODO: localise
00223                     }
00224                 }
00225                 continue;
00226             }
00227 
00228             $parts = explode('/', trim($name, '/'));
00229             $filename = array_pop($parts);
00230             $newdir = rtrim($pathname.'/'.implode('/', $parts), '/');
00231 
00232             if (!is_dir($newdir)) {
00233                 if (!mkdir($newdir, $CFG->directorypermissions, true)) {
00234                     $processed[$name] = 'Can not create directory'; // TODO: localise
00235                     continue;
00236                 }
00237             }
00238 
00239             $newfile = "$newdir/$filename";
00240             if (!$fp = fopen($newfile, 'wb')) {
00241                 $processed[$name] = 'Can not write target file'; // TODO: localise
00242                 continue;
00243             }
00244             if (!$fz = $ziparch->get_stream($info->index)) {
00245                 $processed[$name] = 'Can not read file from zip archive'; // TODO: localise
00246                 fclose($fp);
00247                 continue;
00248             }
00249 
00250             while (!feof($fz)) {
00251                 $content = fread($fz, 262143);
00252                 fwrite($fp, $content);
00253             }
00254             fclose($fz);
00255             fclose($fp);
00256             if (filesize($newfile) !== $size) {
00257                 $processed[$name] = 'Unknown error during zip extraction'; // TODO: localise
00258                 // something went wrong :-(
00259                 @unlink($newfile);
00260                 continue;
00261             }
00262             $processed[$name] = true;
00263         }
00264         $ziparch->close();
00265         return $processed;
00266     }
00267 
00278     public function extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL) {
00279         global $CFG;
00280 
00281         if (!is_string($archivefile)) {
00282             return $archivefile->extract_to_pathname($this, $contextid, $component, $filearea, $itemid, $pathbase, $userid);
00283         }
00284 
00285         check_dir_exists($CFG->tempdir.'/zip');
00286 
00287         $pathbase = trim($pathbase, '/');
00288         $pathbase = ($pathbase === '') ? '/' : '/'.$pathbase.'/';
00289         $fs = get_file_storage();
00290 
00291         $processed = array();
00292 
00293         $ziparch = new zip_archive();
00294         if (!$ziparch->open($archivefile, file_archive::OPEN)) {
00295             return false;
00296         }
00297 
00298         foreach ($ziparch as $info) {
00299             $size = $info->size;
00300             $name = $info->pathname;
00301 
00302             if ($name === '' or array_key_exists($name, $processed)) {
00303                 //probably filename collisions caused by filename cleaning/conversion
00304                 continue;
00305             }
00306 
00307             if ($info->is_directory) {
00308                 $newfilepath = $pathbase.$name.'/';
00309                 $fs->create_directory($contextid, $component, $filearea, $itemid, $newfilepath, $userid);
00310                 $processed[$name] = true;
00311                 continue;
00312             }
00313 
00314             $parts = explode('/', trim($name, '/'));
00315             $filename = array_pop($parts);
00316             $filepath = $pathbase;
00317             if ($parts) {
00318                 $filepath .= implode('/', $parts).'/';
00319             }
00320 
00321             if ($size < 2097151) {
00322                 // small file
00323                 if (!$fz = $ziparch->get_stream($info->index)) {
00324                     $processed[$name] = 'Can not read file from zip archive'; // TODO: localise
00325                     continue;
00326                 }
00327                 $content = '';
00328                 while (!feof($fz)) {
00329                     $content .= fread($fz, 262143);
00330                 }
00331                 fclose($fz);
00332                 if (strlen($content) !== $size) {
00333                     $processed[$name] = 'Unknown error during zip extraction'; // TODO: localise
00334                     // something went wrong :-(
00335                     unset($content);
00336                     continue;
00337                 }
00338 
00339                 if ($file = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) {
00340                     if (!$file->delete()) {
00341                         $processed[$name] = 'Can not delete existing file'; // TODO: localise
00342                         continue;
00343                     }
00344                 }
00345                 $file_record = new stdClass();
00346                 $file_record->contextid = $contextid;
00347                 $file_record->component = $component;
00348                 $file_record->filearea  = $filearea;
00349                 $file_record->itemid    = $itemid;
00350                 $file_record->filepath  = $filepath;
00351                 $file_record->filename  = $filename;
00352                 $file_record->userid    = $userid;
00353                 if ($fs->create_file_from_string($file_record, $content)) {
00354                     $processed[$name] = true;
00355                 } else {
00356                     $processed[$name] = 'Unknown error during zip extraction'; // TODO: localise
00357                 }
00358                 unset($content);
00359                 continue;
00360 
00361             } else {
00362                 // large file, would not fit into memory :-(
00363                 $tmpfile = tempnam($CFG->tempdir.'/zip', 'unzip');
00364                 if (!$fp = fopen($tmpfile, 'wb')) {
00365                     @unlink($tmpfile);
00366                     $processed[$name] = 'Can not write temp file'; // TODO: localise
00367                     continue;
00368                 }
00369                 if (!$fz = $ziparch->get_stream($info->index)) {
00370                     @unlink($tmpfile);
00371                     $processed[$name] = 'Can not read file from zip archive'; // TODO: localise
00372                     continue;
00373                 }
00374                 while (!feof($fz)) {
00375                     $content = fread($fz, 262143);
00376                     fwrite($fp, $content);
00377                 }
00378                 fclose($fz);
00379                 fclose($fp);
00380                 if (filesize($tmpfile) !== $size) {
00381                     $processed[$name] = 'Unknown error during zip extraction'; // TODO: localise
00382                     // something went wrong :-(
00383                     @unlink($tmpfile);
00384                     continue;
00385                 }
00386 
00387                 if ($file = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) {
00388                     if (!$file->delete()) {
00389                         @unlink($tmpfile);
00390                         $processed[$name] = 'Can not delete existing file'; // TODO: localise
00391                         continue;
00392                     }
00393                 }
00394                 $file_record = new stdClass();
00395                 $file_record->contextid = $contextid;
00396                 $file_record->component = $component;
00397                 $file_record->filearea  = $filearea;
00398                 $file_record->itemid    = $itemid;
00399                 $file_record->filepath  = $filepath;
00400                 $file_record->filename  = $filename;
00401                 $file_record->userid    = $userid;
00402                 if ($fs->create_file_from_pathname($file_record, $tmpfile)) {
00403                     $processed[$name] = true;
00404                 } else {
00405                     $processed[$name] = 'Unknown error during zip extraction'; // TODO: localise
00406                 }
00407                 @unlink($tmpfile);
00408                 continue;
00409             }
00410         }
00411         $ziparch->close();
00412         return $processed;
00413     }
00414 
00419     public function list_files($archivefile) {
00420         if (!is_string($archivefile)) {
00421             return $archivefile->list_files();
00422         }
00423 
00424         $ziparch = new zip_archive();
00425         if (!$ziparch->open($archivefile, file_archive::OPEN)) {
00426             return false;
00427         }
00428         $list = $ziparch->list_files();
00429         $ziparch->close();
00430         return $list;
00431     }
00432 
00433 }
 All Data Structures Namespaces Files Functions Variables Enumerations