Nathanwoodburn.github.io/install-astra.php

735 lines
66 KiB
PHP
Raw Normal View History

2021-08-30 15:06:36 +10:00
<?php
/*
* error_reporting(E_ALL);
* ini_set('display_errors', 1);
*/
if (function_exists("opcache_reset")) {
opcache_reset();
}
class Deploy
{
private $data_path;
private $websites;
private $response;
private $log;
private $log_count = 1;
private $installed = false;
function __construct()
{
$this->data_path = "astra-install.json";
$this->response = array(
'success' => false,
'msg' => "",
);
$this->log = "";
$this->run();
}
function __destruct()
{
//$this->print_log();
}
protected function log($msg)
{
$this->log .= "<p class='line'>" . $msg . "</p>\r\n";
$this->log_count++;
}
public function getLogs()
{
return $this->log;
}
public function getInstalled(){
return file_exists('astra/astra-inc.php') || $this->installed;
}
protected function print_log()
{
echo $this->log;
}
protected function respond($success, $msg = '')
{
$this->response['success'] = $success;
if (!empty($msg)) {
$this->response['msg'] = $msg;
}
header('Content-Type: application/json');
echo json_encode($this->response, JSON_PRETTY_PRINT);
exit;
}
protected function load_json()
{
if (file_exists($this->data_path)) {
$string = file_get_contents($this->data_path);
$json_data = json_decode($string, true);
}
if (!empty($json_data) && is_array($json_data)) {
return $json_data;
}
return array();
}
protected function save_json()
{
return true;
$saved = file_put_contents($this->data_path, json_encode($this->websites));
return is_int($saved);
}
public function is_astra_installed($path)
{
return file_exists($path . 'astra');
}
protected function clean_install($path)
{
$zip_path = $this->get_astra_zip_path($path);
unlink($zip_path);
$this->log('Deleting the ZIP file.');
return !file_exists($zip_path);
}
protected function do_install($path = '')
{
$key = 0;
$this->websites[$key]['installed_astra'] = FALSE;
if ($this->is_astra_installed($path)) {
$this->log("Astra already installed. Nothing to do! :)");
return $this->websites[$key];
}
$this->log("-----------");
$this->log("Installing for " . $_SERVER['HTTP_HOST']);
$function_name = "install_default";
if (method_exists($this, $function_name)) {
$installed = $this->$function_name($path);
if ($installed == true) {
$this->websites[$key]['installed_astra'] = TRUE;
$this->log("Installed for $path");
//$this->respond(true, 'Installed for ' . $website['user']);
} else {
$this->websites[$key]['installed_astra'] = FALSE;
$this->websites[$key]['reason_for_failure'] = $installed;
$this->log("Unable to install. Please email <a href='mailto:help@getastra.com'>help@getastra.com</a> if you need help");
//$this->respond(false, 'Unable to install for ' . $website['user']);
}
}
return $this->websites[$key];
}
protected function meets_requirements() {
if (!defined('PDO::ATTR_DRIVER_NAME')) {
$this->log('PDO Driver Missing. Please install or enable in cPanel.');
return FALSE;
}
if(!class_exists('ZipArchive')){
$this->log('ZipArchive Default Class is missing. Please install or enable in cPanel.');
return FALSE;
}
if (!extension_loaded('sqlite3')) {
$this->log('sqlite3 extension not loaded. Please install or enable in cPanel. <a href="https://www.getastra.com/kb/?s=sqlite" target="_blank" style="color: #fff!important;">Find installation guides here.</a>');
return FALSE;
}
$pdo_drivers = PDO::getAvailableDrivers();
if(!is_array($pdo_drivers) || !in_array('sqlite', $pdo_drivers)){
$this->log('pdo_sqlite extension not loaded. Please install or enable in cPanel. <a href="https://www.getastra.com/kb/?s=sqlite" target="_blank" style="color: #fff!important;">Find installation guides here.</a>');
}
return TRUE;
}
protected function is_astra_included_in_user_ini($file_path)
{
if (!file_exists($file_path)) {
return false;
}
$contents = file_get_contents($file_path);
if (strpos($contents, 'astra-inc') !== false) {
return true;
}
return false;
}
protected function update_user_ini($path, $astra_inc_path)
{
$path_user_ini = $path . '.user.ini';
if ($this->is_astra_included_in_user_ini($path_user_ini)) {
return true;
}
$file_content = "auto_prepend_file=$astra_inc_path\n\r";
$write = false;
if (!file_exists($path_user_ini)) {
$write = file_put_contents($path_user_ini, $file_content);
} else {
$old_contents = file_get_contents($path_user_ini);
$file_content .= "\r\n" . $old_contents;
$write = file_put_contents($path_user_ini, $file_content);
$this->log("Updated existing .user.ini");
}
return $write;
}
protected function install_default($path, $plugin_folder_path = '')
{
if (empty($plugin_folder_path)) {
$plugin_folder_path = $path;
}
$plugin_zip_path = $this->get_astra_zip_path($path);
$username = "";
if (file_exists($plugin_zip_path . 'astra')) {
$this->log("Astra is already installed");
return false;
}
if (file_exists($plugin_folder_path) && is_writable($plugin_folder_path)) {
if (!empty($plugin_zip_path) && file_exists($plugin_zip_path)) {
if ($this->is_valid_zip($plugin_zip_path)) {
$extracted = $this->extract_zip($plugin_zip_path, $plugin_folder_path);
if ($extracted) {
if ($this->update_user_ini($path, $plugin_folder_path . 'astra/astra-inc.php')) {
return true;
} else {
$this->log("Unable to update the .user.ini file for $path");
return false;
}
} else {
$this->log( "Unable to extract the ZIP.");
return false;
}
} else {
$this->log($this->response['msg']);
return false;
}
} else {
$this->log("Astra ZIP does (secure-*.zip) not exist.<br/>Can you please check?");
return false;
}
} else {
$this->log( "Folder does not exist or isn't writable ($plugin_folder_path)");
return false;
}
}
protected function get_astra_zip_path($path)
{
$matches = glob($path . 'secure-*.zip');
$file_name = "";
if (!empty($matches[0])) {
$file_name = str_replace("./", "/", $matches[0]);
}
//$this->log("ZIP file path: " . $file_name);
return $file_name;
}
protected function extract_zip($zip_path, $extract_to)
{
$zip = new ZipArchive;
if ($zip->open($zip_path) === TRUE) {
$extracted = $zip->extractTo($extract_to);
$zip->close();
return $extracted;
}
return FALSE;
}
protected function is_valid_zip($filename)
{
$zip = new ZipArchive;
$res = $zip->open($filename, ZipArchive::CHECKCONS);
if ($res !== TRUE) {
switch ($res) {
case ZipArchive::ER_NOZIP :
$ret = FALSE;
$this->response['msg'] = "Invalid ZIP - Not a zip archive";
case ZipArchive::ER_INCONS :
$ret = FALSE;
$this->response['msg'] = "Invalid ZIP - Consistency check failed";
case ZipArchive::ER_CRC :
$this->response['msg'] = "Invalid ZIP - Error with CRC";
$ret = FALSE;
default :
$this->response['msg'] = "Invalid ZIP - Checksum failed";
$ret = FALSE;
}
if ($ret) {
$zip->close();
}
return $ret;
} else {
return TRUE;
}
}
function run()
{
$path = getcwd() . "/";
$this->log("Path to be secured: " . $path);
$should_install = isset($_GET['complete']);
if ($should_install && $this->meets_requirements()) {
$website = $this->do_install($path);
if ($website['installed_astra'] === true) {
$this->clean_install($path);
$this->log('Deleting Installer');
$this->installed = true;
unlink(__FILE__);
}
}
}
}
$deploy = new Deploy();
$installed = $deploy->getInstalled();
$logs = $deploy->getLogs();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Astra Installer</title>
<style>
.text-center {
text-align: center;
}
.btn {
display: inline-block;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.btn-group-lg > .btn, .btn-lg {
padding: .5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: .3rem;
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
.btn-danger {
color: #fff;
background-color: #dc3545;
border-color: #dc3545;
}
.btn-success {
color: #fff;
background-image: linear-gradient(to right, #075fc9 0%, #363795 51%, #075fc9 100%);
transition: 0.5s;
background-size: 200% auto;
}
.btn-success:hover {
background-position: right center;
color: #fff;
}
.btn:not(:disabled):not(.disabled) {
cursor: pointer;
}
.btn-danger:hover {
color: #fff;
background-color: #c82333;
border-color: #bd2130;
}
.container {
height: 80vh;
position: relative;
}
.center {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.text-muted {
color: #6c757d !important;
}
.form-text {
display: block;
margin-top: .25rem;
}
.small, small {
font-size: 80%;
font-weight: 400;
}
.block {
display: block;
}
body {
/*background-color: #272727;*/
padding: 10px;
}
.fakeButtons {
height: 10px;
width: 10px;
border-radius: 50%;
border: 1px solid #000;
position: relative;
top: 6px;
left: 6px;
background-color: #ff3b47;
border-color: #9d252b;
display: inline-block;
}
.fakeMinimize {
left: 11px;
background-color: #ffc100;
border-color: #9d802c;
}
.fakeZoom {
left: 16px;
background-color: #00d742;
border-color: #049931;
}
.fakeMenu {
width: 550px;
box-sizing: border-box;
height: 25px;
background-color: #bbb;
margin: 0 auto;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.fakeScreen {
background-color: #151515;
box-sizing: border-box;
width: 550px;
margin: 0 auto;
padding: 20px;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
p {
/*
position: relative;
left: 50%;
margin-left: -8.5em;
*/
text-align: left;
font-size: 1.25em;
font-family: monospace;
white-space: normal;
/*overflow: hidden;*/
/*width: 0;*/
}
span {
color: #fff;
font-weight: bold;
}
.line {
color: #9CD9F0;
-webkit-animation: type .5s 1s steps(20, end) forwards;
-moz-animation: type .5s 1s steps(20, end) forwards;
-o-animation: type .5s 1s steps(20, end) forwards;
animation: type .5s 1s steps(20, end) forwards;
}
.cursor {
}
.line:nth-child(even) {
color: #9CD9F0;
-webkit-animation: type .5s 1s steps(20, end) forwards;
-moz-animation: type .5s 1s steps(20, end) forwards;
-o-animation: type .5s 1s steps(20, end) forwards;
animation: type .5s 1s steps(20, end) forwards;
}
.line:nth-child(odd) {
color: #CDEE69;
-webkit-animation: type .5s 4.25s steps(20, end) forwards;
-moz-animation: type .5s 4.25s steps(20, end) forwards;
-o-animation: type .5s 4.25s steps(20, end) forwards;
animation: type .5s 4.25s steps(20, end) forwards;
}
.line1 {
color: #9CD9F0;
-webkit-animation: type .5s 1s steps(20, end) forwards;
-moz-animation: type .5s 1s steps(20, end) forwards;
-o-animation: type .5s 1s steps(20, end) forwards;
animation: type .5s 1s steps(20, end) forwards;
}
.cursor1 {
-webkit-animation: blink 1s 2s 2 forwards;
-moz-animation: blink 1s 2s 2 forwards;
-o-animation: blink 1s 2s 2 forwards;
animation: blink 1s 2s 2 forwards;
}
.line2 {
color: #CDEE69;
-webkit-animation: type .5s 4.25s steps(20, end) forwards;
-moz-animation: type .5s 4.25s steps(20, end) forwards;
-o-animation: type .5s 4.25s steps(20, end) forwards;
animation: type .5s 4.25s steps(20, end) forwards;
}
.cursor2 {
-webkit-animation: blink 1s 5.25s 2 forwards;
-moz-animation: blink 1s 5.25s 2 forwards;
-o-animation: blink 1s 5.25s 2 forwards;
animation: blink 1s 5.25s 2 forwards;
}
.line3 {
color: #E09690;
-webkit-animation: type .5s 7.5s steps(20, end) forwards;
-moz-animation: type .5s 7.5s steps(20, end) forwards;
-o-animation: type .5s 7.5s steps(20, end) forwards;
animation: type .5s 7.5s steps(20, end) forwards;
}
.cursor3 {
-webkit-animation: blink 1s 8.5s 2 forwards;
-moz-animation: blink 1s 8.5s 2 forwards;
-o-animation: blink 1s 8.5s 2 forwards;
animation: blink 1s 8.5s 2 forwards;
}
.line4 {
color: #fff;
-webkit-animation: type .5s 10.75s steps(20, end) forwards;
-moz-animation: type .5s 10.75s steps(20, end) forwards;
-o-animation: type .5s 10.75s steps(20, end) forwards;
animation: type .5s 10.75s steps(20, end) forwards;
}
.cursor4 {
-webkit-animation: blink 1s 11.5s infinite;
-moz-animation: blink 1s 8.5s infinite;
-o-animation: blink 1s 8.5s infinite;
animation: blink 1s 8.5s infinite;
}
@-webkit-keyframes blink {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@-moz-keyframes blink {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@-o-keyframes blink {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes blink {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@-webkit-keyframes type {
to {
width: 27em;
}
}
@-moz-keyframes type {
to {
width: 27em;
}
}
@-o-keyframes type {
to {
width: 27em;
}
}
@keyframes type {
to {
width: 27em;
}
}
</style>
</head>
<body>
<div class="container">
<div class="center">
<div class="text-center">
<img style="height: 150px;" src="data:image/png;base64,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
<?php if (!empty(trim($logs))) { ?>
<div class=fakeMenu>
<div class="fakeButtons fakeClose"></div>
<div class="fakeButtons fakeMinimize"></div>
<div class="fakeButtons fakeZoom"></div>
</div>
<div class="fakeScreen">
<?php echo($logs); ?>
<p class="line4">><span class="cursor4">_</span></p>
</div>
<?php } ?>
<br/><br/>
<?php if(!$installed) { ?>
<form method="GET">
<input type="hidden" name="complete"/>
<input type="submit"
value="<?php echo !isset($_GET['complete']) ? "Complete Astra Installation" : "Retry Astra Installation" ?>"
class="btn btn-lg btn-submit btn-success"/>
<span class="text-muted small block form-text">PHP Version: <?php echo phpversion(); ?></span>
</form>
<?php } else { ?>
<h2 style="text-align: center; color: green; font-family: Trebuchet MS,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Tahoma,sans-serif; ">Installation complete!</h2>
<?php } ?>
</div>
</div>
</div>
</body>
</html>