2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2010 */
6 /* Inclusive Design Institute */
8 /* This program is free software. You can redistribute it and/or */
9 /* modify it under the terms of the GNU General Public License */
10 /* as published by the Free Software Foundation. */
11 /************************************************************************/
13 define('PCLZIP_TEMPORARY_DIR', TR_CONTENT_DIR.'export'.DIRECTORY_SEPARATOR); //constant for the temp folder.
14 include_once(TR_INCLUDE_PATH.'lib/pclzip.lib.php'); //loads the pclzip library.
15 include_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); //copy/delete folder
18 * Class for creating and accessing an archive zip file. Originally written by Joel Kronenberg,
19 * edited by Harris Wong to use the PCLZIP library (http://www.phpconcept.net)
21 * As of ATutor 2.0, this file will extend the pclzip library functions instead of using Joel's.
22 * The function preconditions and postconditions will remain the same however.
25 * @link http://www.pkware.com/documents/casestudies/APPNOTE.TXT for the specs
26 * @author Joel Kronenberg
31 * string $zipfile_dir - the actual system directory that stores the temporary files for archiving.
37 * boolean $is_closed - flag set to true if file is closed, false if still open
43 * string $filename - randomized filename of this zip instance. It also shares the same name
44 * as the folder under the export/ folder.
50 * Constructor method. Initialises variables.
52 * @author Joel Kronenberg
55 //create the temp folder for export if it hasn't been created.
56 if (!is_dir(PCLZIP_TEMPORARY_DIR)){
57 mkdir(PCLZIP_TEMPORARY_DIR);
58 copy(PCLZIP_TEMPORARY_DIR.'../index.html', PCLZIP_TEMPORARY_DIR.'index.html');
61 //generate a random hash
62 $this->filename = substr(md5(rand()), 0, 5);
64 //create a temporary folder for this zip instance
65 $this->zipfile_dir = PCLZIP_TEMPORARY_DIR.$this->filename.DIRECTORY_SEPARATOR;
66 mkdir($this->zipfile_dir);
67 $this->is_closed = false;
72 * Public interface for adding a dir and its contents recursively to zip file
74 * @param string $dir the real system directory that contains the files to add to the zip
75 * @param string $zip_prefix_dir the zip dir where the contents of $dir will be put in
76 * @param string $pre_pend_dir used during the recursion to keep track of the path, default=''
77 * @see $_base_path in include/vitals.inc.php
78 * @see priv_add_dir() in include/classes/zipfile.class.php
79 * @see add_file() in include/classes/zipfile.class.php
80 * @author Joel Kronenberg
82 function add_dir($dir, $zip_prefix_dir, $pre_pend_dir='') {
83 if (!($dh = @opendir($dir.$pre_pend_dir))) {
84 echo 'cant open dir: '.$dir.$pre_pend_dir;
87 //copy folder recursively into the temp folder.
88 FileUtility::copys($dir, $this->zipfile_dir.DIRECTORY_SEPARATOR.$zip_prefix_dir);
92 * Adding a dir to the archive
94 * @param string $name directory name
95 * @param string $timestamp time, default=''
96 * @author Joel Kronenberg
98 function priv_add_dir($name, $timestamp = '') {
99 //deprecated as of ATutor 2.0
103 * Public interface to create a directory in the archive.
105 * @param string $name directory name
106 * @param string $timestamp time of creation, default=''
107 * @see $_base_path in include/vitals.inc.php
108 * @see priv_add_dir() in include/zipfile.class.php
109 * @author Joel Kronenberg
111 function create_dir($name, $timestamp='') {
113 //don't create a folder if it is itself
114 if ($name=='' || $name=='.'){
118 $parent_folder = dirname($name);
119 if (!is_dir($this->zipfile_dir.$name) && ($parent_folder=='.' || $parent_folder=='')){
121 mkdir($this->zipfile_dir.$name);
125 $this->create_dir(dirname($name));
128 //returned stack. continue from where it left off.
129 if (!is_dir($this->zipfile_dir.$name)){
130 //the parent folder should be created at this point, create itself
131 mkdir($this->zipfile_dir.$name);
137 * Adds a file to the archive.
139 * @param string $file_data file contents
140 * @param string $name name of file in archive (add path if your want)
141 * @param string $timestamp time of creation, default=''
142 * @see $_base_path in include/vitals.inc.php
143 * @see priv_add_dir() in include/zipfile.class.php
144 * @author Joel Kronenberg
146 function add_file($file_data, $name, $timestamp = '') {
147 $name = str_replace("\\", "/", $name);
149 //check if folder exists, if not, create it.
150 if (!is_dir($this->zipfile_dir.dirname($name))){
151 $this->create_dir(dirname($name));
155 $fp = fopen($this->zipfile_dir.$name, 'w');
156 fwrite($fp, $file_data);
161 * Closes archive, sets $is_closed to true
164 * @author Joel Kronenberg
167 //use pclzip to compress the file, and save it in the temp folder.
168 $archive = new PclZip($this->zipfile_dir.$this->filename.'.zip');
169 $v_list = $archive->create($this->zipfile_dir,
170 PCLZIP_OPT_REMOVE_PATH, $this->zipfile_dir);
174 die ("Error: " . $archive->errorInfo(true));
177 $this->is_closed = true;
181 * Gets size of new archive
182 * Only call this after calling close() - will return false if the zip wasn't close()d yet
184 * @return int size of file in byte.
185 * @author Joel Kronenberg
187 function get_size() {
188 if (!$this->is_closed) {
193 $filepath = $this->zipfile_dir.$this->filename.'.zip';
194 if (file_exists($filepath)){
195 return filesize($filepath);
203 * Returns binary file
205 * @see get_size() in include/classes/zipfile.class.php
206 * @author Joel Kronenberg
208 function get_file() {
209 if (!$this->is_closed) {
212 return file_get_contents($this->zipfile_dir.$this->filename.'.zip');
216 * Writes the file to disk.
217 * Similar to get_file(), but instead of returning the file, it saves it to disk.
219 * @author Joel Kronenberg
220 * @param $file The full path and file name of the destination file.
222 function write_file($file) {
223 if (!$this->is_closed) {
226 copy($this->zipfile_dir.$this->filename.'.zip', $file);
231 * Outputs the file - sends headers to browser to force download
232 * Only call this after calling close() - will return false if the zip wasn't close()d yet
234 * @see get_size() in include/classes/zipfile.class.php
235 * @author Joel Kronenberg
237 function send_file($file_name) {
238 if (!$this->is_closed) {
241 $file_name = str_replace(array('"', '<', '>', '|', '?', '*', ':', '/', '\\'), '', $file_name);
243 header("Content-type: archive/zip");
244 header("Content-disposition: attachment; filename=$file_name.zip");
245 FileUtility::readfile_in_chunks($this->zipfile_dir.$this->filename.'.zip');
250 * Destructor - removes temporary folder and its content.
251 * Should self-destruct automatically for PHP 5.0+; otherwise developers should call this function
254 * @author Harris Wong
256 function __destruct(){
257 FileUtility::clr_dir($this->zipfile_dir);