source: extensions/autoupdate/autoupdate.php @ 4080

Last change on this file since 4080 was 4032, checked in by patdenice, 15 years ago

[Plugin Autoupdate]
Add timeout to retrieve last version on piwigo server.

File size: 7.0 KB
Line 
1<?php
2
3/* Fetch remote function with timeout */
4function autoupdate_fetchRemote($src, &$dest, $timeout=0, $user_agent='Piwigo', $step=0)
5{
6  // Try to retrieve data from local file?
7  if (!url_is_remote($src))
8  {
9    $content = @file_get_contents($src);
10    if ($content !== false)
11    {
12      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
13      return true;
14    }
15    else
16    {
17      return false;
18    }
19  }
20
21  // After 3 redirections, return false
22  if ($step > 3) return false;
23
24  // Initialize $dest
25  is_resource($dest) or $dest = '';
26
27  // Try curl to read remote file
28  if (function_exists('curl_init'))
29  {
30    $ch = @curl_init();
31    @curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
32    @curl_setopt($ch, CURLOPT_URL, $src);
33    @curl_setopt($ch, CURLOPT_HEADER, 1);
34    @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
35    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
36    $content = @curl_exec($ch);
37    $header_length = @curl_getinfo($ch, CURLINFO_HEADER_SIZE);
38    $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
39    @curl_close($content);
40    if ($content !== false and $status >= 200 and $status < 400)
41    {
42      if (preg_match('/Location:\s+?(.+)/', substr($content, 0, $header_length), $m))
43      {
44        return autoupdate_fetchRemote($m[1], $dest, $user_agent, $step+1);
45      }
46      $content = substr($content, $header_length);
47      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
48      return true;
49    }
50  }
51
52  // Try file_get_contents to read remote file
53  if (ini_get('allow_url_fopen'))
54  {
55    $opts['http'] = array('timeout' => $timeout);
56    $ctx = stream_context_create($opts);
57    $content = @file_get_contents($src, 0, $ctx);
58    if ($content !== false)
59    {
60      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
61      return true;
62    }
63  }
64
65  return false;
66}
67
68function autoupdate_deltree($path)
69{
70  if (is_dir($path))
71  {
72    $fh = opendir($path);
73    while ($file = readdir($fh))
74    {
75      if ($file != '.' and $file != '..')
76      {
77        $pathfile = $path . '/' . $file;
78        if (is_dir($pathfile))
79        {
80          autoupdate_deltree($pathfile);
81        }
82        else
83        {
84          @unlink($pathfile);
85        }
86      }
87    }
88    closedir($fh);
89    return @rmdir($path);
90  }
91}
92
93function check_version_for_autoupdate($version=PHPWG_VERSION)
94{
95  global $conf, $header_notes;
96
97  if (preg_match('/(\d+\.\d+)\.(\d+)/', $version, $matches) and @autoupdate_fetchRemote(PHPWG_URL.'/download/latest_version', $result, 1))
98  {
99    $lines = @explode("\r\n", $result);
100    $new_version = trim($lines[1]);
101    $new_branch = preg_replace('/(\d+\.\d+)\.\d+/', '$1', $new_version);
102    $actual_branch = $matches[1];
103    $update_to =  $actual_branch . '.' . ($matches[2]+1);
104
105    if (version_compare($version, $new_version) < 0
106      and $actual_branch == $new_branch)
107    {
108      $path = $conf['local_data_dir'].'/autoupdate/';
109      $code = $version.'_to_'.$update_to;
110      $filename = $path.$version.'_to_'.$update_to.'.zip';
111      mkgetdir($path);
112
113      if (!file_exists($filename) or !filesize($filename))
114      {
115        $zip = @fopen($filename, 'w+');
116        @autoupdate_fetchRemote(PHPWG_URL.'/download/dlcounter.php?code='.str_replace(array('.', '_'), '', $code), $zip);
117        @fclose($zip);
118      }
119
120      if (file_exists($filename) and filesize($filename))
121      {
122        if (isset($_GET['autoupdate']) and preg_match('/\d+\.\d+\.\d+_to_'.preg_quote($version).'/', $_GET['autoupdate']))
123        {
124          redirect('admin.php?autoupdate='.$code);
125        }
126        else
127        {
128          array_push($header_notes,
129            '<p>'.l10n('A new version of Piwigo is available.').'<br>',
130            '<a href="admin.php?autoupdate='.$code.'" onClick="return confirm(\''.l10n('autoupdate_alert').'\');">'.l10n('Click here to upgrade automatically').'</a></p>'
131          );
132        }
133      }
134    }
135  }
136}
137
138load_language('plugin.lang', dirname(__FILE__).'/');
139
140if (isset($_GET['autoupdate']))
141{
142  if ($_GET['autoupdate'] == 'success')
143  {
144    array_push($page['infos'], sprintf(l10n('autoupdate_success'), PHPWG_VERSION));
145  }
146  elseif ($file = $conf['local_data_dir'].'/autoupdate/'.$_GET['autoupdate'].'.zip' and file_exists($file))
147  {
148    include_once(PHPWG_ROOT_PATH.'admin/include/pclzip.lib.php');
149    $zip = new PclZip($file);
150    if ($result = $zip->extract(PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
151                                PCLZIP_OPT_REMOVE_PATH, $_GET['autoupdate'],
152                                PCLZIP_OPT_SET_CHMOD, 0755,
153                                PCLZIP_OPT_REPLACE_NEWER))
154    {
155      //Check if all files were extracted
156      $error = '';
157      foreach($result as $extract)
158      {
159        if (!in_array($extract['status'], array('ok', 'filtered', 'already_a_directory')))
160        {
161          // Try to change chmod and extract
162          if (@chmod(PHPWG_ROOT_PATH.$extract['filename'], 0777)
163            and ($res = $zip->extract(PCLZIP_OPT_BY_NAME, $_GET['autoupdate'].'/'.$extract['filename'],
164                                      PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
165                                      PCLZIP_OPT_REMOVE_PATH, $_GET['autoupdate'],
166                                      PCLZIP_OPT_SET_CHMOD, 0755,
167                                      PCLZIP_OPT_REPLACE_NEWER))
168            and isset($res[0]['status'])
169            and $res[0]['status'] == 'ok')
170          {
171            continue;
172          }
173          else
174          {
175            $error .= $extract['filename'].': '.$extract['status']."\n";
176          }
177        }
178      }
179
180      if (empty($error))
181      {
182        if (file_exists(PHPWG_ROOT_PATH.'obsolete.list')
183          and $old_files = file(PHPWG_ROOT_PATH.'obsolete.list', FILE_IGNORE_NEW_LINES)
184          and !empty($old_files))
185        {
186          array_push($old_files, 'obsolete.list');
187          foreach($old_files as $old_file)
188          {
189            $path = PHPWG_ROOT_PATH.$old_file;
190            if (is_file($path))
191            {
192              @unlink($path);
193            }
194            elseif (is_dir($path))
195            {
196              autoupdate_deltree($path);
197            }
198          }
199        }
200        if (preg_match('/\d+\.\d+\.\d+_to_(\d+\.\d+\.\d+)/', $_GET['autoupdate'], $matches))
201        {
202          check_version_for_autoupdate($matches[1]);
203        }
204        autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
205        invalidate_user_cache(true);
206        $template->delete_compiled_templates();
207        redirect('admin.php?autoupdate=success');
208      }
209      else
210      {
211        file_put_contents($conf['local_data_dir'].'/autoupdate/log_error.txt', $error);
212        $relative_path = trim(str_replace(dirname(dirname(dirname(__FILE__))), '', $conf['local_data_dir']), '/\\');
213        array_push($page['errors'], sprintf(l10n('autoupdate_extract_fail'), PHPWG_ROOT_PATH.$relative_path.'/autoupdate/log_error.txt'));
214      }
215    }
216    else
217    {
218      autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
219      array_push($page['errors'], l10n('autoupdate_fail'));
220    }
221  }
222  else
223  {
224    array_push($page['errors'], l10n('autoupdate_fail'));
225  }
226}
227else
228{
229  check_version_for_autoupdate();
230}
231
232?>
Note: See TracBrowser for help on using the repository browser.