source: extensions/autoupdate/branches/1.7/include/functions.inc.php @ 6206

Last change on this file since 6206 was 6206, checked in by patdenice, 14 years ago

Keep compatibility with php4 for branch 1.7

File size: 14.7 KB
Line 
1<?php
2
3if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
4
5function autoupdate_deltree($path, $move_to_trash=false)
6{
7  if (is_dir($path))
8  {
9    $fh = opendir($path);
10    while ($file = readdir($fh))
11    {
12      if ($file != '.' and $file != '..')
13      {
14        $pathfile = $path . '/' . $file;
15        if (is_dir($pathfile))
16        {
17          autoupdate_deltree($pathfile, $move_to_trash);
18        }
19        else
20        {
21          @unlink($pathfile);
22        }
23      }
24    }
25    closedir($fh);
26    if (@rmdir($path))
27    {
28      return true;
29    }
30    elseif ($move_to_trash)
31    {
32      $trash = PHPWG_ROOT_PATH.'_trash';
33      if (!is_dir($trash))
34      {
35        @mkgetdir($trash);
36      }
37      return @rename($path, $trash . '/'.md5(uniqid(rand(), true)));
38    }
39    else
40    {
41      return false;
42    }
43  }
44}
45
46function autoupdate_add_index($path)
47{
48  if (is_dir($path))
49  {
50    $fh = opendir($path);
51    while ($file = readdir($fh))
52    {
53      if ($file != '.' and $file != '..')
54      {
55        $pathfile = $path . '/' . $file;
56        if (is_dir($pathfile))
57        {
58          autoupdate_add_index($pathfile);
59        }
60      }
61    }
62    $fp = @fopen($path.'/index.php', 'w');
63    @fwrite($fp, AU_DEFAULT_INDEX);
64    @fclose($fp);
65    closedir($fh);
66  }
67}
68
69function process_obsolete_list($file)
70{
71  if (file_exists(PHPWG_ROOT_PATH.$file)
72    and $old_files = file(PHPWG_ROOT_PATH.$file, FILE_IGNORE_NEW_LINES)
73    and !empty($old_files))
74  {
75    array_push($old_files, $file);
76    foreach($old_files as $old_file)
77    {
78      $path = PHPWG_ROOT_PATH.$old_file;
79      if (is_file($path))
80      {
81        @unlink($path);
82      }
83      elseif (is_dir($path))
84      {
85        autoupdate_deltree($path, true);
86      }
87    }
88  }
89}
90
91function move_local_files($dir)
92{
93  global $page, $cfgBase, $cfgUser, $cfgPassword, $cfgHote, $prefixeTable;
94
95  if ((!is_dir($dir) and !mkdir($dir, 0777))
96    or (!is_dir($dir.'/config') and !mkdir($dir.'/config'))
97    or (!is_dir($dir.'/css') and !mkdir($dir.'/css'))
98    or (!is_dir($dir.'/language') and !mkdir($dir.'/language')))
99  {
100    autoupdate_deltree($dir);
101    array_push($page['errors'], l10n('Unable to write new local directory.'));
102    return;
103  }
104
105  // Add index.php
106  autoupdate_add_index($dir);
107
108  // mysql.inc.php
109  $file = PHPWG_ROOT_PATH.'include/mysql.inc.php';
110  if (is_readable($file))
111  {
112    $file_content = '<?php
113$conf[\'dblayer\'] = \'mysql\';
114$conf[\'db_base\'] = \''.$cfgBase.'\';
115$conf[\'db_user\'] = \''.$cfgUser.'\';
116$conf[\'db_password\'] = \''.$cfgPassword.'\';
117$conf[\'db_host\'] = \''.$cfgHote.'\';
118
119$prefixeTable = \''.$prefixeTable.'\';
120
121define(\'PHPWG_INSTALLED\', true);';
122    if (defined('PWG_CHARSET'))
123    {
124      $file_content.= '
125define(\'PWG_CHARSET\', \'utf-8\');
126define(\'DB_CHARSET\', \'utf8\');
127define(\'DB_COLLATE\', \'\');';
128    }
129    $file_content.= '
130?>';
131    $new_config_file = $dir.'/config/database.inc.php';
132
133    if (!($fp = @fopen($new_config_file, 'w'))
134      or !@fwrite($fp, $file_content)
135      or !@fclose($fp))
136    {
137      array_push($page['errors'], l10n('Unable to write new local directory.'));
138      return;
139    }
140    @chmod($new_config_file, 0755);
141  }
142
143  // config_local.inc.php
144  $file = PHPWG_ROOT_PATH.'include/config_local.inc.php';
145  if (is_readable($file))
146  {
147    copy($file, $dir.'/config/config.inc.php');
148    @chmod($file, 0755);
149  }
150
151  // languages
152  $language_dir = opendir(PHPWG_ROOT_PATH.'language');
153  while ($file = readdir($language_dir))
154  {
155    $path = PHPWG_ROOT_PATH.'language/'.$file;
156    if (!is_link($path) and is_dir($path) and is_readable($path.'/local.lang.php'))
157    {
158      $content = file_get_contents($path.'/local.lang.php');
159      $langdef = explode('.',$file);
160      if (count($langdef)>1)
161      {
162        $content = utf8_encode($content);
163      }
164      $filename = $dir.'/language/'.$langdef[0].'.lang.php';
165      $fp = @fopen($filename, 'w');
166      @fwrite($fp, $content);
167      @fclose($fp);
168      @chmod($filename, 0755);
169    }
170  }
171  closedir($language_dir);
172
173  // template-common/local-layout.css
174  $file = PHPWG_ROOT_PATH.'template-common/local-layout.css';
175  if (is_readable($file))
176  {
177    copy($file, $dir.'/css/rules.css');
178    @chmod($file, 0755);
179  }
180
181  // template/xxx/local-layout.css
182  $known_templates = array(
183    'yoga'     => 'default',
184    'floPure'  => 'Pure_default',
185    'floOs'    => 'OS_default',
186    'gally'    => 'gally-default',
187    'simple'   => 'simple',
188  );
189
190  foreach ($known_templates as $old_tpl => $new_tpl)
191  {
192    $file = PHPWG_ROOT_PATH.'template/'.$old_tpl.'/local-layout.css';
193    if (is_readable($file))
194    {
195      copy($file, $dir.'/css/'.$new_tpl.'-rules.css');
196      @chmod($file, 0755);
197    }
198  }
199}
200
201function autoupdate_save_template_dir()
202{
203  global $page, $conf;
204
205  $path = $conf['local_data_dir'].'/autoupdate';
206
207  if (mkgetdir($conf['local_data_dir'])
208    and mkgetdir($path)
209    and ($zip = tempnam($path, 'zip'))
210    and ($archive = new pclZip($zip))
211    and ($v_list = $archive->add(PHPWG_ROOT_PATH.'template', PCLZIP_OPT_REMOVE_PATH, PHPWG_ROOT_PATH))
212    and is_array($v_list)
213    and !empty($v_list))
214  {
215    $http_headers = array(
216      'Content-Length: '.@filesize($zip),
217      'Content-Type: application/zip',
218      'Content-Disposition: attachment; filename="template.zip";',
219      'Content-Transfer-Encoding: binary',
220      );
221
222    foreach ($http_headers as $header) {
223      header($header);
224    }
225
226    @readfile($zip);
227    autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
228    exit();
229  }
230  else
231  {
232    array_push($page['errors'], l10n('Unable to send template directory.'));
233  }
234}
235
236function autoupdate_dump_database()
237{
238  global $page, $conf, $cfgBase;
239
240  if (version_compare(PHPWG_VERSION, '2.1', '<'))
241  {
242    $conf['db_base'] = $cfgBase;
243  }
244
245  include(AUTOUPDATE_PATH.'include/mysqldump.php');
246
247  $path = $conf['local_data_dir'].'/autoupdate';
248
249  if (mkgetdir($conf['local_data_dir'])
250    and mkgetdir($path)
251    and ($backupFile = tempnam($path, 'sql'))
252    and ($dumper = new MySQLDump($conf['db_base'],$backupFile,false,false)))
253  {
254    foreach (get_defined_constants() as $constant => $value)
255    {
256      if (preg_match('/_TABLE$/', $constant))
257      {
258        $dumper->getTableStructure($value);
259
260        if ($constant == 'HISTORY_TABLE' and !isset($_POST['includeHistory']))
261        {
262          continue;
263        }
264
265        $dumper->getTableData($value);
266      }
267    }
268  }
269
270  if (@filesize($backupFile))
271  {
272    $http_headers = array(
273      'Content-Length: '.@filesize($backupFile),
274      'Content-Type: text/x-sql',
275      'Content-Disposition: attachment; filename="database.sql";',
276      'Content-Transfer-Encoding: binary',
277      );
278
279    foreach ($http_headers as $header) {
280      header($header);
281    }
282
283    @readfile($backupFile);
284    autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
285    exit();
286  }
287  else
288  {
289    array_push($page['errors'], l10n('Unable to dump database.'));
290  }
291}
292
293function autoupdate_upgrade_to($upgrade_to, &$step)
294{
295  global $page, $conf, $template;
296
297  if (!version_compare($_POST['upgrade_to'], PHPWG_VERSION, '>'))
298  {
299    redirect(get_admin_plugin_menu_link(AUTOUPDATE_PATH . '/autoupdate.php'));
300  }
301
302  if ($step == 2)
303  {
304    preg_match('/(\d+\.\d+)\.(\d+)/', PHPWG_VERSION, $matches);
305    $code =  $matches[1].'.x_to_'.$_POST['upgrade_to'];
306    $dl_code = str_replace(array('.', '_'), '', $code);
307    $remove_path = $code;
308    $obsolete_list = 'obsolete.list';
309  }
310  else
311  {
312    $code = $_POST['upgrade_to'];
313    $dl_code = $code;
314    $remove_path = version_compare($code, '2.0.8', '>=') ? 'piwigo' : 'piwigo-'.$code;
315    $obsolete_list = PHPWG_ROOT_PATH.'install/obsolete.list';
316
317    move_local_files(PHPWG_ROOT_PATH.'local');
318  }
319
320  if (empty($page['errors']))
321  {
322    $path = $conf['local_data_dir'].'/autoupdate';
323    $filename = $path.'/'.$code.'.zip';
324    mkgetdir($conf['local_data_dir']);
325    mkgetdir($path);
326
327    $chunk_num = 0;
328    $end = false;
329    $zip = @fopen($filename, 'w');
330    while (!$end)
331    {
332      $chunk_num++;
333      if (@fetchRemote('http://piwigo.org/download/dlcounter.php?code='.$dl_code.'&chunk_num='.$chunk_num, $result)
334        and $input = @unserialize($result))
335      {
336        if (0 == $input['remaining'])
337        {
338          $end = true;
339        }
340        @fwrite($zip, base64_decode($input['data']));
341      }
342      else
343      {
344        $end = true;
345      }
346    }
347    @fclose($zip);
348
349    if (@filesize($filename))
350    {
351      $zip = new PclZip($filename);
352      if ($result = $zip->extract(PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
353                                  PCLZIP_OPT_REMOVE_PATH, $remove_path,
354                                  PCLZIP_OPT_SET_CHMOD, 0755,
355                                  PCLZIP_OPT_REPLACE_NEWER))
356      {
357        //Check if all files were extracted
358        $error = '';
359        foreach($result as $extract)
360        {
361          if (!in_array($extract['status'], array('ok', 'filtered', 'already_a_directory')))
362          {
363            // Try to change chmod and extract
364            if (@chmod(PHPWG_ROOT_PATH.$extract['filename'], 0777)
365              and ($res = $zip->extract(PCLZIP_OPT_BY_NAME, $remove_path.'/'.$extract['filename'],
366                                        PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
367                                        PCLZIP_OPT_REMOVE_PATH, $remove_path,
368                                        PCLZIP_OPT_SET_CHMOD, 0755,
369                                        PCLZIP_OPT_REPLACE_NEWER))
370              and isset($res[0]['status'])
371              and $res[0]['status'] == 'ok')
372            {
373              continue;
374            }
375            else
376            {
377              $error .= $extract['filename'].': '.$extract['status']."\n";
378            }
379          }
380        }
381
382        if (empty($error))
383        {
384          process_obsolete_list($obsolete_list);
385          autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
386          invalidate_user_cache(true);
387          if ($step == 2)
388          {
389            array_push($page['infos'], sprintf(l10n('autoupdate_success'), $upgrade_to));
390            $step = 4;
391          }
392          else
393          {
394            redirect(PHPWG_ROOT_PATH.'upgrade.php?now=');
395          }
396        }
397        else
398        {
399          $logfile = @fopen($conf['local_data_dir'].'/autoupdate/log_error.txt', 'w');
400          @fwrite($logfile, $error);
401          @fclose($logfile);
402          $relative_path = trim(str_replace(dirname(dirname(dirname(dirname(__FILE__)))), '', $conf['local_data_dir']), '/\\');
403          array_push($page['errors'], sprintf(l10n('autoupdate_extract_fail'), PHPWG_ROOT_PATH.$relative_path.'/autoupdate/log_error.txt'));
404        }
405      }
406      else
407      {
408        autoupdate_deltree($conf['local_data_dir'].'/autoupdate');
409        array_push($page['errors'], l10n('autoupdate_fail'));
410      }
411    }
412    else
413    {
414      array_push($page['errors'], l10n('Piwigo cannot retrieve upgrade file from server'));
415    }
416  }
417}
418
419function is_webmaster($user_status = '')
420{
421  return is_autorize_status(ACCESS_WEBMASTER, $user_status);
422}
423
424/**
425 * Retrieve data from external URL
426 *
427 * @param string $src: URL
428 * @param global $dest: can be a file ressource or string
429 * @return bool
430 */
431function fetchRemote($src, &$dest, $user_agent='Piwigo', $step=0)
432{
433  // Try to retrieve data from local file?
434  if (!url_is_remote($src))
435  {
436    $content = @file_get_contents($src);
437    if ($content !== false)
438    {
439      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
440      return true;
441    }
442    else
443    {
444      return false;
445    }
446  }
447
448  // After 3 redirections, return false
449  if ($step > 3) return false;
450
451  // Initialize $dest
452  is_resource($dest) or $dest = '';
453
454  // Try curl to read remote file
455  if (function_exists('curl_init'))
456  {
457    $ch = @curl_init();
458    @curl_setopt($ch, CURLOPT_URL, $src);
459    @curl_setopt($ch, CURLOPT_HEADER, 1);
460    @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
461    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
462    $content = @curl_exec($ch);
463    $header_length = @curl_getinfo($ch, CURLINFO_HEADER_SIZE);
464    $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
465    @curl_close($ch);
466    if ($content !== false and $status >= 200 and $status < 400)
467    {
468      if (preg_match('/Location:\s+?(.+)/', substr($content, 0, $header_length), $m))
469      {
470        return fetchRemote($m[1], $dest, $user_agent, $step+1);
471      }
472      $content = substr($content, $header_length);
473      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
474      return true;
475    }
476  }
477
478  // Try file_get_contents to read remote file
479  if (ini_get('allow_url_fopen'))
480  {
481    $content = @file_get_contents($src);
482    if ($content !== false)
483    {
484      is_resource($dest) ? @fwrite($dest, $content) : $dest = $content;
485      return true;
486    }
487  }
488
489  // Try fsockopen to read remote file
490  $src = parse_url($src);
491  $host = $src['host'];
492  $path = isset($src['path']) ? $src['path'] : '/';
493  $path .= isset($src['query']) ? '?'.$src['query'] : '';
494
495  if (($s = @fsockopen($host,80,$errno,$errstr,5)) === false)
496  {
497    return false;
498  }
499
500  fwrite($s,
501    "GET ".$path." HTTP/1.0\r\n"
502    ."Host: ".$host."\r\n"
503    ."User-Agent: ".$user_agent."\r\n"
504    ."Accept: */*\r\n"
505    ."\r\n"
506  );
507
508  $i = 0;
509  $in_content = false;
510  while (!feof($s))
511  {
512    $line = fgets($s);
513
514    if (rtrim($line,"\r\n") == '' && !$in_content)
515    {
516      $in_content = true;
517      $i++;
518      continue;
519    }
520    if ($i == 0)
521    {
522      if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/',rtrim($line,"\r\n"), $m))
523      {
524        fclose($s);
525        return false;
526      }
527      $status = (integer) $m[2];
528      if ($status < 200 || $status >= 400)
529      {
530        fclose($s);
531        return false;
532      }
533    }
534    if (!$in_content)
535    {
536      if (preg_match('/Location:\s+?(.+)$/',rtrim($line,"\r\n"),$m))
537      {
538        fclose($s);
539        return fetchRemote(trim($m[1]),$dest,$user_agent,$step+1);
540      }
541      $i++;
542      continue;
543    }
544    is_resource($dest) ? @fwrite($dest, $line) : $dest .= $line;
545    $i++;
546  }
547  fclose($s);
548  return true;
549}
550
551define('MKGETDIR_NONE', 0);
552define('MKGETDIR_RECURSIVE', 1);
553define('MKGETDIR_DIE_ON_ERROR', 2);
554define('MKGETDIR_PROTECT_INDEX', 4);
555define('MKGETDIR_PROTECT_HTACCESS', 8);
556define('MKGETDIR_DEFAULT', 7);
557/**
558 * creates directory if not exists; ensures that directory is writable
559 * @param:
560 *  string $dir
561 *  int $flags combination of MKGETDIR_xxx
562 * @return bool false on error else true
563 */
564function mkgetdir($dir, $flags=MKGETDIR_DEFAULT)
565{
566  if ( !is_dir($dir) )
567  {
568    $umask = umask(0);
569    $mkd = @mkdir($dir, 0755 );
570    umask($umask);
571    if ($mkd==false)
572    {
573      !($flags&MKGETDIR_DIE_ON_ERROR) or die( "$dir ".l10n('no write access'));
574      return false;
575    }
576  }
577  if ( !is_writable($dir) )
578  {
579    !($flags&MKGETDIR_DIE_ON_ERROR) or die( "$dir ".l10n('no write access'));
580    return false;
581  }
582  return true;
583}
584
585define('AU_DEFAULT_INDEX', file_get_contents(AUTOUPDATE_PATH.'index.php'));
586?>
Note: See TracBrowser for help on using the repository browser.