source: trunk/admin/include/updates.class.php @ 28169

Last change on this file since 28169 was 28169, checked in by flop25, 11 years ago

TakeATour replace c13y_upgrade ; c13y_upgrade not activated after upgrade
adding TakeATour files
less margin-top in no_photo_yet.tpl

File size: 14.4 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
25
26class updates
27{
28  var $types = array();
29  var $plugins;
30  var $themes;
31  var $languages;
32  var $missing = array();
33  var $default_plugins = array();
34  var $default_themes = array();
35  var $default_languages = array();
36  var $merged_extensions = array();
37  var $merged_extension_url = 'http://piwigo.org/download/merged_extensions.txt';
38
39  function __construct($page='updates')
40  {
41    $this->types = array('plugins', 'themes', 'languages');
42
43    if (in_array($page, $this->types))
44    {
45      $this->types = array($page);
46    }
47    $this->default_themes = array('clear', 'dark', 'Sylvia', 'elegant');
48    $this->default_plugins = array('admin_multi_view', 'TakeATour', 'language_switch', 'LocalFilesEditor');
49
50    foreach ($this->types as $type)
51    {
52      include_once(PHPWG_ROOT_PATH.'admin/include/'.$type.'.class.php');
53      $this->$type = new $type();
54    }
55  }
56
57  static function check_piwigo_upgrade()
58  {
59    $_SESSION['need_update'] = null;
60
61    if (preg_match('/(\d+\.\d+)\.(\d+)/', PHPWG_VERSION, $matches)
62      and @fetchRemote(PHPWG_URL.'/download/all_versions.php?rand='.md5(uniqid(rand(), true)), $result))
63    {
64      $all_versions = @explode("\n", $result);
65      $new_version = trim($all_versions[0]);
66      $_SESSION['need_update'] = version_compare(PHPWG_VERSION, $new_version, '<');
67    }
68  }
69
70  function get_server_extensions($version=PHPWG_VERSION)
71  {
72    global $user;
73
74    $get_data = array(
75      'format' => 'php',
76    );
77
78    // Retrieve PEM versions
79    $versions_to_check = array();
80    $url = PEM_URL . '/api/get_version_list.php';
81    if (fetchRemote($url, $result, $get_data) and $pem_versions = @unserialize($result))
82    {
83      if (!preg_match('/^\d+\.\d+\.\d+$/', $version))
84      {
85        $version = $pem_versions[0]['name'];
86      }
87      $branch = get_branch_from_version($version);
88      foreach ($pem_versions as $pem_version)
89      {
90        if (strpos($pem_version['name'], $branch) === 0)
91        {
92          $versions_to_check[] = $pem_version['id'];
93        }
94      }
95    }
96    if (empty($versions_to_check))
97    {
98      return false;
99    }
100
101    // Extensions to check
102    $ext_to_check = array();
103    foreach ($this->types as $type)
104    {
105      $fs = 'fs_'.$type;
106      foreach ($this->$type->$fs as $ext)
107      {
108        if (isset($ext['extension']))
109        {
110          $ext_to_check[$ext['extension']] = $type;
111        }
112      }
113    }
114
115    // Retrieve PEM plugins infos
116    $url = PEM_URL . '/api/get_revision_list.php';
117    $get_data = array_merge($get_data, array(
118      'last_revision_only' => 'true',
119      'version' => implode(',', $versions_to_check),
120      'lang' => substr($user['language'], 0, 2),
121      'get_nb_downloads' => 'true',
122      )
123    );
124
125    $post_data = array();
126    if (!empty($ext_to_check))
127    {
128      $post_data['extension_include'] = implode(',', array_keys($ext_to_check));
129    }
130
131    if (fetchRemote($url, $result, $get_data, $post_data))
132    {
133      $pem_exts = @unserialize($result);
134      if (!is_array($pem_exts))
135      {
136        return false;
137      }
138      foreach ($pem_exts as $ext)
139      {
140        if (isset($ext_to_check[$ext['extension_id']]))
141        {
142          $server = 'server_'.$ext_to_check[$ext['extension_id']];
143          $this->$ext_to_check[$ext['extension_id']]->$server += array($ext['extension_id'] => $ext);
144          unset($ext_to_check[$ext['extension_id']]);
145        }
146      }
147      $this->check_missing_extensions($ext_to_check);
148      return true;
149    }
150    return false;
151  }
152
153  // Check all extensions upgrades
154  function check_extensions()
155  {
156    global $conf;
157
158    if (!$this->get_server_extensions())
159    {
160      return false;
161    }
162
163    $_SESSION['extensions_need_update'] = array();
164
165    foreach ($this->types as $type)
166    {
167      $fs = 'fs_'.$type;
168      $server = 'server_'.$type;
169      $server_ext = $this->$type->$server;
170      $fs_ext = $this->$type->$fs;
171
172      $ignore_list = array();
173      $need_upgrade = array();
174
175      foreach($fs_ext as $ext_id => $fs_ext)
176      {
177        if (isset($fs_ext['extension']) and isset($server_ext[$fs_ext['extension']]))
178        {
179          $ext_info = $server_ext[$fs_ext['extension']];
180
181          if (!safe_version_compare($fs_ext['version'], $ext_info['revision_name'], '>='))
182          {
183            if (in_array($ext_id, $conf['updates_ignored'][$type]))
184            {
185              $ignore_list[] = $ext_id;
186            }
187            else
188            {
189              $_SESSION['extensions_need_update'][$type][$ext_id] = $ext_info['revision_name'];
190            }
191          }
192        }
193      }
194      $conf['updates_ignored'][$type] = $ignore_list;
195    }
196    conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored'])));
197  }
198
199  // Check if extension have been upgraded since last check
200  function check_updated_extensions()
201  {
202    foreach ($this->types as $type)
203    {
204      if (!empty($_SESSION['extensions_need_update'][$type]))
205      {
206        $fs = 'fs_'.$type;
207        foreach($this->$type->$fs as $ext_id => $fs_ext)
208        {
209          if (isset($_SESSION['extensions_need_update'][$type][$ext_id])
210            and safe_version_compare($fs_ext['version'], $_SESSION['extensions_need_update'][$type][$ext_id], '>='))
211          {
212            // Extension have been upgraded
213            $this->check_extensions();
214            break;
215          }
216        }
217      }
218    }
219  }
220
221  function check_missing_extensions($missing)
222  {
223    foreach ($missing as $id => $type)
224    {
225      $fs = 'fs_'.$type;
226      $default = 'default_'.$type;
227      foreach ($this->$type->$fs as $ext_id => $ext)
228      {
229        if (isset($ext['extension']) and $id == $ext['extension']
230          and !in_array($ext_id, $this->$default)
231          and !in_array($ext['extension'], $this->merged_extensions))
232        {
233          $this->missing[$type][] = $ext;
234          break;
235        }
236      }
237    }
238  }
239
240  function get_merged_extensions($version)
241  {
242    if (fetchRemote($this->merged_extension_url, $result))
243    {
244      $rows = explode("\n", $result);
245      foreach ($rows as $row)
246      {
247        if (preg_match('/^(\d+\.\d+): *(.*)$/', $row, $match))
248        {
249          if (version_compare($version, $match[1], '>='))
250          {
251            $extensions = explode(',', trim($match[2]));
252            $this->merged_extensions = array_merge($this->merged_extensions, $extensions);
253          }
254        }
255      }
256    }
257  }
258
259  static function process_obsolete_list($file)
260  {
261    if (file_exists(PHPWG_ROOT_PATH.$file)
262      and $old_files = file(PHPWG_ROOT_PATH.$file, FILE_IGNORE_NEW_LINES)
263      and !empty($old_files))
264    {
265      $old_files[] = $file;
266      foreach($old_files as $old_file)
267      {
268        $path = PHPWG_ROOT_PATH.$old_file;
269        if (is_file($path))
270        {
271          @unlink($path);
272        }
273        elseif (is_dir($path))
274        {
275          deltree($path, PHPWG_ROOT_PATH.'_trash');
276        }
277      }
278    }
279  }
280
281  static function dump_database($include_history=false)
282  {
283    global $page, $conf, $cfgBase;
284
285    if (version_compare(PHPWG_VERSION, '2.1', '<'))
286    {
287      $conf['db_base'] = $cfgBase;
288    }
289
290    include(PHPWG_ROOT_PATH.'admin/include/mysqldump.php');
291
292    $path = PHPWG_ROOT_PATH.$conf['data_location'].'update';
293
294    if (@mkgetdir($path)
295      and ($backupFile = tempnam($path, 'sql'))
296      and ($dumper = new MySQLDump($conf['db_base'],$backupFile,false,false)))
297    {
298      foreach (get_defined_constants() as $constant => $value)
299      {
300        if (preg_match('/_TABLE$/', $constant))
301        {
302          $dumper->getTableStructure($value);
303          if ($constant == 'HISTORY_TABLE' and !$include_history)
304          {
305            continue;
306          }
307          $dumper->getTableData($value);
308        }
309      }
310    }
311
312    if (@filesize($backupFile))
313    {
314      $http_headers = array(
315        'Content-Length: '.@filesize($backupFile),
316        'Content-Type: text/x-sql',
317        'Content-Disposition: attachment; filename="database.sql";',
318        'Content-Transfer-Encoding: binary',
319        );
320
321      foreach ($http_headers as $header) {
322        header($header);
323      }
324
325      @readfile($backupFile);
326      deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
327      exit();
328    }
329    else
330    {
331      $page['errors'][] = l10n('Unable to dump database.');
332    }
333  }
334
335  static function upgrade_to($upgrade_to, &$step, $check_current_version=true)
336  {
337    global $page, $conf, $template;
338
339    if ($check_current_version and !version_compare($upgrade_to, PHPWG_VERSION, '>'))
340    {
341      redirect(get_root_url().'admin.php?page=plugin-'.basename(dirname(__FILE__)));
342    }
343
344    if ($step == 2)
345    {
346      preg_match('/(\d+\.\d+)\.(\d+)/', PHPWG_VERSION, $matches);
347      $code =  $matches[1].'.x_to_'.$upgrade_to;
348      $dl_code = str_replace(array('.', '_'), '', $code);
349      $remove_path = $code;
350      $obsolete_list = 'obsolete.list';
351    }
352    else
353    {
354      $code = $upgrade_to;
355      $dl_code = $code;
356      $remove_path = version_compare($code, '2.0.8', '>=') ? 'piwigo' : 'piwigo-'.$code;
357      $obsolete_list = PHPWG_ROOT_PATH.'install/obsolete.list';
358    }
359
360    if (empty($page['errors']))
361    {
362      $path = PHPWG_ROOT_PATH.$conf['data_location'].'update';
363      $filename = $path.'/'.$code.'.zip';
364      @mkgetdir($path);
365
366      $chunk_num = 0;
367      $end = false;
368      $zip = @fopen($filename, 'w');
369
370      while (!$end)
371      {
372        $chunk_num++;
373        if (@fetchRemote(PHPWG_URL.'/download/dlcounter.php?code='.$dl_code.'&chunk_num='.$chunk_num, $result)
374          and $input = @unserialize($result))
375        {
376          if (0 == $input['remaining'])
377          {
378            $end = true;
379          }
380          @fwrite($zip, base64_decode($input['data']));
381        }
382        else
383        {
384          $end = true;
385        }
386      }
387      @fclose($zip);
388
389      if (@filesize($filename))
390      {
391        $zip = new PclZip($filename);
392        if ($result = $zip->extract(PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
393                                    PCLZIP_OPT_REMOVE_PATH, $remove_path,
394                                    PCLZIP_OPT_SET_CHMOD, 0755,
395                                    PCLZIP_OPT_REPLACE_NEWER))
396        {
397          //Check if all files were extracted
398          $error = '';
399          foreach($result as $extract)
400          {
401            if (!in_array($extract['status'], array('ok', 'filtered', 'already_a_directory')))
402            {
403              // Try to change chmod and extract
404              if (@chmod(PHPWG_ROOT_PATH.$extract['filename'], 0777)
405                and ($res = $zip->extract(PCLZIP_OPT_BY_NAME, $remove_path.'/'.$extract['filename'],
406                                          PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
407                                          PCLZIP_OPT_REMOVE_PATH, $remove_path,
408                                          PCLZIP_OPT_SET_CHMOD, 0755,
409                                          PCLZIP_OPT_REPLACE_NEWER))
410                and isset($res[0]['status'])
411                and $res[0]['status'] == 'ok')
412              {
413                continue;
414              }
415              else
416              {
417                $error .= $extract['filename'].': '.$extract['status']."\n";
418              }
419            }
420          }
421
422          if (empty($error))
423          {
424            self::process_obsolete_list($obsolete_list);
425            deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
426            invalidate_user_cache(true);
427            $template->delete_compiled_templates();
428            unset($_SESSION['need_update']);
429            if ($step == 2)
430            {
431              $page['infos'][] = l10n('Update Complete');
432              $page['infos'][] = $upgrade_to;
433              $step = -1;
434            }
435            else
436            {
437              redirect(PHPWG_ROOT_PATH.'upgrade.php?now=');
438            }
439          }
440          else
441          {
442            file_put_contents(PHPWG_ROOT_PATH.$conf['data_location'].'update/log_error.txt', $error);
443           
444            $page['errors'][] = l10n(
445              'An error has occured during extract. Please check files permissions of your piwigo installation.<br><a href="%s">Click here to show log error</a>.',
446              get_root_url().$conf['data_location'].'update/log_error.txt'
447              );
448          }
449        }
450        else
451        {
452          deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
453          $page['errors'][] = l10n('An error has occured during upgrade.');
454        }
455      }
456      else
457      {
458        $page['errors'][] = l10n('Piwigo cannot retrieve upgrade file from server');
459      }
460    }
461  }
462}
463
464?>
Note: See TracBrowser for help on using the repository browser.