| [ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 class ap_download extends ap_manage { 3 4 var $overwrite = true; 5 6 /** 7 * Initiate the plugin download 8 */ 9 function process() { 10 global $INPUT; 11 12 $plugin_url = $INPUT->str('url'); 13 $this->download($plugin_url, $this->overwrite); 14 return ''; 15 } 16 17 /** 18 * Print results of the download 19 */ 20 function html() { 21 parent::html(); 22 23 ptln('<div class="pm_info">'); 24 ptln('<h2>'.$this->lang['downloading'].'</h2>'); 25 26 if ($this->manager->error) { 27 ptln('<div class="error">'.str_replace("\n","<br />",hsc($this->manager->error)).'</div>'); 28 } else if (count($this->downloaded) == 1) { 29 ptln('<p>'.sprintf($this->lang['downloaded'],$this->downloaded[0]).'</p>'); 30 } else if (count($this->downloaded)) { // more than one plugin in the download 31 ptln('<p>'.$this->lang['downloads'].'</p>'); 32 ptln('<ul>'); 33 foreach ($this->downloaded as $plugin) { 34 ptln('<li><div class="li">'.$plugin.'</div></li>',2); 35 } 36 ptln('</ul>'); 37 } else { // none found in download 38 ptln('<p>'.$this->lang['download_none'].'</p>'); 39 } 40 ptln('</div>'); 41 } 42 43 /** 44 * Process the downloaded file 45 */ 46 function download($url, $overwrite=false) { 47 // check the url 48 $matches = array(); 49 if (!preg_match("/[^\/]*$/", $url, $matches) || !$matches[0]) { 50 $this->manager->error = $this->lang['error_badurl']."\n"; 51 return false; 52 } 53 54 $file = $matches[0]; 55 56 if (!($tmp = io_mktmpdir())) { 57 $this->manager->error = $this->lang['error_dircreate']."\n"; 58 return false; 59 } 60 61 if (!$file = io_download($url, "$tmp/", true, $file, 0)) { 62 $this->manager->error = sprintf($this->lang['error_download'],$url)."\n"; 63 } 64 65 if (!$this->manager->error && !$this->decompress("$tmp/$file", $tmp)) { 66 $this->manager->error = sprintf($this->lang['error_decompress'],$file)."\n"; 67 } 68 69 // search $tmp for the folder(s) that has been created 70 // move the folder(s) to lib/plugins/ 71 if (!$this->manager->error) { 72 $result = array('old'=>array(), 'new'=>array()); 73 if($this->find_folders($result,$tmp)){ 74 // choose correct result array 75 if(count($result['new'])){ 76 $install = $result['new']; 77 }else{ 78 $install = $result['old']; 79 } 80 81 // now install all found items 82 foreach($install as $item){ 83 // where to install? 84 if($item['type'] == 'template'){ 85 $target = DOKU_INC.'lib/tpl/'.$item['base']; 86 }else{ 87 $target = DOKU_INC.'lib/plugins/'.$item['base']; 88 } 89 90 // check to make sure we aren't overwriting anything 91 if (!$overwrite && @file_exists($target)) { 92 // remember our settings, ask the user to confirm overwrite, FIXME 93 continue; 94 } 95 96 $instruction = @file_exists($target) ? 'update' : 'install'; 97 98 // copy action 99 if ($this->dircopy($item['tmp'], $target)) { 100 $this->downloaded[] = $item['base']; 101 $this->plugin_writelog($target, $instruction, array($url)); 102 } else { 103 $this->manager->error .= sprintf($this->lang['error_copy']."\n", $item['base']); 104 } 105 } 106 107 } else { 108 $this->manager->error = $this->lang['error']."\n"; 109 } 110 } 111 112 // cleanup 113 if ($tmp) $this->dir_delete($tmp); 114 115 if (!$this->manager->error) { 116 msg(sprintf($this->lang['packageinstalled'], count($this->downloaded), join(',',$this->downloaded)),1); 117 $this->refresh(); 118 return true; 119 } 120 121 return false; 122 } 123 124 /** 125 * Find out what was in the extracted directory 126 * 127 * Correct folders are searched recursively using the "*.info.txt" configs 128 * as indicator for a root folder. When such a file is found, it's base 129 * setting is used (when set). All folders found by this method are stored 130 * in the 'new' key of the $result array. 131 * 132 * For backwards compatibility all found top level folders are stored as 133 * in the 'old' key of the $result array. 134 * 135 * When no items are found in 'new' the copy mechanism should fall back 136 * the 'old' list. 137 * 138 * @author Andreas Gohr <andi@splitbrain.org> 139 * @param arrayref $result - results are stored here 140 * @param string $base - the temp directory where the package was unpacked to 141 * @param string $dir - a subdirectory. do not set. used by recursion 142 * @return bool - false on error 143 */ 144 function find_folders(&$result,$base,$dir=''){ 145 $dh = @opendir("$base/$dir"); 146 if(!$dh) return false; 147 while (false !== ($f = readdir($dh))) { 148 if ($f == '.' || $f == '..' || $f == 'tmp') continue; 149 150 if(!is_dir("$base/$dir/$f")){ 151 // it's a file -> check for config 152 if($f == 'plugin.info.txt'){ 153 $info = array(); 154 $info['type'] = 'plugin'; 155 $info['tmp'] = "$base/$dir"; 156 $conf = confToHash("$base/$dir/$f"); 157 $info['base'] = utf8_basename($conf['base']); 158 if(!$info['base']) $info['base'] = utf8_basename("$base/$dir"); 159 $result['new'][] = $info; 160 }elseif($f == 'template.info.txt'){ 161 $info = array(); 162 $info['type'] = 'template'; 163 $info['tmp'] = "$base/$dir"; 164 $conf = confToHash("$base/$dir/$f"); 165 $info['base'] = utf8_basename($conf['base']); 166 if(!$info['base']) $info['base'] = utf8_basename("$base/$dir"); 167 $result['new'][] = $info; 168 } 169 }else{ 170 // it's a directory -> add to dir list for old method, then recurse 171 if(!$dir){ 172 $info = array(); 173 $info['type'] = 'plugin'; 174 $info['tmp'] = "$base/$dir/$f"; 175 $info['base'] = $f; 176 $result['old'][] = $info; 177 } 178 $this->find_folders($result,$base,"$dir/$f"); 179 } 180 } 181 closedir($dh); 182 return true; 183 } 184 185 186 /** 187 * Decompress a given file to the given target directory 188 * 189 * Determines the compression type from the file extension 190 */ 191 function decompress($file, $target) { 192 global $conf; 193 194 // decompression library doesn't like target folders ending in "/" 195 if (substr($target, -1) == "/") $target = substr($target, 0, -1); 196 197 $ext = $this->guess_archive($file); 198 if (in_array($ext, array('tar','bz','gz'))) { 199 switch($ext){ 200 case 'bz': 201 $compress_type = Tar::COMPRESS_BZIP; 202 break; 203 case 'gz': 204 $compress_type = Tar::COMPRESS_GZIP; 205 break; 206 default: 207 $compress_type = Tar::COMPRESS_NONE; 208 } 209 210 $tar = new Tar(); 211 try { 212 $tar->open($file, $compress_type); 213 $tar->extract($target); 214 return true; 215 }catch(Exception $e){ 216 if($conf['allowdebug']){ 217 msg('Tar Error: '.$e->getMessage().' ['.$e->getFile().':'.$e->getLine().']',-1); 218 } 219 return false; 220 } 221 } else if ($ext == 'zip') { 222 223 $zip = new ZipLib(); 224 $ok = $zip->Extract($file, $target); 225 226 // FIXME sort something out for handling zip error messages meaningfully 227 return ($ok==-1?false:true); 228 229 } 230 231 // unsupported file type 232 return false; 233 } 234 235 /** 236 * Determine the archive type of the given file 237 * 238 * Reads the first magic bytes of the given file for content type guessing, 239 * if neither bz, gz or zip are recognized, tar is assumed. 240 * 241 * @author Andreas Gohr <andi@splitbrain.org> 242 * @returns boolean|string false if the file can't be read, otherwise an "extension" 243 */ 244 function guess_archive($file){ 245 $fh = fopen($file,'rb'); 246 if(!$fh) return false; 247 $magic = fread($fh,5); 248 fclose($fh); 249 250 if(strpos($magic,"\x42\x5a") === 0) return 'bz'; 251 if(strpos($magic,"\x1f\x8b") === 0) return 'gz'; 252 if(strpos($magic,"\x50\x4b\x03\x04") === 0) return 'zip'; 253 return 'tar'; 254 } 255 256 /** 257 * Copy with recursive sub-directory support 258 */ 259 function dircopy($src, $dst) { 260 global $conf; 261 262 if (is_dir($src)) { 263 if (!$dh = @opendir($src)) return false; 264 265 if ($ok = io_mkdir_p($dst)) { 266 while ($ok && (false !== ($f = readdir($dh)))) { 267 if ($f == '..' || $f == '.') continue; 268 $ok = $this->dircopy("$src/$f", "$dst/$f"); 269 } 270 } 271 272 closedir($dh); 273 return $ok; 274 275 } else { 276 $exists = @file_exists($dst); 277 278 if (!@copy($src,$dst)) return false; 279 if (!$exists && !empty($conf['fperm'])) chmod($dst, $conf['fperm']); 280 @touch($dst,filemtime($src)); 281 } 282 283 return true; 284 } 285 286 287 } 288
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sun Jan 19 03:00:05 2014 | Cross-referenced by PHPXref 0.7 |