[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/plugin/classes/ -> ap_download.class.php (source)

   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  


Generated: Sun Jan 19 03:00:05 2014 Cross-referenced by PHPXref 0.7