source: extensions/netinstall/trunk/piwigo-netinstall.php @ 31936

Last change on this file since 31936 was 31936, checked in by plg, 6 years ago

Change required PHP version to 5.3.0

No longer tries to configure PHP 5 with htaccess (this feature may come back for PHP 7 later)

File size: 15.3 KB
Line 
1<?php
2# -- BEGIN LICENSE BLOCK ----------------------------------
3#
4# This file is part of Piwigo.
5#
6# Copyright (c) 2003-2008 Olivier Meunier and contributors
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK ------------------------------------
12
13// +-----------------------------------------------------------------------+
14// |                              Configuration                            |
15// +-----------------------------------------------------------------------+
16
17define('DC_LOADER_SERVICE','http://piwigo.org/download/netinstall/');
18define('DC_LOADER_ARCHIVE','http://piwigo.org/download/dlcounter.php?code=latest');
19define('REQUIRED_PHP_VERSION', '5.6.31');
20
21$available_languages = array(
22  'cs_CZ' => 'Česky [CZ]',
23  'da_DK' => 'Dansk [DK]',
24  'de_DE' => 'Deutch [DE]',
25  'el_GR' => 'Ελληνικά [GR]',
26  'en_UK' => 'English [UK]',
27  'es_ES' => 'Español [ES]',
28  'fa_IR' => 'پارسی [IR]',
29  'fr_FR' => 'Français [FR]',
30  'gl_ES' => 'Galego [ES]',
31  'hu_HU' => 'Magyar [HU]',
32  'it_IT' => 'Italiano [IT]',
33  'lv_LV' => 'Latviešu [LV]',
34  'nb_NO' => 'Norwegian [NO]',
35  'nl_NL' => 'Nederlands [NL]',
36  'pl_PL' => 'Polski [PL]',
37  'pt_BR' => 'Brasil [BR]',
38  'pt_PT' => 'Português [PT]',
39  'ru_RU' => 'Русский [RU]',
40  'sk_SK' => 'Slovensky [SK]',
41  'tr_TR' => 'Türkçe [TR]',
42  'uk_UA' => 'Українська [UA]',
43  'zh_CN' => '简体中文 [CN]',
44);
45
46$url_subdomain_for_language = array(
47  'pt_BR' => 'br',
48  'da_DK' => 'da',
49  'de_DE' => 'de',
50  'es_ES' => 'es',
51  'fr_FR' => 'fr',
52  'it_IT' => 'it',
53  'hu_HU' => 'hu',
54  'nl_NL' => 'nl',
55  'pl_PL' => 'pl',
56  'tr_TR' => 'tr',
57  'ru_RU' => 'ru',
58  'zh_CN' => 'cn',
59  );
60
61// +-----------------------------------------------------------------------+
62
63error_reporting(E_ALL & ~E_NOTICE);
64
65getLanguage();
66
67$step = !empty($_REQUEST['step']) ? (integer)$_REQUEST['step'] : 1;
68$got_php5 = version_compare(PHP_VERSION, REQUIRED_PHP_VERSION, '>=');
69if (!$got_php5 && $step != 2)
70{
71  $step = 1;
72}
73
74function l10n($str)
75{
76  global $lang;
77
78  return isset($lang[$str]) ? $lang[$str] : $str;
79}
80
81function fetchRemote($src,&$dest,$step=0)
82{
83  if ($step > 3)
84  {
85    return false;
86  }
87
88  // Try curl to read remote file
89  if (function_exists('curl_init') && function_exists('curl_exec'))
90  {
91    $ch = @curl_init(); 
92    @curl_setopt($ch, CURLOPT_URL, $src); 
93    @curl_setopt($ch, CURLOPT_HEADER, 0); 
94    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
95    @curl_setopt($ch, CURLOPT_USERAGENT, 'Piwigo Net Install'); 
96    $content = @curl_exec($ch);
97    @curl_close($ch);
98    if ($content !== false)
99    {
100      write_dest($content, $dest);
101      return true;
102    }
103  }
104
105  // Try file_get_contents to read remote file
106  if ((boolean)ini_get('allow_url_fopen'))
107  {
108    $content = @file_get_contents($src);
109    if ($content !== false)
110    {
111      write_dest($content, $dest);
112      return true;
113    }
114  }
115 
116  if (!function_exists('fsockopen'))
117  {
118    return false;
119  }
120
121  // Try fsockopen to read remote file
122  $src = parse_url($src);
123  $host = $src['host'];
124  $path = $src['path'];
125 
126  if (($s = @fsockopen($host,80,$errno,$errstr,5)) === false)
127  {
128    return false;
129  }
130
131  fwrite($s,
132    'GET '.$path." HTTP/1.0\r\n"
133    .'Host: '.$host."\r\n"
134    ."User-Agent: Piwigo Net Install\r\n"
135    ."Accept: text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*\r\n"
136    ."\r\n"
137  );
138
139  $i = 0;
140  $in_content = false;
141  while (!feof($s))
142  {
143    $line = fgets($s,4096);
144
145    if (rtrim($line,"\r\n") == '' && !$in_content)
146    {
147      $in_content = true;
148      $i++;
149      continue;
150    }
151    if ($i == 0)
152    {
153      if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/',rtrim($line,"\r\n"), $m))
154      {
155        fclose($s);
156        return false;
157      }
158      $status = (integer) $m[2];
159      if ($status < 200 || $status >= 400)
160      {
161        fclose($s);
162        return false;
163      }
164    }
165    if (!$in_content)
166    {
167      if (preg_match('/Location:\s+?(.+)$/',rtrim($line,"\r\n"),$m))
168      {
169        fclose($s);
170        return fetchRemote(trim($m[1]),$dest,$step+1);
171      }
172      $i++;
173      continue;
174    }
175    write_dest($line, $dest);
176    $i++;
177  }
178  fclose($s);
179  return true;
180}
181
182function write_dest($str, &$dest)
183{
184  if (is_resource($dest))
185  {
186    fwrite($dest, $str);
187  }
188  else
189  {
190    $dest .= $str;
191  }
192}
193
194function getLanguage()
195{
196  global $lang, $available_languages;
197
198  if (isset($_GET['language']) and isset($available_languages[$_GET['language']]))
199  {
200    $language = $_GET['language'];
201  }
202  else
203  {
204    $language = 'en_UK';
205    // Try to get browser language
206    foreach ($available_languages as $language_code => $language_name)
207    {
208      if (substr($language_code,0,2) == @substr($_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2))
209      {
210        $language = $language_code;
211        break;
212      }
213    }
214  }
215  // Retrieve traductions
216  $lang = array();
217  if (fetchRemote(DC_LOADER_SERVICE.'language/'.$language.'/loader.lang.txt', $code))
218  {
219    @eval($code);
220    define('DC_LOADER_LANG', $language);
221  }
222}
223
224function getLocation()
225{
226  $server_name = explode(':',$_SERVER['HTTP_HOST']);
227  $server_name = $server_name[0];
228  if ($_SERVER['SERVER_PORT'] == '443')
229  {
230    $scheme = 'https';
231    $port = '';
232  }
233  elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
234  {
235    $scheme = 'https';
236    $port = ($_SERVER['SERVER_PORT'] != '443') ? ':'.$_SERVER['SERVER_PORT'] : '';
237  }
238  else
239  {
240    $scheme = 'http';
241    $port = ($_SERVER['SERVER_PORT'] != '80') ? ':'.$_SERVER['SERVER_PORT'] : '';
242  }
243  $loc = preg_replace('#/$#','',str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])));
244
245  return $scheme.'://'.$server_name.$port.$loc.'/';
246}
247
248function openPage()
249{
250  header('Content-Type: text/html; charset=UTF-8');
251  echo
252  '<!DOCTYPE html>'."\n".
253  '<html lang="'.l10n('code').'" dir="'.l10n('direction').'">'."\n".
254  '<head>'."\n".
255  ' <meta charset="UTF-8" />'."\n".
256  ' <title>'.l10n('Piwigo NetInstall').'</title>'."\n".
257  ' <meta name="ROBOTS" content="NOARCHIVE,NOINDEX,NOFOLLOW" />'."\n".
258  ' <link rel="stylesheet" type="text/css" media="screen" href="'.DC_LOADER_SERVICE.'loader.css" />'."\n".
259  '</head>'."\n".
260  '<body>'."\n".
261  '<div id="theHeader"></div>'."\n".
262  '<div id="content">'."\n".
263  '<h2>'.l10n('Piwigo NetInstall').'</h2>'."\n";
264}
265
266function closePage()
267{
268  global $url_subdomain_for_language;
269
270  $prefix = '';
271  if (isset($url_subdomain_for_language[DC_LOADER_LANG]))
272  {
273    $prefix = $url_subdomain_for_language[DC_LOADER_LANG].'.';
274  }
275 
276  echo
277    '<div style="text-align:center">'.
278      sprintf(l10n('Need help ? Ask your question on <a href="%s">Piwigo message board</a>.'), 'http://'.$prefix.'piwigo.org/forum').
279    '</div>'."\n".
280  '</div>'."\n".
281  '</body>'."\n".
282  '</html>';
283}
284
285function initPHP5()
286{
287  $htaccess = dirname(__FILE__).'/.htaccess';
288  if (file_exists($htaccess)) {
289    if (!is_readable($htaccess) || !is_writable($htaccess))
290    {
291      return false;
292    }
293  }
294  $rawdatas = '';
295  if (!fetchRemote(DC_LOADER_SERVICE.'hosting.txt',$rawdatas))
296  {
297    return false;
298  }
299  $rawdatas = explode("\n",$rawdatas);
300  if (!($my_hostname = @gethostbyaddr($_SERVER['SERVER_ADDR'])))
301  {
302    return false;
303  }
304  $found = false;
305  foreach ($rawdatas as $line) {
306    list($name,$hostname,$rule) = explode('|',trim($line));
307    if (preg_match('!'.preg_quote($hostname).'$!',$my_hostname))
308    {
309      $found = $rule;
310      break;
311    }
312  }
313  if ($found) {
314    if (false !== ($fh = @fopen($htaccess,"ab")))
315    {
316      fwrite($fh,"\n".$found);
317      fclose($fh);
318      return true;
319    }
320  }
321  return false;
322}
323
324function cleanFiles()
325{
326  @unlink(dirname(__FILE__).'/pwg_files.php');
327  @unlink(dirname(__FILE__).'/pwg_unzip.php');
328  @unlink(dirname(__FILE__).'/piwigo-install.zip');
329}
330
331function grabFiles()
332{
333  $failed = true;
334  $lib_files = @fopen(dirname(__FILE__).'/pwg_files.php','wb');
335  $lib_unzip = @fopen(dirname(__FILE__).'/pwg_unzip.php','wb');
336  $dc_zip    = @fopen(dirname(__FILE__).'/piwigo-install.zip','wb');
337
338  if (!$lib_files || !$lib_unzip || !$dc_zip)
339  {
340    return false;
341  }
342
343  if (fetchRemote(DC_LOADER_SERVICE.'lib.files.txt',$lib_files))
344  {
345    if (fetchRemote(DC_LOADER_SERVICE.'class.unzip.txt',$lib_unzip))
346    {
347      if (fetchRemote(DC_LOADER_ARCHIVE.'',$dc_zip))
348      {
349        $failed = false;
350      }
351    }
352  }
353
354  fclose($lib_files);
355  fclose($lib_unzip);
356  fclose($dc_zip);
357
358  if ($failed)
359  {
360    cleanFiles();
361    return false;
362  }
363  return true;
364}
365
366function writeMessage($level,$title,$lines)
367{
368  if (empty($lines))
369  {
370    return;
371  }
372
373  echo 
374  '<div class="msg '.$level.'">'."\n".
375  '<h3>'.$title.'</h3>'."\n".
376  '<p>'."\n";
377  foreach ($lines as $line)
378  {
379    echo $line.'<br />'."\n";
380  }
381  echo '</p></div>'."\n";
382}
383
384function nextAction($label,$step,$more='')
385{
386  echo
387  '<form action="'.$_SERVER['SCRIPT_NAME'].'?language='.DC_LOADER_LANG.'" method="post">'."\n".
388  $more."\n".
389  '<p class="button"><input type="hidden" name="step" value="'.$step.'" />'."\n".
390  '<input type="hidden" name="lang" value="'.DC_LOADER_LANG.'" />'."\n".
391  '<input type="submit" name="submit" value="'.$label.'"/>'."\n".
392  '</p></form>'."\n";
393}
394
395
396if (!defined('DC_LOADER_LANG'))
397{
398  $lang['code'] = 'en';
399  $lang['direction'] = 'ltr';
400
401  // No traduction for this part because can't fetch!
402  openPage();
403  writeMessage('warning','Damnit!', array(
404    'Due to restrictions in your PHP configuration, NetInstall cannot get its job done.',
405    'Please see Piwigo documentation to perform a normal installation.',
406    'Really sorry for the inconvenience.'
407  ));
408  closePage();
409  exit;
410}
411
412switch ($step)
413{
414  case 1 :
415  {
416    openPage();
417    echo '<fieldset><legend>'.l10n('Welcome to NetInstall!').'</legend>'."\n";
418
419    // Show available languages
420    asort($available_languages);
421    echo
422    '<p class="language">'.l10n('Language').' &nbsp;'."\n".
423    '<select name="language" onchange="document.location = \''.basename(__FILE__).'?language=\'+this.options[this.selectedIndex].value;">'."\n";
424    foreach ($available_languages as $language_code => $language_name)
425    {
426      echo '<option label="'.$language_name.'" value="'.$language_code.'" '.($language_code == DC_LOADER_LANG ? 'selected="selected"' : '').'>'.$language_name.'</option>'."\n";
427    }
428    echo '</select>'."\n".'</p>'."\n";
429
430    echo
431    '<p>'.l10n('This tool is meant to retrieve the latest Piwigo archive and unzip it in your webspace.').'<br />'."\n".
432    l10n('Right after then, you will be redirect to the Piwigo Setup Wizard.').'</p>'."\n";
433
434    if (!is_writable(dirname(__FILE__)))
435    {
436      writeMessage('warning',l10n('Write access is needed'), array(
437        l10n('It looks like NetInstall wont be able to write in the current directory, and this is required to follow on.'),
438        l10n('Please try to change the permissions to allow write access, then reload this page by hitting the Refresh button.')
439      ));
440      nextAction(l10n('Refresh'),1);
441    }
442    elseif (!$got_php5)
443    {
444      writeMessage('notice',sprintf(l10n('PHP %s is required'), REQUIRED_PHP_VERSION), array(
445        sprintf(l10n('It appears your webhost is currently running PHP %s.'), PHP_VERSION),
446        // l10n('NetInstall may try to switch your configuration to PHP 5 by creating or modifying a .htaccess file.'),
447        // l10n('Note you can change your configuration by yourself and restart NetInstall after that.')
448      ));
449
450      // 2018-07-18 : Piwigo 2.9.4 is out and now requires PHP 5.3 instead of 5.2.
451      // I realize NetInstall has this procedure which try to force PHP 5 instead
452      // of PHP 4. This procedure has become useless in 2018. I comment it for now,
453      // because we may need it in a few years when PHP 7 will become mandatory.
454
455      // nextAction(l10n('Try to configure PHP 5'),2);
456    }
457    else
458    {
459      nextAction(l10n('Retrieve and unzip Piwigo'),3,
460        '<p class="destination" dir="ltr"><label for="destination">'.l10n('Destination:').'</label> '.
461        getLocation().
462        ' <input type="text" id="destination" name="destination" '.
463        'value="piwigo" size="15" maxlength="100" /></p>'
464      );
465    }
466    echo '</fieldset>';
467    closePage();
468    break;
469  }
470
471  case 2 :
472  {
473    if (!empty($_POST['submit']) && !$got_php5)
474    {
475      $got_php5 = initPHP5();
476    }
477    if ($got_php5)
478    {
479      header('Location: '.$_SERVER['SCRIPT_NAME'].'?step=1&language='.DC_LOADER_LANG);
480    }
481    else
482    {
483      openPage();
484      writeMessage('warning',l10n('Sorry!'),array(
485        l10n('NetInstall was not able to configure PHP 5.'),
486        l10n("You may referer to your hosting provider's support and see how you could switch to PHP 5 by yourself."),
487        l10n('Hope to see you back soon.')
488      ));
489      closePage();
490    }
491    break;
492  }
493
494  case 3 :
495  {
496    $msg = array(l10n('What are you doing here that way ?!'));
497    $text = '';
498    if (!empty($_POST['submit']) && isset($_POST['destination']))
499    {
500      $msg = array();
501      $dest = preg_replace('/[^A-Za-z0-9_\/-]/','',$_POST['destination']);
502      $dest = preg_replace('#/+#','/',$dest);
503     
504      if (file_exists(dirname(__FILE__).'/./'.$dest.'/include/mysql.inc.php') || file_exists(dirname(__FILE__).'/./'.$dest.'/include/default_config.inc.php'))
505      {
506        $msg[] = l10n('It seems like a previous Piwigo installation is still sitting in that space.');
507        $msg[] = l10n('You need to rename or remove it before we can go further...');
508      }
509      elseif (grabFiles())
510      {
511        $lib_files = dirname(__FILE__).'/pwg_files.php';
512        $lib_unzip = dirname(__FILE__).'/pwg_unzip.php';
513        $dc_zip    = dirname(__FILE__).'/piwigo-install.zip';
514        if (!file_exists($lib_files) || !file_exists($lib_unzip) || !file_exists($dc_zip))
515        {
516          $msg[] = l10n('Needed files are not present.');
517        }
518
519        require $lib_files;
520        require $lib_unzip;
521        $uz = new fileUnzip($dc_zip);
522        $files = $uz->getList();
523        if (!is_array($files) or count($files) == 0)
524        {
525          $msg[] = l10n('Invalid zip file.');
526        }
527        else
528        {
529          foreach ($files as $k => $v)
530          {
531            if ($v['is_dir'])
532            {
533              continue;
534            }
535          if (preg_match('#^[^/]*/_data#', $k))
536          {
537            continue;
538          }
539            $t = preg_replace('#^[^/]*/#','./'.$dest.'/',$k);
540            $uz->unzip($k,$t);
541          }
542        }
543        $uz->close;
544        unset($uz);
545
546        if (!is_dir(dirname(__FILE__).'/'.$dest))
547        {
548          $msg[] = l10n('It seems that the zip file was not extracted.');
549        }
550        else
551        {
552          # Remove files and self-destruction
553          cleanFiles();
554          unlink(__FILE__);
555
556          $redir = preg_replace('#/+#','/',str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])).'/'.$dest.'/install.php');
557
558          $text = '<fieldset><legend>'.l10n('Congratulations!').'</legend>'
559          .'<p>'.l10n('Everything went fine. You are now ready to start the installation procedure.').'</p>'
560          .'<form action="'.$redir.'" method="get"><p class="button">'
561          . '<input type="hidden" name="language" value="'.DC_LOADER_LANG.'">'
562          . '<input type="submit" value="'.l10n('Install Piwigo now').'" />'
563          . '</p></form>'
564          .'</fieldset>';
565        }
566      }
567      else
568      {
569        $msg[] = l10n('An error occurred while grabbing the necessary files to go on.');
570      }
571    }
572    openPage();
573    writeMessage('warning',l10n('Something went wrong...'),$msg);
574    echo $text;
575    closePage();
576    break;
577  }
578}
Note: See TracBrowser for help on using the repository browser.