<?php
/**
 * @package linea21.loader
 * @author Simon Georget <simon@linea21.com>
 * @version $id SVN
 * @access public
 * @license http://opensource.org/licenses/gpl-3.0.html
 */
ob_start();
@set_time_limit(0);

error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors',1);
ini_set("track_errors", 1);

// defines
define('SITE_LINEA_URL', 'https://www.linea21.com');
define('USER_AGENT', 'Linea21 - Loader/0.4 (https://www.linea21.com)');
define('REFERER', $_SERVER["HTTP_HOST"].' Linea21 - Loader/0.4');
define('ZIP_FILE', '_tmp.zip');
define('BASE_PATH', dirname(__FILE__).'/');
define('END_LINE', "<br />");
define('PERFORM_TEST', true);
// TARGET_URL is set later - do not uncomment the following line
// U_L is defined later

# localized input
$lang = array(
		'en' => array(
                'already_installed' => '<em class="b">Linea21 seems to be already installed.</em>',
				'pre-requisites' => 'pre-requisites',
                'connection_failed' => 'Unable to connect to <em>%s</em>.',
                'OK' => '<em class="g">OK</em>',
                'not_OK' => '<em class="b">not OK</em>',
                'php_version' => 'PHP version >= 7.3',
                'is_writable' => 'Folder is writable',
				'simplexml_ext' => 'SimpleXML extension',
				'gd_ext' => 'GD extension',
				'xml_ext' => 'XML extension',
				'libxml_ext' => 'LibXML extension',
				'mbstring_ext' => 'mbstring extension',
				'mysqli_ext' => 'MySQLi extension',
				'zip_ext' => 'ZIP extension',
                'curl_ext' => 'cURL extension',
				'check_not_ok' => 'Sorry, settings do not allow the Loader to run correctly.',
                'dl_latest' => 'Downloading latest stable version',
                'dl_from' => 'Downloading from',
                'curl_error_no' => 'cURL error number',
				'curl_error_msg' => 'cURL error message',
                'zip_extract' => 'Extracting <em>%s</em> to <em>%s</em>',
				'del_msg' => 'Deleting <em>%s</em>',
                'succeed' => '<em class="g">succeed</em>',
				'failed' => '<em class="b">failed</em>',
                'end_up' => ' <em class="b">The automatic installation ended up. Please, change current settings or download Linea21 manually.</em>',
                'delete_loader' => 'Do not forget to delete <em>loader.php</em> file.',
                'go_on' => 'Téléchargement terminé, poursuivre l\'installation !',
                'errors' => 'error(s)'
),
        'fr' => array(
                'already_installed' => '<em class="b">Linea21 semble déjà installé.</em>',
				'pre-requisites' => 'Pré-requis',
                'connection_failed' => 'Connexion à <em>%s</em> impossible.',
                'OK' => '<em class="g">OK</em>',
                'not_OK' => '<em class="b">non OK</em>',
                'php_version' => 'PHP version >= 7.3',
                'is_writable' => 'Permissions en écriture sur le dossier',
				'simplexml_ext' => 'extension SimpleXML',
				'gd_ext' => 'extension GD',
				'xml_ext' => 'extension XML',
				'libxml_ext' => 'extension LibXML',
				'mbstring_ext' => 'extension MBstring',
				'mysqli_ext' => 'extension MySQLi',
				'zip_ext' => 'extension ZIP',
                'curl_ext' => 'extension cURL',
				'check_not_ok' => 'Desolé, la configuration actuelle ne permet pas de lancer le Loader.',
                'dl_latest' => 'Téléchargement de la dernière version stable',
                'dl_from' => 'Téléchargement depuis',
                'curl_error_no' => 'erreur cURL numéro',
				'curl_error_msg' => 'message d\'erreur cURL',
                'zip_extract' => 'Extraction de <em>%s</em> vers <em>%s</em>',
				'del_msg' => 'Suppression de <em>%s</em>',
                'succeed' => '<em class="g">succès</em>',
				'failed' => '<em class="b">échec</em>',
                'end_up' => ' <em class="b">L\'installation automatique a été stoppée. Veuillez modifier vos paramètres ou installer Linea21 manuellement.</em>',
                'delete_loader' => 'N\'oubliez pas de supprimer le fichier <em>loader.php</em>.',
                'go_on' => 'Téléchargement terminé, poursuivre l\'installation !',
                'errors' => 'erreur(s)'
)
);

$language = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2));
if(!in_array($language, array_keys($lang))) $language = 'en';
define('U_L', $language);
$check = true;

// display localized message
function _t($var) {
  global $lang;

  return $lang[U_L][$var];
}

function rmLoader() {
	
	$js = "<script>
			var el = document.querySelector( '.lds-ripple' );
			el.parentNode.removeChild( el );
		</script>";
	
	echo $js;
}

// buffer flush
function fl() {
  @ob_end_flush();
  @ob_flush();
  @flush();
  @ob_start();
}

// check if given extension is loaded
function check_ext($ext) {
  global $check;

  if (!extension_loaded($ext)) {
    $check = false;
    return _t('not_OK');
  } else {
    return _t('OK');
  }
}
// check PHP version
function check_php() {
	global $check;
	
  if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
    return _t('OK'). ' ('.PHP_VERSION.')';
  } else {
	  $check = false;
    return _t('not_OK'). ' ('.PHP_VERSION.')';
  }
}

// check writable file/folder
function check_writable() {
  global $check;

  if (!is_writable(__DIR__)) {
    $check = false;
    return _t('not_OK');
  } else {
    return _t('OK');
  }
}

# from https://www.php.net/manual/en/ziparchive.extractto.php#116353
# permet de supprimer des dossiers de l'arborescence. Ici : 'linea21'
  class my_ZipArchive extends ZipArchive
  {
    public function extractSubdirTo($destination, $subdir)
    {
      $errors = array();

      // Prepare dirs
      $destination = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $destination);
      $subdir = str_replace(array("/", "\\"), "/", $subdir);

      if (substr($destination, mb_strlen(DIRECTORY_SEPARATOR, "UTF-8") * -1) != DIRECTORY_SEPARATOR)
        $destination .= DIRECTORY_SEPARATOR;

      if (substr($subdir, -1) != "/")
        $subdir .= "/";

      // Extract files
      for ($i = 0; $i < $this->numFiles; $i++)
      {
        $filename = $this->getNameIndex($i);

        if (substr($filename, 0, mb_strlen($subdir, "UTF-8")) == $subdir)
        {
          $relativePath = substr($filename, mb_strlen($subdir, "UTF-8"));
          $relativePath = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $relativePath);

          if (mb_strlen($relativePath, "UTF-8") > 0)
          {
            if (substr($filename, -1) == "/")  // Directory
            {
              // New dir
              if (!is_dir($destination . $relativePath))
                if (!@mkdir($destination . $relativePath, 0755, true))
                  $errors[$i] = $filename;
            }
            else
            {
              if (dirname($relativePath) != ".")
              {
                if (!is_dir($destination . dirname($relativePath)))
                {
                  // New dir (for file)
                  @mkdir($destination . dirname($relativePath), 0755, true);
                }
              }

              // New file
              if (@file_put_contents($destination . $relativePath, $this->getFromIndex($i)) === false)
                $errors[$i] = $filename;
            }
          }
        }
      }

      return $errors;
    }
  }


?>
<!DOCTYPE html>
<html class="no-js" lang="<?php echo U_L; ?>">
<head>
<title><?php echo USER_AGENT; ?></title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<style type='text/css'>
body {
	background-color: #003440;
	color: #ececec;
	margin: 5% 20%;
	font-family: Verdana, Arial, Sans, sans-serif;
}

a {
	color: #B32CD9;
	text-decoration: none;
}

a:hover {
	color: #D073EA;
	text-decoration: underline;
}

a.button {
	background-color: #B3D92C;
	text-decoration: none;
	padding: 1em 1.5em;
	border-radius: 4px;
	text-transform: uppercase;
	font-weight: bold;
	color: #242631;
	margin: 1em 0;
	display: inline-block;

}
a.button:hover {
	text-decoration: none;
	color: #08161a;
}

em.g {
	color: #68aff7;
	font-style: normal;
	font-weight:bold;
}

em.b {
	color: #c65252;
	font-style: normal;
	font-weight:bold;
}

h2 {
	color: ##5aa0b0;
	margin-bottom: 0;
	margin-top: 1.3em;
	font-size: 120%;
}

h1 {
	color: #b3d92c;
	margin: 0;
	font-size: 130%;
}

.n-delete {
	font-size: 0.85em;
	color: #b3d92c;
}

/* Debut loading */
.lds-ripple {
  display: inline-block;
  position: relative;
  width: 80px;
  height: 80px;
}
.lds-ripple div {
  position: absolute;
  border: 4px solid #fff;
  opacity: 1;
  border-radius: 50%;
  animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
.lds-ripple div:nth-child(2) {
  animation-delay: -0.5s;
}
@keyframes lds-ripple {
  0% {
    top: 36px;
    left: 36px;
    width: 0;
    height: 0;
    opacity: 0;
  }
  4.9% {
    top: 36px;
    left: 36px;
    width: 0;
    height: 0;
    opacity: 0;
  }
  5% {
    top: 36px;
    left: 36px;
    width: 0;
    height: 0;
    opacity: 1;
  }
  100% {
    top: 0px;
    left: 0px;
    width: 72px;
    height: 72px;
    opacity: 0;
  }
}
/* FIN loading */
</style>
</head>
<body>
<h1><?php echo USER_AGENT; ?></h1>

<div style="width:100%;text-align:center;margin:1em 0">
<div class="lds-ripple"><div></div><div></div></div>
</div>


<?php
### Step 0
if(file_exists('./config/config.ini')) {
	rmLoader();
	die(_t('already_installed'));
}


### Step 1
?>
<?php if(PERFORM_TEST == true) { ?>
<h2><?php echo _t('pre-requisites'); ?></h2>

<?php
echo _t('php_version'). ' : ' .check_php().END_LINE;
echo _t('mysqli_ext'). ' : ' . check_ext('mysqli').END_LINE;
echo _t('gd_ext'). ' : ' . check_ext('gd').END_LINE;
echo _t('xml_ext'). ' : ' . check_ext('xml').END_LINE;
echo _t('libxml_ext'). ' : ' . check_ext('libxml').END_LINE;
echo _t('simplexml_ext'). ' : ' . check_ext('simplexml').END_LINE;
echo _t('mbstring_ext'). ' : ' . check_ext('mbstring').END_LINE;
echo _t('zip_ext'). ' : ' . check_ext('zip').END_LINE;
echo _t('curl_ext'). ' : ' . check_ext('curl').END_LINE;
echo _t('is_writable'). ' : ' . check_writable().END_LINE;

if($check === false) {
	rmLoader();
	die (_t('check_not_ok'));
}
fl();
} // PERFORM_TEST end

?>

<?php

### Step 2
// Get the latest stable version link (zip format)
if(!@$xml=simplexml_load_file(SITE_LINEA_URL.'/linea21-version-check.php')){
  rmLoader();
  die( _t('connection_failed'). _t('end_up'));
} else   {
  if(! defined('TARGET_URL')) define('TARGET_URL', $xml->zipfile);
}
?>

<h2><?php echo _t('dl_latest'); ?></h2>
<?php
echo _t('dl_from'). ' <em>'. TARGET_URL.'</em>';
fl();
// cURL request
$fp = fopen(ZIP_FILE, "w");
$h = curl_init();
curl_setopt($h, CURLOPT_USERAGENT, USER_AGENT);
curl_setopt($h, CURLOPT_URL,TARGET_URL);
curl_setopt($h, CURLOPT_FAILONERROR, true);
curl_setopt($h, CURLOPT_HEADER,0);
curl_setopt($h, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($h, CURLOPT_AUTOREFERER, false);
curl_setopt($h, CURLOPT_REFERER, REFERER);
curl_setopt($h, CURLOPT_TIMEOUT, 1000);
curl_setopt($h, CURLOPT_FILE, $fp);

$curl_res = curl_exec($h);

if (!$curl_res) {
  echo ' : '.  _t('failed').END_LINE;
  echo '<p class="b">';
  echo  _t('curl_error_no'). ' : ' .curl_errno($h).END_LINE;
  echo  _t('curl_error_msg'). ' : ' . curl_error($h);
  echo '</p>';
  rmLoader();
  die(_t('end_up'));
} else {
  echo ' : '.  _t('succeed').END_LINE;
}
curl_close($h);
fclose($fp);

fl();



### Step 3
### Extracting zip file and cleaning
echo '<em>'.ZIP_FILE . '</em> : chmod ';
echo @chmod(ZIP_FILE, 0777) == true ? _t('succeed').END_LINE : _t('failed').END_LINE;

echo sprintf(_t('zip_extract'), ZIP_FILE, BASE_PATH). ' ';
fl();

$zip = new my_ZipArchive();
  if ($zip->open(ZIP_FILE) === TRUE)
  {
    $errors = $zip->extractSubdirTo("./", "linea21/");
    $zip->close();   
    echo _t('succeed').END_LINE;
    echo ' [' . _t('errors') . ' : ' . count($errors) . '] : ';
  }
  else {
    echo _t('failed').END_LINE;
    
  }

fl();

// deleting old files and ZIP archive)
// echo sprintf(_t('del_msg').' : ', BASE_PATH.'linea21');
// if(@rmdir(BASE_PATH.'linea21')) echo _t('succeed').END_LINE; else echo _t('failed').END_LINE;
echo sprintf(_t('del_msg').' : ', ZIP_FILE);
if(@unlink(ZIP_FILE)) echo _t('succeed').END_LINE; else echo _t('failed').END_LINE;

exec ("chmod -R 0755 " . dirname($_SERVER['SCRIPT_FILENAME']));

### Step 4
### Follow up on DB Install and set-up
?>
<p><a href="./install/install.php" class="button"><?php echo _t('go_on'); ?></a></p>
<p class="info n-delete"><?php echo _t('delete_loader'); ?></p>
<?php rmLoader(); ?>
</body>
</html>
<?php ob_end_flush(); ?>