remove old readme
[atutor.git] / docs / include / classes / zipfile.class.php
1 <?php
2 /***********************************************************************/
3 /* ATutor                                                                                                                          */
4 /***********************************************************************/
5 /* Copyright (c) 2002-2010                                             */
6 /* Inclusive Design Institute                                          */
7 /* http://atutor.ca                                                                                                        */
8 /*                                                                                                                                         */
9 /* This program is free software. You can redistribute it and/or           */
10 /* modify it under the terms of the GNU General Public License             */
11 /* as published by the Free Software Foundation.                                           */
12 /***********************************************************************/
13 // $Id$
14
15 define('PCLZIP_TEMPORARY_DIR', AT_CONTENT_DIR.'export'.DIRECTORY_SEPARATOR);  //constant for the temp folder.
16 include(AT_INCLUDE_PATH.'classes/pclzip.lib.php');       //loads the pclzip library.
17 include_once(AT_INCLUDE_PATH.'../mods/_core/file_manager/filemanager.inc.php'); //copy/delete folder
18
19 /**
20 * Class for creating and accessing an archive zip file.  Originally written by Joel Kronenberg,
21 * edited by Harris Wong to use the PCLZIP library (http://www.phpconcept.net)
22 *
23 * As of ATutor 2.0, this file will extend the pclzip library functions instead of using Joel's.  
24 * The function preconditions and postconditions will remain the same however. 
25 *
26 * @access       public
27 * @link         http://www.pkware.com/documents/casestudies/APPNOTE.TXT for the specs
28 * @author       Joel Kronenberg
29 */
30 class zipfile {
31
32         /**
33          * string $zipfile_dir - the actual system directory that stores the temporary files for archiving.
34          * @access      private
35          */
36         var $zipfile_dir;
37
38         /**
39         * boolean $is_closed - flag set to true if file is closed, false if still open
40         * @access  private
41         */
42         var $is_closed; 
43
44         /** 
45          * string $filename -   randomized filename of this zip instance.  It also shares the same name
46          *                                              as the folder under the export/ folder.  
47          */
48         var $filename; 
49
50
51         /**
52         * Constructor method.  Initialises variables.
53         * @access       public
54         * @author       Joel Kronenberg
55         */
56         function zipfile() {
57                 //create the temp folder for export if it hasn't been created.
58                 if (!is_dir(PCLZIP_TEMPORARY_DIR)){
59                         mkdir(PCLZIP_TEMPORARY_DIR);
60                         copy(PCLZIP_TEMPORARY_DIR.'../index.html', PCLZIP_TEMPORARY_DIR.'index.html');
61                 }
62
63                 //generate a random hash 
64                 $this->filename = substr(md5(rand()), 0, 5);
65
66                 //create a temporary folder for this zip instance
67                 $this->zipfile_dir = PCLZIP_TEMPORARY_DIR.$this->filename.DIRECTORY_SEPARATOR;
68                 mkdir($this->zipfile_dir);
69                 $this->is_closed = false;
70         }
71
72
73         /**
74         * Public interface for adding a dir and its contents recursively to zip file
75         * @access  public
76         * @param   string $dir                          the real system directory that contains the files to add to the zip              
77         * @param   string $zip_prefix_dir       the zip dir where the contents of $dir will be put in
78         * @param   string $pre_pend_dir         used during the recursion to keep track of the path, default=''
79         * @see     $_base_path                          in include/vitals.inc.php
80         * @see     priv_add_dir()                       in include/classes/zipfile.class.php
81         * @see     add_file()                           in include/classes/zipfile.class.php
82         * @author  Joel Kronenberg
83         */
84         function add_dir($dir, $zip_prefix_dir, $pre_pend_dir='') {
85                 if (!($dh = @opendir($dir.$pre_pend_dir))) {
86                         echo 'cant open dir: '.$dir.$pre_pend_dir;
87                         exit;           
88                 }
89                 //copy folder recursively into the temp folder.
90                 copys($dir, $this->zipfile_dir.DIRECTORY_SEPARATOR.$zip_prefix_dir);
91         }
92
93         /**
94         * Adding a dir to the archive 
95         * @access  private
96         * @param   string $name                         directory name
97         * @param   string $timestamp            time, default=''
98         * @author  Joel Kronenberg
99         */
100     function priv_add_dir($name, $timestamp = '') {   
101                 //deprecated as of ATutor 2.0
102     } 
103         
104         /**
105         * Public interface to create a directory in the archive.
106         * @access  public
107         * @param   string $name                         directory name
108         * @param   string $timestamp            time of creation, default=''
109         * @see     $_base_path                          in include/vitals.inc.php
110         * @see     priv_add_dir()                       in include/zipfile.class.php
111         * @author  Joel Kronenberg
112         */
113         function create_dir($name, $timestamp='') {
114                 $name = trim($name);
115                 //don't create a folder if it is itself
116                 if ($name=='' || $name=='.'){
117                         return;
118                 }
119
120                 $parent_folder = dirname($name);
121                 if (!is_dir($this->zipfile_dir.$name) && ($parent_folder=='.' || $parent_folder=='')){
122                         //base case
123                         mkdir($this->zipfile_dir.$name);
124                         return;
125                 } else {
126                         //recursion step
127                         $this->create_dir(dirname($name));
128                 }
129
130                 //returned stack. continue from where it left off.              
131                 if (!is_dir($this->zipfile_dir.$name)){
132                         //the parent folder should be created at this point, create itself
133                         mkdir($this->zipfile_dir.$name);
134                 }
135         }
136
137
138         /**
139         * Adds a file to the archive.
140         * @access  public
141         * @param   string $file_data            file contents
142         * @param   string $name                         name of file in archive (add path if your want)
143         * @param   string $timestamp            time of creation, default=''
144         * @see     $_base_path                          in include/vitals.inc.php
145         * @see     priv_add_dir()                       in include/zipfile.class.php
146         * @author  Joel Kronenberg
147         */
148     function add_file($file_data, $name, $timestamp = '') {
149         $name = str_replace("\\", "/", $name);
150
151                 //check if folder exists, if not, create it.
152                 if (!is_dir($this->zipfile_dir.dirname($name))){
153                         $this->create_dir(dirname($name));
154                 }
155
156                 //write to file
157                 $fp = fopen($this->zipfile_dir.$name, 'w');
158                 fwrite($fp, $file_data);
159                 fclose($fp);            
160     } 
161
162         /**
163         * Closes archive, sets $is_closed to true
164         * @access  public
165         * @param   none
166         * @author  Joel Kronenberg
167         */
168         function close() {
169                 //use pclzip to compress the file, and save it in the temp folder.
170                 $archive = new PclZip($this->zipfile_dir.$this->filename.'.zip');
171                 $v_list = $archive->create($this->zipfile_dir, 
172                                                         PCLZIP_OPT_REMOVE_PATH, $this->zipfile_dir);
173
174                 //error info
175                 if ($v_list == 0) {
176                 die ("Error: " . $archive->errorInfo(true));
177                 }
178                 
179                 $this->is_closed = true;
180         }
181
182     /**
183         * Gets size of new archive
184         * Only call this after calling close() - will return false if the zip wasn't close()d yet
185         * @access  public
186         * @return  int  size of file in byte.
187         * @author  Joel Kronenberg
188         */
189         function get_size() {
190                 if (!$this->is_closed) {
191                         return false;
192                 }
193
194                 //file path
195                 $filepath = $this->zipfile_dir.$this->filename.'.zip';
196                 if (file_exists($filepath)){
197                         return filesize($filepath);
198                 } 
199
200                 return false;
201         }
202
203
204     /**
205         * Returns binary file
206         * @access       public
207         * @see          get_size()              in include/classes/zipfile.class.php
208         * @author  Joel Kronenberg
209         */      
210         function get_file() {
211                 if (!$this->is_closed) {
212                         $this->close();
213                 }
214                 return file_get_contents($this->zipfile_dir.$this->filename.'.zip');
215     }
216
217         /**
218         * Writes the file to disk.
219         * Similar to get_file(), but instead of returning the file, it saves it to disk.
220         * @access  public
221         * @author  Joel Kronenberg
222         * @param  $file The full path and file name of the destination file.
223         */
224         function write_file($file) {
225                 if (!$this->is_closed) {
226                         $this->close();
227                 }               
228                 copy($this->zipfile_dir.$this->filename.'.zip', $file);
229         }
230
231
232     /**
233         * Outputs the file - sends headers to browser to force download
234         * Only call this after calling close() - will return false if the zip wasn't close()d yet
235         * @access       public
236         * @see          get_size()              in include/classes/zipfile.class.php
237         * @author  Joel Kronenberg
238         */
239         function send_file($file_name) {
240                 if (!$this->is_closed) {
241                         $this->close();
242                 }
243                 $file_name = str_replace(array('"', '<', '>', '|', '?', '*', ':', '/', '\\'), '', $file_name);
244                 
245                 header("Content-type: archive/zip");
246                 header("Content-disposition: attachment; filename=$file_name.zip");
247                 
248                 readfile_in_chunks($this->zipfile_dir.$this->filename.'.zip');
249                 exit;
250         }
251
252         /**
253          * Destructor - removes temporary folder and its content.
254          * Should self-destruct automatically for PHP 5.0+; otherwise developers should call this function
255          * to clean up.
256          * @access      public
257          * @author      Harris Wong
258          */
259         function __destruct(){
260                 clr_dir($this->zipfile_dir);
261         }
262 }
263
264 ?>