Changeset 3894
- Timestamp:
- 03/23/11 15:15:28 (12 years ago)
- Location:
- branches/2.2/filemanager/inc
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2/filemanager/inc/jupload.php
r3386 r3894 1 1 <?php 2 3 2 4 3 /** … … 53 52 * 54 53 */ 55 56 54 class JUpload { 57 55 58 var $appletparams; 59 var $classparams; 60 var $files; 61 62 public function JUpload($appletparams = array(), $classparams = array()) { 63 if (gettype($classparams) != 'array') 64 $this->abort('Invalid type of parameter classparams: Expecting an array'); 65 if (gettype($appletparams) != 'array') 66 $this->abort('Invalid type of parameter appletparams: Expecting an array'); 67 68 // set some defaults for the applet params 69 if (!isset($appletparams['afterUploadURL'])) 70 $appletparams['afterUploadURL'] = $_SERVER['PHP_SELF'] . '?afterupload=1'; 71 if (!isset($appletparams['name'])) 72 $appletparams['name'] = 'JUpload'; 73 if (!isset($appletparams['archive'])) 74 $appletparams['archive'] = 'wjhk.jupload.jar'; 75 if (!isset($appletparams['code'])) 76 $appletparams['code'] = 'wjhk.jupload2.JUploadApplet'; 77 if (!isset($appletparams['debugLevel'])) 78 $appletparams['debugLevel'] = 0; 79 if (!isset($appletparams['httpUploadParameterType'])) 80 $appletparams['httpUploadParameterType'] = 'array'; 81 if (!isset($appletparams['showLogWindow'])) 82 $appletparams['showLogWindow'] = ($appletparams['debugLevel'] > 0) ? 'true' : 'false'; 83 if (!isset($appletparams['width'])) 84 $appletparams['width'] = 500; 85 if (!isset($appletparams['height'])) 86 $appletparams['height'] = ($appletparams['showLogWindow'] == 'true') ? 500 : 300; 87 if (!isset($appletparams['mayscript'])) 88 $appletparams['mayscript'] = 'true'; 89 if (!isset($appletparams['scriptable'])) 90 $appletparams['scriptable'] = 'false'; 91 //if (!isset($appletparams['stringUploadSuccess'])) 92 $appletparams['stringUploadSuccess'] = 'SUCCESS'; 93 //if (!isset($appletparams['stringUploadError'])) 94 $appletparams['stringUploadError'] = 'ERROR: (.*)'; 95 $maxpost = $this->tobytes(ini_get('post_max_size')); 96 $maxmem = $this->tobytes(ini_get('memory_limit')); 97 $maxfs = $this->tobytes(ini_get('upload_max_filesize')); 98 $obd = ini_get('open_basedir'); 99 if (!isset($appletparams['maxChunkSize'])) { 100 $maxchunk = ($maxpost < $maxmem) ? $maxpost : $maxmem; 101 $maxchunk = ($maxchunk < $maxfs) ? $maxchunk : $maxfs; 102 $maxchunk /= 4; 103 $optchunk = (500000 > $maxchunk) ? $maxchunk : 500000; 104 $appletparams['maxChunkSize'] = $optchunk; 105 } 106 $appletparams['maxChunkSize'] = $this->tobytes($appletparams['maxChunkSize']); 107 if (!isset($appletparams['maxFileSize'])) 108 $appletparams['maxFileSize'] = $maxfs; 109 $appletparams['maxFileSize'] = $this->tobytes($appletparams['maxFileSize']); 110 if (isset($classparams['errormail'])) { 111 $appletparams['urlToSendErrorTo'] = $_SERVER["PHP_SELF"] . '?errormail'; 112 } 113 114 // Same for class parameters 115 if (!isset($classparams['demo_mode'])) 116 $classparams['demo_mode'] = false; 117 if ($classparams['demo_mode']) { 118 $classparams['create_destdir'] = false; 119 $classparams['allow_subdirs'] = true; 120 $classparams['allow_zerosized'] = true; 121 $classparams['duplicate'] = 'overwrite'; 122 } 123 if (!isset($classparams['debug_php'])) // set true to log some messages in PHP log 124 $classparams['debug_php'] = false; 125 if (!isset($this->classparams['allowed_mime_types'])) // array of allowed MIME type 126 $classparams['allowed_mime_types'] = 'all'; 127 if (!isset($this->classparams['allowed_file_extensions'])) // array of allowed file extensions 128 $classparams['allowed_file_extensions'] = 'all'; 129 if (!isset($classparams['verbose_errors'])) // shouldn't display server info on a production site! 130 $classparams['verbose_errors'] = true; 131 if (!isset($classparams['session_regenerate'])) 132 $classparams['session_regenerate'] = false; 133 if (!isset($classparams['create_destdir'])) 134 $classparams['create_destdir'] = true; 135 if (!isset($classparams['allow_subdirs'])) 136 $classparams['allow_subdirs'] = false; 137 if (!isset($classparams['spaces_in_subdirs'])) 138 $classparams['spaces_in_subdirs'] = false; 139 if (!isset($classparams['allow_zerosized'])) 140 $classparams['allow_zerosized'] = false; 141 if (!isset($classparams['duplicate'])) 142 $classparams['duplicate'] = 'rename'; 143 if (!isset($classparams['dirperm'])) 144 $classparams['dirperm'] = 0755; 145 if (!isset($classparams['fileperm'])) 146 $classparams['fileperm'] = 0644; 147 if (!isset($classparams['destdir'])) { 148 if ($obd != '') 149 $classparams['destdir'] = $obd; 150 else 151 $classparams['destdir'] = '/var/tmp/jupload_test'; 152 } 153 if ($classparams['create_destdir']) 154 @mkdir($classparams['destdir'], $classparams['dirperm']); 155 if (!is_dir($classparams['destdir']) && is_writable($classparams['destdir'])) 156 $this->abort('Destination dir not accessible'); 157 if (!isset($classparams['tmp_prefix'])) 158 $classparams['tmp_prefix'] = 'jutmp.'; 159 if (!isset($classparams['var_prefix'])) 160 $classparams['var_prefix'] = 'juvar.'; 161 if (!isset($classparams['jscript_wrapper'])) 162 $classparams['jscript_wrapper'] = 'JUploadSetProperty'; 163 if (!isset($classparams['tag_jscript'])) 164 $classparams['tag_jscript'] = '<!--JUPLOAD_JSCRIPT-->'; 165 if (!isset($classparams['tag_applet'])) 166 $classparams['tag_applet'] = '<!--JUPLOAD_APPLET-->'; 167 if (!isset($classparams['tag_flist'])) 168 $classparams['tag_flist'] = '<!--JUPLOAD_FILES-->'; 169 if (!isset($classparams['http_flist_start'])) 170 $classparams['http_flist_start'] = 171 "<table border='1'><TR><TH>Filename</TH><TH>file size</TH><TH>Relative path</TH><TH>Full name</TH><TH>md5sum</TH><TH>Specific parameters</TH></TR>"; 172 if (!isset($classparams['http_flist_end'])) 173 $classparams['http_flist_end'] = "</table>\n"; 174 if (!isset($classparams['http_flist_file_before'])) 175 $classparams['http_flist_file_before'] = "<tr><td>"; 176 if (!isset($classparams['http_flist_file_between'])) 177 $classparams['http_flist_file_between'] = "</td><td>"; 178 if (!isset($classparams['http_flist_file_after'])) 179 $classparams['http_flist_file_after'] = "</td></tr>\n"; 180 181 $this->appletparams = $appletparams; 182 $this->classparams = $classparams; 183 $this->page_start(); 184 } 185 186 /** 187 * Log a message on the current output, as a HTML comment. 188 */ 189 protected function logDebug($function, $msg, $htmlComment=true) { 190 $output = "[DEBUG] [$function] $msg"; 191 if ($htmlComment) { 192 echo("<!-- $output -->\r\n"); 193 } else { 194 echo("$output\r\n"); 195 } 196 } 197 198 /** 199 * Log a message to the PHP log. 200 * Declared "protected" so it may be Extended if you require customised logging (e.g. particular log file location). 201 */ 202 protected function logPHPDebug($function, $msg) { 203 if ($this->classparams['debug_php'] === true) { 204 $output = "[DEBUG] [$function] ".$this->arrayexpand($msg); 205 error_log($output); 206 } 207 } 208 209 private function arrayexpand($array) { 210 $output = ''; 211 if (is_array($array)) { 212 foreach ($array as $key => $value) { 213 $output .= "\n ".$key.' => '.$this->arrayexpand($value); 214 } 215 } else { 216 $output .= $array; 217 } 218 return $output; 219 } 220 221 222 /** 223 * Convert a value ending in 'G','M' or 'K' to bytes 224 * 225 */ 226 private function tobytes($val) { 227 $val = trim($val); 228 $last = strtolower($val{strlen($val)-1}); 229 switch($last) { 230 case 'g': 231 $val *= 1024; 232 case 'm': 233 $val *= 1024; 234 case 'k': 235 $val *= 1024; 236 } 237 return $val; 238 } 239 240 /** 241 * Build a string, containing a javascript wrapper function 242 * for setting applet properties via JavaScript. This is necessary, 243 * because we use the "modern" method of including the applet (using 244 * <object> resp. <embed> tags) in order to trigger automatic JRE downloading. 245 * Therefore, in Netscape-like browsers, the applet is accessible via 246 * the document.embeds[] array while in others, it is accessible via the 247 * document.applets[] array. 248 * 249 * @return A string, containing the necessary wrapper function (named JUploadSetProperty) 250 */ 251 private function str_jsinit() { 252 $N = "\n"; 253 $name = $this->appletparams['name']; 254 $ret = '<script type="text/javascript">'.$N; 255 $ret .= '<!--'.$N; 256 $ret .= 'function '.$this->classparams['jscript_wrapper'].'(name, value) {'.$N; 257 $ret .= ' document.applets["'.$name.'"] == null || document.applets["'.$name.'"].setProperty(name,value);'.$N; 258 $ret .= ' document.embeds["'.$name.'"] == null || document.embeds["'.$name.'"].setProperty(name,value);'.$N; 259 $ret .= '}'.$N; 260 $ret .= '//-->'.$N; 261 $ret .= '</script>'; 262 return $ret; 263 } 264 265 /** 266 * Build a string, containing the applet tag with all parameters. 267 * 268 * @return A string, containing the applet tag 269 */ 270 private function str_applet() { 271 $N = "\n"; 272 $params = $this->appletparams; 273 // return the actual applet tag 274 $ret = '<object classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"'.$N; 275 $ret .= ' codebase = "http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,3"'.$N; 276 $ret .= ' width = "'.$params['width'].'"'.$N; 277 $ret .= ' height = "'.$params['height'].'"'.$N; 278 $ret .= ' name = "'.$params['name'].'">'.$N; 279 foreach ($params as $key => $val) { 280 if ($key != 'width' && $key != 'height') 281 $ret .= ' <param name = "'.$key.'" value = "'.$val.'" />'.$N; 282 } 283 $ret .= ' <comment>'.$N; 284 $ret .= ' <embed'.$N; 285 $ret .= ' type = "application/x-java-applet;version=1.5"'.$N; 286 foreach ($params as $key => $val) 287 $ret .= ' '.$key.' = "'.$val.'"'.$N; 288 $ret .= ' pluginspage = "http://java.sun.com/products/plugin/index.html#download">'.$N; 289 $ret .= ' <noembed>'.$N; 290 $ret .= ' Java 1.5 or higher plugin required.'.$N; 291 $ret .= ' </noembed>'.$N; 292 $ret .= ' </embed>'.$N; 293 $ret .= ' </comment>'.$N; 294 $ret .= '</object>'; 295 return $ret; 296 } 297 298 private function abort($msg = '') { 299 $this->cleanup(); 300 if ($msg != '') 301 die(str_replace('(.*)',$msg,$this->appletparams['stringUploadError'])."\n"); 302 exit; 303 } 304 305 private function warning($msg = '') { 306 $this->cleanup(); 307 if ($msg != '') 308 echo('WARNING: '.$msg."\n"); 309 echo $this->appletparams['stringUploadSuccess']."\n"; 310 exit; 311 } 312 313 private function cleanup() { 314 // remove all uploaded files of *this* request 315 if (isset($_FILES)) { 316 foreach ($_FILES as $key => $val) 317 @unlink($val['tmp_name']); 318 } 319 // remove accumulated file, if any. 320 @unlink($this->classparams['destdir'].'/'.$this->classparams['tmp_prefix'].session_id()); 321 @unlink($this->classparams['destdir'].'/'.$this->classparams['tmp_prefix'].'tmp'.session_id()); 322 // reset session var 323 $_SESSION[$this->classparams['var_prefix'].'size'] = 0; 324 return; 325 } 326 327 private function mkdirp($path) { 328 // create subdir (hierary) below destdir; 329 $dirs = explode('/', $path); 330 $path = $this->classparams['destdir']; 331 foreach ($dirs as $dir) { 332 $path .= '/'.$dir; 333 if (!file_exists($path)) { // @ does NOT always supress the error! 334 @mkdir($path, $this->classparams['dirperm']); 335 } 336 } 337 if (!is_dir($path) && is_writable($path)) 338 $this->abort('Destination dir not accessible'); 339 } 56 var $appletparams; 57 var $classparams; 58 var $files; 59 60 public function JUpload($appletparams = array(), $classparams = array()) { 61 if (gettype($classparams) != 'array') 62 $this->abort('Invalid type of parameter classparams: Expecting an array'); 63 if (gettype($appletparams) != 'array') 64 $this->abort('Invalid type of parameter appletparams: Expecting an array'); 65 66 // set some defaults for the applet params 67 if (!isset($appletparams['afterUploadURL'])) 68 $appletparams['afterUploadURL'] = $_SERVER['PHP_SELF'] . '?afterupload=1'; 69 if (!isset($appletparams['name'])) 70 $appletparams['name'] = 'JUpload'; 71 if (!isset($appletparams['archive'])) 72 $appletparams['archive'] = 'wjhk.jupload.jar'; 73 if (!isset($appletparams['code'])) 74 $appletparams['code'] = 'wjhk.jupload2.JUploadApplet'; 75 if (!isset($appletparams['debugLevel'])) 76 $appletparams['debugLevel'] = 0; 77 if (!isset($appletparams['httpUploadParameterType'])) 78 $appletparams['httpUploadParameterType'] = 'array'; 79 if (!isset($appletparams['showLogWindow'])) 80 $appletparams['showLogWindow'] = ($appletparams['debugLevel'] > 0) ? 'true' : 'false'; 81 if (!isset($appletparams['width'])) 82 $appletparams['width'] = 500; 83 if (!isset($appletparams['height'])) 84 $appletparams['height'] = ($appletparams['showLogWindow'] == 'true') ? 500 : 300; 85 if (!isset($appletparams['mayscript'])) 86 $appletparams['mayscript'] = 'true'; 87 if (!isset($appletparams['scriptable'])) 88 $appletparams['scriptable'] = 'false'; 89 //if (!isset($appletparams['stringUploadSuccess'])) 90 $appletparams['stringUploadSuccess'] = 'SUCCESS'; 91 //if (!isset($appletparams['stringUploadError'])) 92 $appletparams['stringUploadError'] = 'ERROR: (.*)'; 93 $maxpost = $this->tobytes(ini_get('post_max_size')); 94 $maxmem = $this->tobytes(ini_get('memory_limit')); 95 $maxfs = $this->tobytes(ini_get('upload_max_filesize')); 96 $obd = ini_get('open_basedir'); 97 if (!isset($appletparams['maxChunkSize'])) { 98 $maxchunk = ($maxpost < $maxmem) ? $maxpost : $maxmem; 99 $maxchunk = ($maxchunk < $maxfs) ? $maxchunk : $maxfs; 100 $maxchunk /= 4; 101 $optchunk = (500000 > $maxchunk) ? $maxchunk : 500000; 102 $appletparams['maxChunkSize'] = $optchunk; 103 } 104 $appletparams['maxChunkSize'] = $this->tobytes($appletparams['maxChunkSize']); 105 if (!isset($appletparams['maxFileSize'])) 106 $appletparams['maxFileSize'] = $maxfs; 107 $appletparams['maxFileSize'] = $this->tobytes($appletparams['maxFileSize']); 108 if (isset($classparams['errormail'])) { 109 $appletparams['urlToSendErrorTo'] = $_SERVER["PHP_SELF"] . '?errormail'; 110 } 111 112 // Same for class parameters 113 if (!isset($classparams['demo_mode'])) 114 $classparams['demo_mode'] = false; 115 if ($classparams['demo_mode']) { 116 $classparams['create_destdir'] = false; 117 $classparams['allow_subdirs'] = true; 118 $classparams['allow_zerosized'] = true; 119 $classparams['duplicate'] = 'overwrite'; 120 } 121 if (!isset($classparams['debug_php'])) // set true to log some messages in PHP log 122 $classparams['debug_php'] = false; 123 if (!isset($this->classparams['allowed_mime_types'])) // array of allowed MIME type 124 $classparams['allowed_mime_types'] = 'all'; 125 if (!isset($this->classparams['allowed_file_extensions'])) // array of allowed file extensions 126 $classparams['allowed_file_extensions'] = 'all'; 127 if (!isset($classparams['verbose_errors'])) // shouldn't display server info on a production site! 128 $classparams['verbose_errors'] = true; 129 if (!isset($classparams['session_regenerate'])) 130 $classparams['session_regenerate'] = false; 131 if (!isset($classparams['create_destdir'])) 132 $classparams['create_destdir'] = true; 133 if (!isset($classparams['allow_subdirs'])) 134 $classparams['allow_subdirs'] = false; 135 if (!isset($classparams['spaces_in_subdirs'])) 136 $classparams['spaces_in_subdirs'] = false; 137 if (!isset($classparams['allow_zerosized'])) 138 $classparams['allow_zerosized'] = false; 139 if (!isset($classparams['duplicate'])) 140 $classparams['duplicate'] = 'rename'; 141 if (!isset($classparams['dirperm'])) 142 $classparams['dirperm'] = 0755; 143 if (!isset($classparams['fileperm'])) 144 $classparams['fileperm'] = 0644; 145 if (!isset($classparams['destdir'])) { 146 if ($obd != '') 147 $classparams['destdir'] = $obd; 148 else 149 $classparams['destdir'] = '/var/tmp/jupload_test'; 150 } 151 if ($classparams['create_destdir']) 152 @mkdir($classparams['destdir'], $classparams['dirperm']); 153 if (!is_dir($classparams['destdir']) && is_writable($classparams['destdir'])) 154 $this->abort('Destination dir not accessible'); 155 if (!isset($classparams['tmp_prefix'])) 156 $classparams['tmp_prefix'] = 'jutmp.'; 157 if (!isset($classparams['var_prefix'])) 158 $classparams['var_prefix'] = 'juvar.'; 159 if (!isset($classparams['jscript_wrapper'])) 160 $classparams['jscript_wrapper'] = 'JUploadSetProperty'; 161 if (!isset($classparams['tag_jscript'])) 162 $classparams['tag_jscript'] = '<!--JUPLOAD_JSCRIPT-->'; 163 if (!isset($classparams['tag_applet'])) 164 $classparams['tag_applet'] = '<!--JUPLOAD_APPLET-->'; 165 if (!isset($classparams['tag_flist'])) 166 $classparams['tag_flist'] = '<!--JUPLOAD_FILES-->'; 167 if (!isset($classparams['http_flist_start'])) 168 $classparams['http_flist_start'] = 169 "<table border='1'><TR><TH>Filename</TH><TH>file size</TH><TH>Relative path</TH><TH>Full name</TH><TH>md5sum</TH><TH>Specific parameters</TH></TR>"; 170 if (!isset($classparams['http_flist_end'])) 171 $classparams['http_flist_end'] = "</table>\n"; 172 if (!isset($classparams['http_flist_file_before'])) 173 $classparams['http_flist_file_before'] = "<tr><td>"; 174 if (!isset($classparams['http_flist_file_between'])) 175 $classparams['http_flist_file_between'] = "</td><td>"; 176 if (!isset($classparams['http_flist_file_after'])) 177 $classparams['http_flist_file_after'] = "</td></tr>\n"; 178 179 $this->appletparams = $appletparams; 180 $this->classparams = $classparams; 181 $this->page_start(); 182 } 183 184 /** 185 * Log a message on the current output, as a HTML comment. 186 */ 187 protected function logDebug($function, $msg, $htmlComment=true) 188 { 189 $output = "[DEBUG] [$function] $msg"; 190 if ($htmlComment) { 191 echo("<!-- $output -->\r\n"); 192 } else { 193 echo("$output\r\n"); 194 } 195 } 196 197 /** 198 * Log a message to the PHP log. 199 * Declared "protected" so it may be Extended if you require customised logging (e.g. particular log file location). 200 */ 201 protected function logPHPDebug($function, $msg) 202 { 203 if ($this->classparams['debug_php'] === true) { 204 $output = "[DEBUG] [$function] " . $this->arrayexpand($msg); 205 error_log($output); 206 } 207 } 208 209 private function arrayexpand($array) 210 { 211 $output = ''; 212 if (is_array($array)) { 213 foreach ($array as $key => $value) { 214 $output .= "\n " . $key . ' => ' . $this->arrayexpand($value); 215 } 216 } else { 217 $output .= $array; 218 } 219 return $output; 220 } 221 222 /** 223 * Convert a value ending in 'G','M' or 'K' to bytes 224 * 225 */ 226 private function tobytes($val) 227 { 228 $val = trim($val); 229 $last = strtolower($val{strlen($val) - 1}); 230 switch ($last) { 231 case 'g': 232 $val *= 1024; 233 case 'm': 234 $val *= 1024; 235 case 'k': 236 $val *= 1024; 237 } 238 return $val; 239 } 240 241 /** 242 * Build a string, containing a javascript wrapper function 243 * for setting applet properties via JavaScript. This is necessary, 244 * because we use the "modern" method of including the applet (using 245 * <object> resp. <embed> tags) in order to trigger automatic JRE downloading. 246 * Therefore, in Netscape-like browsers, the applet is accessible via 247 * the document.embeds[] array while in others, it is accessible via the 248 * document.applets[] array. 249 * 250 * @return A string, containing the necessary wrapper function (named JUploadSetProperty) 251 */ 252 private function str_jsinit() 253 { 254 $N = "\n"; 255 $name = $this->appletparams['name']; 256 $ret = '<script type="text/javascript">' . $N; 257 $ret .= '<!--' . $N; 258 $ret .= 'function ' . $this->classparams['jscript_wrapper'] . '(name, value) {' . $N; 259 $ret .= ' document.applets["' . $name . '"] == null || document.applets["' . $name . '"].setProperty(name,value);' . $N; 260 $ret .= ' document.embeds["' . $name . '"] == null || document.embeds["' . $name . '"].setProperty(name,value);' . $N; 261 $ret .= '}' . $N; 262 $ret .= '//-->' . $N; 263 $ret .= '</script>'; 264 return $ret; 265 } 266 267 /** 268 * Build a string, containing the applet tag with all parameters. 269 * 270 * @return A string, containing the applet tag 271 */ 272 private function str_applet() { 273 $N = "\n"; 274 $params = $this->appletparams; 275 // return the actual applet tag 276 $ret = '<object classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"' . $N; 277 $ret .= ' codebase = "http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,3"' . $N; 278 $ret .= ' width = "' . $params['width'] . '"' . $N; 279 $ret .= ' height = "' . $params['height'] . '"' . $N; 280 $ret .= ' name = "' . $params['name'] . '">' . $N; 281 foreach ($params as $key => $val) { 282 if ($key != 'width' && $key != 'height') 283 $ret .= ' <param name = "' . $key . '" value = "' . $val . '" />' . $N; 284 } 285 $ret .= ' <comment>' . $N; 286 $ret .= ' <embed' . $N; 287 $ret .= ' type = "application/x-java-applet;version=1.5"' . $N; 288 foreach ($params as $key => $val) 289 $ret .= ' ' . $key . ' = "' . $val . '"' . $N; 290 $ret .= ' pluginspage = "http://java.sun.com/products/plugin/index.html#download">' . $N; 291 $ret .= ' <noembed>' . $N; 292 $ret .= ' Java 1.5 or higher plugin required.' . $N; 293 $ret .= ' </noembed>' . $N; 294 $ret .= ' </embed>' . $N; 295 $ret .= ' </comment>' . $N; 296 $ret .= '</object>'; 297 return $ret; 298 } 299 300 private function abort($msg = '') 301 { 302 $this->cleanup(); 303 if ($msg != '') 304 die(str_replace('(.*)', $msg, $this->appletparams['stringUploadError']) . "\n"); 305 exit; 306 } 307 308 private function warning($msg = '') 309 { 310 $this->cleanup(); 311 if ($msg != '') 312 echo('WARNING: ' . $msg . "\n"); 313 echo $this->appletparams['stringUploadSuccess'] . "\n"; 314 exit; 315 } 316 317 private function cleanup() 318 { 319 // remove all uploaded files of *this* request 320 if (isset($_FILES)) { 321 foreach ($_FILES as $key => $val) 322 @unlink($val['tmp_name']); 323 } 324 // remove accumulated file, if any. 325 @unlink($this->classparams['destdir'] . '/' . $this->classparams['tmp_prefix'] . session_id()); 326 @unlink($this->classparams['destdir'] . '/' . $this->classparams['tmp_prefix'] . 'tmp' . session_id()); 327 // reset session var 328 $_SESSION[$this->classparams['var_prefix'] . 'size'] = 0; 329 return; 330 } 331 332 private function mkdirp($path) 333 { 334 // create subdir (hierary) below destdir; 335 $dirs = explode('/', $path); 336 $path = $this->classparams['destdir']; 337 foreach ($dirs as $dir) 338 { 339 $path .= '/' . $dir; 340 if (!file_exists($path)) { // @ does NOT always supress the error! 341 @mkdir($path, $this->classparams['dirperm']); 342 } 343 } 344 if (!is_dir($path) && is_writable($path)) 345 $this->abort('Destination dir not accessible'); 346 } 340 347 341 348 /** … … 348 355 * - If yes, and the duplicate class param is set to reject, an error is thrown. 349 356 */ 350 private function dstfinal(&$name, &$subdir) { 351 $name = preg_replace('![`$\\\\/|]!', '_', $name); 352 if ($this->classparams['allow_subdirs'] && ($subdir != '')) { 353 $subdir = trim(preg_replace('!\\\\!','/',$subdir),'/'); 354 $subdir = preg_replace('![`$|]!', '_', $subdir); 355 if (!$this->classparams['spaces_in_subdirs']) { 356 $subdir = str_replace(' ','_',$subdir); 357 } 358 // recursively create subdir 359 if (!$this->classparams['demo_mode']) 360 $this->mkdirp($subdir); 361 // append a slash 362 $subdir .= '/'; 363 } else { 364 $subdir = ''; 365 } 366 $ret = $this->classparams['destdir'].'/'.$subdir.$name; 367 if (file_exists($ret)) { 368 if ($this->classparams['duplicate'] == 'overwrite') { 369 return $ret; 370 } 371 if ($this->classparams['duplicate'] == 'reject') { 372 $this->abort('A file with the same name already exists'); 373 } 374 if ($this->classparams['duplicate'] == 'warning') { 375 $this->warning("File $name already exists - rejected"); 376 } 377 if ($this->classparams['duplicate'] == 'rename') { 378 $cnt = 1; 379 $dir = $this->classparams['destdir'].'/'.$subdir; 380 $ext = strrchr($name, '.'); 381 if ($ext) { 382 $nameWithoutExtension = substr($name, 0, strlen($name) - strlen($ext)); 383 } else { 384 $ext = ''; 385 $nameWithoutExtension = $name; 386 } 387 388 $rtry = $dir.$nameWithoutExtension.'.['.$cnt.']'.$ext; 389 while (file_exists($rtry)) { 390 $cnt++; 391 $rtry = $dir.$nameWithoutExtension.'.['.$cnt.']'.$ext; 392 } 393 //We store the result name in the byReference name parameter. 394 $name = $nameWithoutExtension.'.['.$cnt.']'.$ext; 395 $ret = $rtry; 396 } 397 } 398 return $ret; 399 } 400 401 /** 402 * Example function to process the files uploaded. This one simply displays the files' data. 403 * 404 */ 405 public function defaultAfterUploadManagement() { 406 $flist = '[defaultAfterUploadManagement] Nb uploaded files is: ' . sizeof($this->files); 407 $flist = $this->classparams['http_flist_start']; 408 foreach ($this->files as $f) { 409 //$f is an array, that contains all info about the uploaded file. 410 $this->logDebug('defaultAfterUploadManagement', " Reading file ${f['name']}"); 411 $flist .= $this->classparams['http_flist_file_before']; 412 $flist .= $f['name']; 413 $flist .= $this->classparams['http_flist_file_between']; 414 $flist .= $f['size']; 415 $flist .= $this->classparams['http_flist_file_between']; 416 $flist .= $f['relativePath']; 417 $flist .= $this->classparams['http_flist_file_between']; 418 $flist .= $f['fullName']; 419 $flist .= $this->classparams['http_flist_file_between']; 420 $flist .= $f['md5sum']; 421 $addBR = false; 422 foreach ($f as $key=>$value) { 423 //If it's a specific key, let's display it: 424 if ($key != 'name' && $key != 'size' && $key != 'relativePath' && $key != 'fullName' && $key != 'md5sum') { 425 if ($addBR) { 426 $flist .= "<br>"; 427 } else { 428 // First line. We must add a new 'official' list separator. 429 $flist .= $this->classparams['http_flist_file_between']; 430 $addBR = true; 431 } 432 $flist .= "$key => $value"; 433 } 434 } 435 $flist .= $this->classparams['http_flist_file_after']; 436 } 437 $flist .= $this->classparams['http_flist_end']; 438 439 return $flist; 440 } 441 442 /** 443 * Generation of the applet tag, and necessary things around (js content). Insertion of this into the content of the 444 * page. 445 * See the tag_jscript and tag_applet class parameters. 446 */ 447 private function generateAppletTag($str) { 448 $this->logDebug('generateAppletTag', 'Entering function'); 449 $str = preg_replace('/'.$this->classparams['tag_jscript'].'/', $this->str_jsinit(), $str); 450 return preg_replace('/'.$this->classparams['tag_applet'].'/', $this->str_applet(), $str); 451 } 452 453 /** 454 * This function is called when constructing the page, when we're not reveiving uploaded files. It 'just' construct 455 * the applet tag, by calling the relevant function. 456 * 457 * This *must* be public, because it is called from PHP's output buffering 458 */ 459 public function interceptBeforeUpload($str) { 460 $this->logDebug('interceptBeforeUpload', 'Entering function'); 461 return $this->generateAppletTag($str); 462 } 357 private function dstfinal(&$name, &$subdir) 358 { 359 $name = preg_replace('![`$\\\\/|]!', '_', $name); 360 if ($this->classparams['allow_subdirs'] && ($subdir != '')) { 361 $subdir = trim(preg_replace('!\\\\!', '/', $subdir), '/'); 362 $subdir = preg_replace('![`$|]!', '_', $subdir); 363 if (!$this->classparams['spaces_in_subdirs']) { 364 $subdir = str_replace(' ', '_', $subdir); 365 } 366 // recursively create subdir 367 if (!$this->classparams['demo_mode']) 368 $this->mkdirp($subdir); 369 // append a slash 370 $subdir .= '/'; 371 } else { 372 $subdir = ''; 373 } 374 $ret = $this->classparams['destdir'] . '/' . $subdir . $name; 375 if (file_exists($ret)) { 376 if ($this->classparams['duplicate'] == 'overwrite') { 377 return $ret; 378 } 379 if ($this->classparams['duplicate'] == 'reject') { 380 $this->abort('A file with the same name already exists'); 381 } 382 if ($this->classparams['duplicate'] == 'warning') { 383 $this->warning("File $name already exists - rejected"); 384 } 385 if ($this->classparams['duplicate'] == 'rename') { 386 $cnt = 1; 387 $dir = $this->classparams['destdir'] . '/' . $subdir; 388 $ext = strrchr($name, '.'); 389 if ($ext) { 390 $nameWithoutExtension = substr($name, 0, strlen($name) - strlen($ext)); 391 } else { 392 $ext = ''; 393 $nameWithoutExtension = $name; 394 } 395 396 $rtry = $dir . $nameWithoutExtension . '.[' . $cnt . ']' . $ext; 397 while (file_exists($rtry)) { 398 $cnt++; 399 $rtry = $dir . $nameWithoutExtension . '.[' . $cnt . ']' . $ext; 400 } 401 //We store the result name in the byReference name parameter. 402 $name = $nameWithoutExtension . '.[' . $cnt . ']' . $ext; 403 $ret = $rtry; 404 } 405 } 406 return $ret; 407 } 408 409 /** 410 * Example function to process the files uploaded. This one simply displays the files' data. 411 * 412 */ 413 public function defaultAfterUploadManagement() 414 { 415 $flist = '[defaultAfterUploadManagement] Nb uploaded files is: ' . sizeof($this->files); 416 $flist = $this->classparams['http_flist_start']; 417 foreach ($this->files as $f) { 418 //$f is an array, that contains all info about the uploaded file. 419 $this->logDebug('defaultAfterUploadManagement', " Reading file ${f['name']}"); 420 $flist .= $this->classparams['http_flist_file_before']; 421 $flist .= $f['name']; 422 $flist .= $this->classparams['http_flist_file_between']; 423 $flist .= $f['size']; 424 $flist .= $this->classparams['http_flist_file_between']; 425 $flist .= $f['relativePath']; 426 $flist .= $this->classparams['http_flist_file_between']; 427 $flist .= $f['fullName']; 428 $flist .= $this->classparams['http_flist_file_between']; 429 $flist .= $f['md5sum']; 430 $addBR = false; 431 foreach ($f as $key => $value) { 432 //If it's a specific key, let's display it: 433 if ($key != 'name' && $key != 'size' && $key != 'relativePath' && $key != 'fullName' && $key != 'md5sum') { 434 if ($addBR) { 435 $flist .= "<br>"; 436 } else { 437 // First line. We must add a new 'official' list separator. 438 $flist .= $this->classparams['http_flist_file_between']; 439 $addBR = true; 440 } 441 $flist .= "$key => $value"; 442 } 443 } 444 $flist .= $this->classparams['http_flist_file_after']; 445 } 446 $flist .= $this->classparams['http_flist_end']; 447 448 return $flist; 449 } 450 451 /** 452 * Generation of the applet tag, and necessary things around (js content). Insertion of this into the content of the 453 * page. 454 * See the tag_jscript and tag_applet class parameters. 455 */ 456 private function generateAppletTag($str) 457 { 458 $this->logDebug('generateAppletTag', 'Entering function'); 459 $str = preg_replace('/' . $this->classparams['tag_jscript'] . '/', $this->str_jsinit(), $str); 460 return preg_replace('/' . $this->classparams['tag_applet'] . '/', $this->str_applet(), $str); 461 } 462 463 /** 464 * This function is called when constructing the page, when we're not reveiving uploaded files. It 'just' construct 465 * the applet tag, by calling the relevant function. 466 * 467 * This *must* be public, because it is called from PHP's output buffering 468 */ 469 public function interceptBeforeUpload($str) 470 { 471 $this->logDebug('interceptBeforeUpload', 'Entering function'); 472 return $this->generateAppletTag($str); 473 } 463 474 464 475 /** … … 467 478 * This *must* be public, because it is called from PHP's output buffering. 468 479 */ 469 public function interceptAfterUpload($str) { 470 $this->logDebug('interceptAfterUpload', 'Entering function'); 471 $this->logPHPDebug('interceptAfterUpload', $this->files); 472 473 if (count($this->files) > 0) { 474 if (isset($this->classparams['callbackAfterUploadManagement'])) { 475 $this->logDebug('interceptAfterUpload', 'Before call of ' .$this->classparams['callbackAfterUploadManagement']); 476 $strForFListContent = call_user_func($this->classparams['callbackAfterUploadManagement'], $this, $this->files); 477 } else { 478 $strForFListContent = $this->defaultAfterUploadManagement(); 479 } 480 $str = preg_replace('/'.$this->classparams['tag_flist'].'/', $strForFListContent, $str); 481 } 482 return $this->generateAppletTag($str); 483 } 484 485 /** 486 * This method manages the receiving of the debug log, when an error occurs. 487 */ 488 private function receive_debug_log() { 489 // handle error report 490 if (isset($_POST['description']) && isset($_POST['log'])) { 491 $msg = $_POST['log']; 492 mail($this->classparams['errormail'], $_POST['description'], $msg); 493 } else { 494 if (isset($_SERVER['SERVER_ADMIN'])) 495 mail($_SERVER['SERVER_ADMIN'], 'Empty jupload error log', 496 'An empty log has just been posted.'); 497 $this->logPHPDebug('receive_debug_log', 'Empty error log received'); 498 } 499 exit; 500 } 501 502 /** 503 * This method is the heart of the system. It manage the files sent by the applet, check the incoming parameters (md5sum) and 504 * reconstruct the files sent in chunk mode. 505 * 506 * The result is stored in the $files array, and can then be managed by the function given in the callbackAfterUploadManagement 507 * class parameter, or within the page whose URL is given in the afterUploadURL applet parameter. 508 * Or you can Extend the class and redeclare defaultAfterUploadManagement() to your needs. 509 */ 510 private function receive_uploaded_files() { 511 $this->logDebug('receive_uploaded_files', 'Entering POST management'); 512 513 if (session_id() == '') { include_once('../../header.session.inc.php'); } 514 // we check for the session *after* handling possible error log 515 // because an error could have happened because the session-id is missing. 516 if (!isset($_SESSION[$this->classparams['var_prefix'].'size'])) { 517 $this->abort('Invalid session (in afterupload, POST, check of size)'); 518 } 519 if (!isset($_SESSION[$this->classparams['var_prefix'].'files'])) { 520 $this->abort('Invalid session (in afterupload, POST, check of files)'); 521 } 522 $this->files = $_SESSION[$this->classparams['var_prefix'].'files']; 523 if (!is_array($this->files)) { 524 $this->abort('Invalid session (in afterupload, POST, is_array(files))'); 525 } 526 if ($this->appletParameters['sendMD5Sum'] && !isset($_POST['md5sum'])) { 527 $this->abort('Required POST variable md5sum is missing'); 528 } 529 $cnt = 0; 530 foreach ($_FILES as $key => $value) { 531 //Let's read the $_FILES data 532 if (isset($files_data)) { 533 unset($files_data); 534 } 535 $jupart = (isset($_POST['jupart'])) ? (int)$_POST['jupart'] : 0; 536 $jufinal = (isset($_POST['jufinal'])) ? (int)$_POST['jufinal'] : 1; 537 $relpaths = (isset($_POST['relpathinfo'])) ? $_POST['relpathinfo'] : null; 538 $md5sums = (isset($_POST['md5sum'])) ? $_POST['md5sum'] : null; 539 $mimetypes = (isset($_POST['mimetype'])) ? $_POST['mimetype'] : null; 540 //$relpaths = (isset($_POST["relpathinfo$cnt"])) ? $_POST["relpathinfo$cnt"] : null; 541 //$md5sums = (isset($_POST["md5sum$cnt"])) ? $_POST["md5sum$cnt"] : null; 542 543 if (gettype($relpaths) == 'string') { 544 $relpaths = array($relpaths); 545 } 546 if (gettype($md5sums) == 'string') { 547 $md5sums = array($md5sums); 548 } 549 if ($this->appletParameters['sendMD5Sum'] && !is_array($md5sums)) { 550 $this->abort('Expecting an array of MD5 checksums'); 551 } 552 if (!is_array($relpaths)) { 553 $this->abort('Expecting an array of relative paths'); 554 } 555 if (!is_array($mimetypes)) { 556 $this->abort('Expecting an array of MIME types'); 557 } 558 // Check the MIME type (note: this is easily forged!) 559 if (isset($this->classparams['allowed_mime_types']) && is_array($this->classparams['allowed_mime_types'])) { 560 if (!in_array($mimetypes[$cnt], $this->classparams['allowed_mime_types'])) { 561 $this->abort('MIME type '.$mimetypes[$cnt].' not allowed'); 562 } 563 } 564 if (isset($this->classparams['allowed_file_extensions']) && is_array($this->classparams['allowed_file_extensions'])) { 565 $fileExtension = substr(strrchr($value['name'][$cnt], "."), 1); 566 if (!in_array($fileExtension, $this->classparams['allowed_file_extensions'])) { 567 $this->abort('File extension '.$fileExtension.' not allowed'); 568 } 569 } 570 571 $dstdir = $this->classparams['destdir']; 572 $dstname = $dstdir.'/'.$this->classparams['tmp_prefix'].session_id(); 573 $tmpname = $dstdir.'/'.$this->classparams['tmp_prefix'].'tmp'.session_id(); 574 575 // Controls are now done. Let's store the current uploaded files properties in an array, for future use. 576 $files_data['name'] = $value['name'][$cnt]; 577 $files_data['size'] = 'not calculated yet'; 578 $files_data['tmp_name'] = $value['tmp_name'][$cnt]; 579 $files_data['error'] = $value['error'][$cnt]; 580 $files_data['relativePath'] = $relpaths[$cnt]; 581 $files_data['md5sum'] = $md5sums[$cnt]; 582 $files_data['mimetype'] = $mimetypes[$cnt]; 583 584 if (!move_uploaded_file($files_data['tmp_name'], $tmpname)) { 585 if ($classparams['verbose_errors']) { 586 $this->abort("Unable to move uploaded file (from ${files_data['tmp_name']} to $tmpname)"); 587 } else { 588 trigger_error("Unable to move uploaded file (from ${files_data['tmp_name']} to $tmpname)",E_USER_WARNING); 589 $this->abort("Unable to move uploaded file"); 590 } 591 } 592 593 // In demo mode, no file storing is done. We just delete the newly uploaded file. 594 if ($this->classparams['demo_mode']) { 595 if ($jufinal || (!$jupart)) { 596 if ($jupart) { 597 $files_data['size'] = ($jupart-1) * $this->appletparams['maxChunkSize'] + filesize($tmpname); 598 } else { 599 $files_data['size'] = filesize($tmpname); 600 } 601 $files_data['fullName'] = 'Demo mode<BR>No file storing'; 602 array_push($this->files, $files_data); 603 } 604 unlink($tmpname); 605 $cnt++; 606 continue; 607 } 608 //If we get here, the upload is a real one (no demo) 609 if ($jupart) { 610 // got a chunk of a multi-part upload 611 $len = filesize($tmpname); 612 $_SESSION[$this->classparams['var_prefix'].'size'] += $len; 613 if ($len > 0) { 614 $src = fopen($tmpname, 'rb'); 615 $dst = fopen($dstname, ($jupart == 1) ? 'wb' : 'ab'); 616 while ($len > 0) { 617 $rlen = ($len > 8192) ? 8192 : $len; 618 $buf = fread($src, $rlen); 619 if (!$buf) { 620 fclose($src); 621 fclose($dst); 622 unlink($dstname); 623 $this->abort('read IO error'); 624 } 625 if (!fwrite($dst, $buf, $rlen)) { 626 fclose($src); 627 fclose($dst); 628 unlink($dstname); 629 $this->abort('write IO error'); 630 } 631 $len -= $rlen; 632 } 633 fclose($src); 634 fclose($dst); 635 unlink($tmpname); 636 } 637 if ($jufinal) { 638 // This is the last chunk. Check total lenght and 639 // rename it to it's final name. 640 $dlen = filesize($dstname); 641 if ($dlen != $_SESSION[$this->classparams['var_prefix'].'size']) 642 $this->abort('file size mismatch'); 643 if ($this->appletParameters['sendMD5Sum'] ) { 644 if ($md5sums[$cnt] != md5_file($dstname)) 645 $this->abort('MD5 checksum mismatch'); 646 } 647 // remove zero sized files 648 if (($dlen > 0) || $this->classparams['allow_zerosized']) { 649 $dstfinal = $this->dstfinal($files_data['name'],$files_data['relativePath']); 650 if (!rename($dstname, $dstfinal)) 651 $this->abort('rename IO error'); 652 if (!chmod($dstfinal, $this->classparams['fileperm'])) 653 $this->abort('chmod IO error'); 654 $files_data['size'] = filesize($dstfinal); 655 $files_data['fullName'] = $dstfinal; 656 $files_data['path'] = dirname($dstfinal); 657 array_push($this->files, $files_data); 658 } else { 659 unlink($dstname); 660 } 661 // reset session var 662 $_SESSION[$this->classparams['var_prefix'].'size'] = 0; 663 } 664 } else { 665 // Got a single file upload. Trivial. 666 if ($md5sums[$cnt] != md5_file($tmpname)) 667 $this->abort('MD5 checksum mismatch'); 668 $dstfinal = $this->dstfinal($files_data['name'],$files_data['relativePath']); 669 if (!rename($tmpname, $dstfinal)) 670 $this->abort('rename IO error'); 671 if (!chmod($dstfinal, $this->classparams['fileperm'])) 672 $this->abort('chmod IO error'); 673 $files_data['size'] = filesize($dstfinal); 674 $files_data['fullName'] = $dstfinal; 675 $files_data['path'] = dirname($dstfinal); 676 array_push($this->files, $files_data); 677 } 678 $cnt++; 679 } 680 681 echo $this->appletparams['stringUploadSuccess']."\n"; 682 $_SESSION[$this->classparams['var_prefix'].'files'] = $this->files; 683 session_write_close(); 684 exit; 685 } 686 687 /** 688 * 689 * 690 */ 691 private function page_start() { 692 $this->logDebug('page_start', 'Entering function'); 693 694 // If the applet checks for the serverProtocol, it issues a HEAD request 695 // -> Simply return an empty doc. 696 if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { 697 // Nothing to do 698 699 } else if ($_SERVER['REQUEST_METHOD'] == 'GET') { 700 // A GET request means: return upload page 701 $this->logDebug('page_start', 'Entering GET management'); 702 703 if (session_id() == '') { include_once('../../header.session.inc.php'); } 704 if (isset($_GET['afterupload'])) { 705 $this->logDebug('page_start', 'afterupload is set'); 706 if (!isset($_SESSION[$this->classparams['var_prefix'].'files'])) { 707 $this->abort('Invalid session (in afterupload, GET, check of $_SESSION): files array is not set'); 708 } 709 $this->files = $_SESSION[$this->classparams['var_prefix'].'files']; 710 if (!is_array($this->files)) { 711 $this->abort('Invalid session (in afterupload, GET, check of is_array(files)): files is not an array'); 712 } 713 // clear session data ready for new upload 714 $_SESSION[$this->classparams['var_prefix'].'files'] = array(); 715 716 // start intercepting the content of the calling page, to display the upload result. 717 ob_start(array(& $this, 'interceptAfterUpload')); 718 719 } else { 720 $this->logDebug('page_start', 'afterupload is not set'); 721 if ($this->classparams['session_regenerate']) { session_regenerate_id(true); } 722 $this->files = array(); 723 $_SESSION[$this->classparams['var_prefix'].'size'] = 0; 724 $_SESSION[$this->classparams['var_prefix'].'files'] = $this->files; 725 // start intercepting the content of the calling page, to display the applet tag. 726 ob_start(array(& $this, 'interceptBeforeUpload')); 727 } 728 729 } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { 730 // If we got a POST request, this is the real work. 731 if (isset($_GET['errormail'])) { 732 //Hum, an error occurs on server side. Let's manage the debug log, that we just received. 733 $this->receive_debug_log(); 480 public function interceptAfterUpload($str) 481 { 482 $this->logDebug('interceptAfterUpload', 'Entering function'); 483 $this->logPHPDebug('interceptAfterUpload', $this->files); 484 485 if (count($this->files) > 0) { 486 if (isset($this->classparams['callbackAfterUploadManagement'])) { 487 $this->logDebug('interceptAfterUpload', 'Before call of ' . $this->classparams['callbackAfterUploadManagement']); 488 $strForFListContent = call_user_func($this->classparams['callbackAfterUploadManagement'], $this, $this->files); 489 } else { 490 $strForFListContent = $this->defaultAfterUploadManagement(); 491 } 492 $str = preg_replace('/' . $this->classparams['tag_flist'] . '/', $strForFListContent, $str); 493 } 494 return $this->generateAppletTag($str); 495 } 496 497 /** 498 * This method manages the receiving of the debug log, when an error occurs. 499 */ 500 private function receive_debug_log() 501 { 502 // handle error report 503 if (isset($_POST['description']) && isset($_POST['log'])) { 504 $msg = $_POST['log']; 505 mail($this->classparams['errormail'], $_POST['description'], $msg); 506 } else { 507 if (isset($_SERVER['SERVER_ADMIN'])) 508 mail($_SERVER['SERVER_ADMIN'], 'Empty jupload error log', 'An empty log has just been posted.'); 509 $this->logPHPDebug('receive_debug_log', 'Empty error log received'); 510 } 511 exit; 512 } 513 514 /** 515 * This method is the heart of the system. It manage the files sent by the applet, check the incoming parameters (md5sum) and 516 * reconstruct the files sent in chunk mode. 517 * 518 * The result is stored in the $files array, and can then be managed by the function given in the callbackAfterUploadManagement 519 * class parameter, or within the page whose URL is given in the afterUploadURL applet parameter. 520 * Or you can Extend the class and redeclare defaultAfterUploadManagement() to your needs. 521 */ 522 private function receive_uploaded_files() 523 { 524 $this->logDebug('receive_uploaded_files', 'Entering POST management'); 525 526 if (session_id() == '') { 527 include_once('../../header.session.inc.php'); 528 } 529 // we check for the session *after* handling possible error log 530 // because an error could have happened because the session-id is missing. 531 if (!isset($_SESSION[$this->classparams['var_prefix'] . 'size'])) { 532 $this->abort('Invalid session (in afterupload, POST, check of size)'); 533 } 534 if (!isset($_SESSION[$this->classparams['var_prefix'] . 'files'])) { 535 $this->abort('Invalid session (in afterupload, POST, check of files)'); 536 } 537 $this->files = $_SESSION[$this->classparams['var_prefix'] . 'files']; 538 if (!is_array($this->files)) { 539 $this->abort('Invalid session (in afterupload, POST, is_array(files))'); 540 } 541 if ($this->appletParameters['sendMD5Sum'] && !isset($_POST['md5sum'])) { 542 $this->abort('Required POST variable md5sum is missing'); 543 } 544 $cnt = 0; 545 foreach ($_FILES as $key => $value) { 546 //Let's read the $_FILES data 547 if (isset($files_data)) { 548 unset($files_data); 549 } 550 $jupart = (isset($_POST['jupart'])) ? (int) $_POST['jupart'] : 0; 551 $jufinal = (isset($_POST['jufinal'])) ? (int) $_POST['jufinal'] : 1; 552 $relpaths = (isset($_POST['relpathinfo'])) ? $_POST['relpathinfo'] : null; 553 $md5sums = (isset($_POST['md5sum'])) ? $_POST['md5sum'] : null; 554 $mimetypes = (isset($_POST['mimetype'])) ? $_POST['mimetype'] : null; 555 //$relpaths = (isset($_POST["relpathinfo$cnt"])) ? $_POST["relpathinfo$cnt"] : null; 556 //$md5sums = (isset($_POST["md5sum$cnt"])) ? $_POST["md5sum$cnt"] : null; 557 558 if (gettype($relpaths) == 'string') { 559 $relpaths = array($relpaths); 560 } 561 if (gettype($md5sums) == 'string') { 562 $md5sums = array($md5sums); 563 } 564 if ($this->appletParameters['sendMD5Sum'] && !is_array($md5sums)) { 565 $this->abort('Expecting an array of MD5 checksums'); 566 } 567 if (!is_array($relpaths)) { 568 $this->abort('Expecting an array of relative paths'); 569 } 570 if (!is_array($mimetypes)) { 571 $this->abort('Expecting an array of MIME types'); 572 } 573 // Check the MIME type (note: this is easily forged!) 574 if (isset($this->classparams['allowed_mime_types']) && is_array($this->classparams['allowed_mime_types'])) { 575 if (!in_array($mimetypes[$cnt], $this->classparams['allowed_mime_types'])) { 576 $this->abort('MIME type ' . $mimetypes[$cnt] . ' not allowed'); 577 } 578 } 579 if (isset($this->classparams['allowed_file_extensions']) && is_array($this->classparams['allowed_file_extensions'])) { 580 $fileExtension = substr(strrchr($value['name'][$cnt], "."), 1); 581 if (!in_array($fileExtension, $this->classparams['allowed_file_extensions'])) { 582 $this->abort('File extension ' . $fileExtension . ' not allowed'); 583 } 584 } 585 586 $dstdir = $this->classparams['destdir']; 587 $dstname = $dstdir . '/' . $this->classparams['tmp_prefix'] . session_id(); 588 $tmpname = $dstdir . '/' . $this->classparams['tmp_prefix'] . 'tmp' . session_id(); 589 590 // Controls are now done. Let's store the current uploaded files properties in an array, for future use. 591 $files_data['name'] = $value['name'][$cnt]; 592 $files_data['size'] = 'not calculated yet'; 593 $files_data['tmp_name'] = $value['tmp_name'][$cnt]; 594 $files_data['error'] = $value['error'][$cnt]; 595 $files_data['relativePath'] = $relpaths[$cnt]; 596 $files_data['md5sum'] = $md5sums[$cnt]; 597 $files_data['mimetype'] = $mimetypes[$cnt]; 598 599 if (!move_uploaded_file($files_data['tmp_name'], $tmpname)) { 600 if ($classparams['verbose_errors']) { 601 $this->abort("Unable to move uploaded file (from ${files_data['tmp_name']} to $tmpname)"); 734 602 } else { 735 $this->receive_uploaded_files(); 736 } 737 } 738 } 603 trigger_error("Unable to move uploaded file (from ${files_data['tmp_name']} to $tmpname)", E_USER_WARNING); 604 $this->abort("Unable to move uploaded file"); 605 } 606 } 607 608 // In demo mode, no file storing is done. We just delete the newly uploaded file. 609 if ($this->classparams['demo_mode']) { 610 if ($jufinal || (!$jupart)) { 611 if ($jupart) { 612 $files_data['size'] = ($jupart - 1) * $this->appletparams['maxChunkSize'] + filesize($tmpname); 613 } else { 614 $files_data['size'] = filesize($tmpname); 615 } 616 $files_data['fullName'] = 'Demo mode<BR>No file storing'; 617 array_push($this->files, $files_data); 618 } 619 unlink($tmpname); 620 $cnt++; 621 continue; 622 } 623 //If we get here, the upload is a real one (no demo) 624 if ($jupart) { 625 // got a chunk of a multi-part upload 626 $len = filesize($tmpname); 627 $_SESSION[$this->classparams['var_prefix'] . 'size'] += $len; 628 if ($len > 0) { 629 $src = fopen($tmpname, 'rb'); 630 $dst = fopen($dstname, ($jupart == 1) ? 'wb' : 'ab'); 631 while ($len > 0) { 632 $rlen = ($len > 8192) ? 8192 : $len; 633 $buf = fread($src, $rlen); 634 if (!$buf) { 635 fclose($src); 636 fclose($dst); 637 unlink($dstname); 638 $this->abort('read IO error'); 639 } 640 if (!fwrite($dst, $buf, $rlen)) { 641 fclose($src); 642 fclose($dst); 643 unlink($dstname); 644 $this->abort('write IO error'); 645 } 646 $len -= $rlen; 647 } 648 fclose($src); 649 fclose($dst); 650 unlink($tmpname); 651 } 652 if ($jufinal) { 653 // This is the last chunk. Check total lenght and 654 // rename it to it's final name. 655 $dlen = filesize($dstname); 656 if ($dlen != $_SESSION[$this->classparams['var_prefix'] . 'size']) 657 $this->abort('file size mismatch'); 658 if ($this->appletParameters['sendMD5Sum']) { 659 if ($md5sums[$cnt] != md5_file($dstname)) 660 $this->abort('MD5 checksum mismatch'); 661 } 662 // remove zero sized files 663 if (($dlen > 0) || $this->classparams['allow_zerosized']) { 664 $dstfinal = $this->dstfinal($files_data['name'], $files_data['relativePath']); 665 if (!rename($dstname, $dstfinal)) 666 $this->abort('rename IO error'); 667 if (!chmod($dstfinal, $this->classparams['fileperm'])) 668 $this->abort('chmod IO error'); 669 $files_data['size'] = filesize($dstfinal); 670 $files_data['fullName'] = $dstfinal; 671 $files_data['path'] = dirname($dstfinal); 672 array_push($this->files, $files_data); 673 } else { 674 unlink($dstname); 675 } 676 // reset session var 677 $_SESSION[$this->classparams['var_prefix'] . 'size'] = 0; 678 } 679 } else { 680 // Got a single file upload. Trivial. 681 if ($md5sums[$cnt] != md5_file($tmpname)) 682 $this->abort('MD5 checksum mismatch'); 683 $dstfinal = $this->dstfinal($files_data['name'], $files_data['relativePath']); 684 if (!rename($tmpname, $dstfinal)) 685 $this->abort('rename IO error'); 686 if (!chmod($dstfinal, $this->classparams['fileperm'])) 687 $this->abort('chmod IO error'); 688 $files_data['size'] = filesize($dstfinal); 689 $files_data['fullName'] = $dstfinal; 690 $files_data['path'] = dirname($dstfinal); 691 array_push($this->files, $files_data); 692 } 693 $cnt++; 694 } 695 696 echo $this->appletparams['stringUploadSuccess'] . "\n"; 697 $_SESSION[$this->classparams['var_prefix'] . 'files'] = $this->files; 698 session_write_close(); 699 exit; 700 } 701 702 /** 703 * 704 * 705 */ 706 private function page_start() { 707 $this->logDebug('page_start', 'Entering function'); 708 709 // If the applet checks for the serverProtocol, it issues a HEAD request 710 // -> Simply return an empty doc. 711 if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { 712 // Nothing to do 713 } else if ($_SERVER['REQUEST_METHOD'] == 'GET') { 714 // A GET request means: return upload page 715 $this->logDebug('page_start', 'Entering GET management'); 716 717 if (session_id() == '') { 718 include_once('../../header.session.inc.php'); 719 } 720 if (isset($_GET['afterupload'])) { 721 $this->logDebug('page_start', 'afterupload is set'); 722 if (!isset($_SESSION[$this->classparams['var_prefix'] . 'files'])) { 723 $this->abort('Invalid session (in afterupload, GET, check of $_SESSION): files array is not set'); 724 } 725 $this->files = $_SESSION[$this->classparams['var_prefix'] . 'files']; 726 if (!is_array($this->files)) { 727 $this->abort('Invalid session (in afterupload, GET, check of is_array(files)): files is not an array'); 728 } 729 // clear session data ready for new upload 730 $_SESSION[$this->classparams['var_prefix'] . 'files'] = array(); 731 732 // start intercepting the content of the calling page, to display the upload result. 733 ob_start(array(& $this, 'interceptAfterUpload')); 734 } else { 735 $this->logDebug('page_start', 'afterupload is not set'); 736 if ($this->classparams['session_regenerate']) { 737 session_regenerate_id(true); 738 } 739 $this->files = array(); 740 $_SESSION[$this->classparams['var_prefix'] . 'size'] = 0; 741 $_SESSION[$this->classparams['var_prefix'] . 'files'] = $this->files; 742 // start intercepting the content of the calling page, to display the applet tag. 743 ob_start(array(& $this, 'interceptBeforeUpload')); 744 } 745 } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { 746 // If we got a POST request, this is the real work. 747 if (isset($_GET['errormail'])) { 748 //Hum, an error occurs on server side. Let's manage the debug log, that we just received. 749 $this->receive_debug_log(); 750 } else { 751 $this->receive_uploaded_files(); 752 } 753 } 754 } 755 739 756 } 740 757 -
branches/2.2/filemanager/inc/uploadApp.php
r3889 r3894 27 27 } 28 28 29 // Set Max Chunk Size 30 $maxChunkSize = ini_get('upload_max_filesize'); 31 $maxChunkSize = ( $maxChunkSize*1024 )*1024; 32 29 33 $appletParameters = array( 30 'maxFileSize' 31 'maxChunkSize' => '1600000',32 'archive' 33 'afterUploadURL' 34 'sendMD5Sum' 35 'showLogWindow' 36 'debugLevel' 34 'maxFileSize' => $maxFileSize, 35 'maxChunkSize' => $maxChunkSize, 36 'archive' => '../tp/juploader/wjhk.jupload.jar', 37 'afterUploadURL' => 'after_upload.php', 38 'sendMD5Sum' => 'true', 39 'showLogWindow' => 'false', 40 'debugLevel' => 0 37 41 ); 38 42 39 43 $classParameters = array( 40 'demo_mode' 41 'allow_subdirs' 42 'destdir' 44 'demo_mode' => false, 45 'allow_subdirs' => true, 46 'destdir' => '/tmp' //Where to store the files on the webserver 43 47 ); 44 48
Note: See TracChangeset
for help on using the changeset viewer.