cd ".dirname(__FILE__)."; php install_scj.php");
}
$cmdline = new prompt();
$tmp = phpversion();
$tmp = explode('.', $tmp);
// 5.6 and 7 = 5.6
// 7.1 up to 7.4 = 7.1
// 8.1 and up
/*
if ($tmp[0] == '5') {
$phpversion = 7;
} elseif ($tmp[0] == '7' and $tmp[1] == '0') {
$phpversion = 7;
} elseif ($tmp[0] == '7' and $tmp[1] > 1) {
$phpversion = 71;
} elseif ($tmp[0] == '8' ) {
$phpversion = 81;
} else die();
*/
if (PHP_MAJOR_VERSION == 5 or (PHP_MAJOR_VERSION == 7 and PHP_MINOR_VERSION == 0) ) {
$phpversion = 7;
} elseif (PHP_MAJOR_VERSION == 7 and PHP_MINOR_VERSION >= 1) {
$phpversion = 71;
} elseif (PHP_MAJOR_VERSION == 8 and PHP_MINOR_VERSION == 1) {
$phpversion = 81;
} elseif (PHP_MAJOR_VERSION == 8 and PHP_MINOR_VERSION == 2) {
$phpversion = 82;
} elseif (PHP_MAJOR_VERSION == 8) {
$phpversion = 81;
} else {
die("Unknown version of PHP, please, contact support " . PHP_MAJOR_VERSION . '.' . PHP_MAJOR_VERSION);
}
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
die("This version of PHP (".PHP_VERSION.") is too old. The script requires PHP 5.3 and up.");
} else echo "PHP version {$phpversion} \n";
if (!function_exists("imagecreatefromjpeg") or !function_exists("imagecreatetruecolor") or !function_exists( "imagejpeg" ) || !function_exists( "imagedestroy" ) ) die("PHP GD lib is NOT installed. Ask admin to install it.");
// if (!function_exists("ftp_connect")) die("PHP FTP lib is NOT installed. Ask admin to install it.");
if (!function_exists("mysqli_connect")) die("PHP MySQL lib is NOT installed. Ask admin to install it.");
if (!function_exists("fsockopen")) die("PHP net functions (fsockopen) is NOT installed. Ask admin to install it.");
if (!function_exists("session_start")) die("PHP Session support (session_start) is NOT installed. Ask admin to install it.");
if (!function_exists("exec")) die("PHP exec() function is NOT supported. Ask admin to install it.");
if (!function_exists("curl_init")) die("PHP curl_init() function is NOT supported. Ask admin to install it.");
$user = @exec('whoami');
if ($user == 'root') {
die("Please, DO NOT run install using root account. Install aborted.");
}
$scj_folder = (isset($params['scj_folder'])) ? $params['scj_folder'] : $cmdline->get("Folder name for script (default is scj): ");
if (!$scj_folder) $scj_folder = 'scj';
if (is_dir('./' . $scj_folder)) {
die("Folder {$scj_folder} already exists \n");
}
$test_eval = false;
@eval("\$test_eval=true;");
if (!$test_eval) die("PHP eval() function is NOT installed. Ask admin to install it.");
clearstatcache();
// todo
// if (is_dir('./' . $scj_folder)) die("Folder {$scj_folder} already exists. Rename or remove it and run install again.");
@mkdir('./' . $scj_folder);
if (!is_dir("./" . $scj_folder)) {
die ("Can not create {$scj_folder} folder, contact support \n");
}
$tmp = curl_get_file($install_source_url . "/filelist.php?php_version={$phpversion}");
if($tmp['info']['http_code'] != 200) {
die("Can not get filelist\n");
}
$files = unserialize($tmp['body']);
if (!is_array($files)) {
print_r($tmp);
die("Can not get filelist ({$tmp['info']['http_code']} {$turl}). Please, contact script author. ");
}
$scj_path = getcwd();
if (!$scj_path) {
die ("Can not get path to current folder __FILE__");
}
$scj_path .= '/'.$scj_folder.'/';
$scj_domain = (isset($params['domain'])) ? $params['domain'] : $cmdline->get("Type your domain (only domain ie site.com - NO WWW, NO HTTP) : ");
$admin_email = (isset($params['admin_email'])) ? $params['admin_email'] : $cmdline->get("Type your email (will be used as script admin email) : ");
if (isset($params['php_path'])) {
$php_path = $params['php_path'];
} elseif (PHP_BINARY) {
$php_path = PHP_BINARY;
} else $php_path = $cmdline->get("Type PATH to php (ask admin if you don't know) : ");
// locate mysql
if (@file_exists("/usr/bin/mysql")) {
$mysql_path = '/usr/bin/mysql';
} elseif (@file_exists("/usr/local/bin/mysql")) {
$mysql_path = '/usr/local/bin/mysql';
} else {
$mysql_path = ($params['mysql_path']) ? $params['mysql_path'] : $cmdline->get("Type PATH to Mysql binany (ask admin if you don't know) (for example /usr/bin/mysql) : ");
}
$tr = array();
$tr['htaccess'] = '.htaccess';
$tr['htpasswd'] = '.htpasswd';
echo "Downloading script files \n";
$rc = new RollingCurl("request_callback");
$rc->window_size = 50;
$update_file_folder = ($phpversion == 5) ? 'files' : ('files' . $phpversion);
$count = 0;
foreach ($files as $name => $size) {
$url = "{$cdn_install_source_url}/{$update_file_folder}/{$name}";
$GLOBALS['scj_update_files'][] = $url;
$request = new RollingCurlRequest($url, 'GET', '', '', array(), array('target_file' => './' . $scj_folder . '/' . $name));
$rc->add($request);
if (isset($params['debug'])) {
echo "req: $url \n";
}
$count++;
//if ($count > 1) break;
}
$rc->execute();
echo "\n Done \n";
$htaccess = 'DirectoryIndex index.php
AuthType Basic
AuthName "SCJ Admin Area"
AuthUserFile __PATH__/.htpasswd
require valid-user
';
if (!isset($params['admin_password'])) {
$passwd = '';
for ($i=0; $i < 10; $i++) $passwd .= chr(rand(97,122));
} else $passwd = $params['admin_password'];
$htpasswd = 'admin:' . password_hash($passwd, PASSWORD_DEFAULT);
$ht_deny = "deny from all\n";
file_put_contents($scj_folder . '/admin/.htaccess', $htaccess);
file_put_contents($scj_folder . '/admin/.htpasswd', $htpasswd);
file_put_contents($scj_folder . '/admin/files/.htaccess', $ht_deny);
file_put_contents($scj_folder . '/backup/.htaccess', $ht_deny);
file_put_contents($scj_folder . '/data/.htaccess', $ht_deny);
file_put_contents($scj_folder . '/logs/.htaccess', $ht_deny);
file_put_contents($scj_folder . '/cache/.htaccess', $ht_deny);
file_put_contents($scj_folder . '/includes/libs/.htaccess', $ht_deny);
$ht_list = array('top', 'top/tt', 'tmp', 'thumbs', 'rot_pages');
foreach ($ht_list as $z => $folder) {
if (!$f = fopen('./'.$scj_folder .'/' . $folder . '/.htaccess', 'w')) {
die("Can not open " . $folder . '/.htaccess for writing ');
}
fputs($f, "RemoveHandler .php .phtml .php3 .php4 .php5 .htm .html .shtml\nAddType text/html .php .phtml .php3 .php4 .php5 .htm .html .shtml\n");
fclose($f);
}
echo "Making config.php \n";
$tries = 0;
while (true) {
$tries++;
if ($tries > 3) die("Can not connect using this parameters " . print_r($params));
$mysql_host = (isset($params['mysql_host']) and $params['mysql_host']) ? $params['mysql_host'] : $cmdline->get("Mysql host (usually localhost): ");
$mysql_user = (isset($params['mysql_user']) and $params['mysql_user']) ? $params['mysql_user'] : $cmdline->get("Mysql username: ");
$mysql_pass = (isset($params['mysql_pass']) and $params['mysql_pass']) ? $params['mysql_pass'] : $cmdline->get("Mysql password: ");
$mysql_name = (isset($params['mysql_name']) and $params['mysql_name']) ? $params['mysql_name'] : $cmdline->get("Mysql DB name: ");
try {
if (!$link = mysqli_connect($mysql_host, $mysql_user, $mysql_pass, $mysql_name)) {
echo "Can not connect to mysql using this data, please try again or contact your admin \n";
$params['mysql_host'] = $params['mysql_user'] = $params['mysql_pass'] = $params['mysql_name'] = '';
continue;
}
} catch (Exception $e) {
echo "Can not connect to mysql using this data, please try again or contact your admin \n";
$params['mysql_host'] = $params['mysql_user'] = $params['mysql_pass'] = $params['mysql_name'] = '';
continue;
}
break;
}
// create config
$tr = array();
$tr['__DB_HOST__'] = $mysql_host;
$tr["__DB_USER__"] = $mysql_user;
$tr["__DB_PASSWORD__"] = $mysql_pass;
$tr["__DB_NAME__"] = $mysql_name;
$tr["__PHP_PATH__"] = $php_path;
$tr["__ADMIN_EMAIL__"] = $admin_email;
$tr["__PATH_TO_LOG__"] = $scj_path . 'logs/';
$config_text = file_get_contents("./{$scj_folder}/includes/config.php");
$config_text = strtr($config_text, $tr);
if (isset($mysql_charset) and $mysql_charset != '') $config_text .= "\n \$config['db_charset'] = '{$mysql_charset}'; \n\n";
if (!$f = fopen("./{$scj_folder}/includes/config.php", 'w')) {
die("Can not open {$scj_folder}/includes/config.php for writing, please contact support \n");
}
fputs($f, $config_text);
fclose($f);
//create htaccess
$config_text = file_get_contents("./{$scj_folder}/admin/.htaccess");
$config_text = str_replace('__PATH__', $scj_path . 'admin', $config_text);
if (!$f = fopen("./{$scj_folder}/admin/.htaccess", 'w')) {
die("Can not open {$scj_folder}/admin/.htaccess for writing, please contact support \n");
}
fputs($f, $config_text);
fclose($f);
// create common.php
$config_text = " $str) {
$str = trim($str);
if (!$str) continue;
$tmp = explode('=', $str);
$file_permissions[trim($tmp[0])] = trim($tmp[1]);
}
if (!is_array($file_permissions)) {
die('Can not load permission list');
}
foreach ($file_permissions as $file => $perm) {
if (!file_exists($scj_path . $file)) continue;
if (!chmod($scj_path . $file, octdec( (int) $perm) )) {
die("Can not set permission on {$scj_path}{$file}");
}
}
$cmd = "cd {$scj_folder}/admin; {$php_path} update.php";
`$cmd`;
echo "Add following to Crontab (note, if you are not going to use internal rotation you can skip line with rot.php) \n\n";
echo "#SmartCJ Pro at domain {$scj_domain}\n";
echo "*/1 * * * * cd {$scj_path}bin && env HTTP_HOST={$scj_domain} {$php_path} -q cron.php \n";
echo "*/1 * * * * cd {$scj_path}bin && env HTTP_HOST={$scj_domain} {$php_path} -q rotation.php \n";
//if (!$params['domain']) $mysql_name = $cmdline->get("\n\n Script Installation is done. Please, open http://{$scj_domain}/scj/admin/ in your browser. Your login is 'admin' and password is '{$passwd}'. Press Enter to continue. \n\n");
echo "\n\n Script Installation is done. Please, open http://{$scj_domain}/{$scj_folder}/admin/ in your browser. Your login is 'admin' and password is '{$passwd}'. \n\n";
@mail($admin_email, 'SmartCJ admin password', "Thank you for installing Smartcj at {$scj_domain}. Your login is admin and password is {$passwd} ");
echo "\rDone, everything's ok \n\n\n";
function request_callback($response, $info, $request) {
global $scj_update_files, $total_downloaded, $params, $rc;
if ($info['http_code'] != 200 ) {
//throw new Exception("Can not download file {$info['url']}");
$rc->add($request);
//throw new Exception("Can not download file {$info['url']} (code {$info['http_code']}) ");
print("Can not download file {$info['url']} (code {$info['http_code']}), try again .. \n");
return;
}
$total_downloaded++;
$percent = round($total_downloaded/count($scj_update_files)*100);
echo "\r" . $percent . "% downloaded ";
$save_path = $request->user_params['target_file'];
if (isset($params['debug'])) {
echo "save: {$save_path} \n";
}
$p = 0;
while ($p = strpos($save_path, '/', $p+1)) {
$dir = substr($save_path, 0, $p);
if (!is_dir($dir)) {
if (!mkdir($dir)) die("Can not create $dir");
}
}
if (!$f = fopen($save_path, 'w')) {
echo " NOTE !!! UPDATE IS NOT FINISHED !!! \n Script can not open {$save_path} for writing. Please, check permissions/file owner and run update again !!! \n";
throw new Exception("Can not save file ");
}
fputs($f, $response);
fclose($f);
}
class RollingCurlRequest {
public $url = false;
public $method = 'GET';
public $post_data = null;
public $headers = null;
public $options = null;
public $handle_id = null;
public $user_params = array();
/**
* @param string $url
* @param string $method
* @param $post_data
* @param $headers
* @param $options
* @return void
*/
function __construct($url, $method = "GET", $post_data = null, $headers = null, $options = null, $user_params = null) {
$this->url = $url;
$this->method = $method;
$this->post_data = $post_data;
$this->headers = $headers;
$this->options = $options;
$this->user_params = $user_params;
}
/**
* @return void
*/
public function __destruct() {
unset($this->url, $this->method, $this->post_data, $this->headers, $this->options);
}
}
/**
* RollingCurl custom exception
*/
class RollingCurlException extends Exception {
}
/**
* Class that holds a rolling queue of curl requests.
*
* @throws RollingCurlException
*/
class RollingCurl {
/**
* @var int
*
* Window size is the max number of simultaneous connections allowed.
*
* REMEMBER TO RESPECT THE SERVERS:
* Sending too many requests at one time can easily be perceived
* as a DOS attack. Increase this window_size if you are making requests
* to multiple servers or have permission from the receving server admins.
*/
private $window_size = 5;
/**
* @var float
*
* Timeout is the timeout used for curl_multi_select.
*/
private $timeout = 10;
private $max_download_size = 0;
/**
* @var string|array
*
* Callback function to be applied to each result.
*/
private $callback;
/**
* @var array
*
* Set your base options that you want to be used with EVERY request.
*/
protected $options = array(
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) SmartCJ',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
//CURLOPT_MAXREDIRS => 1
//CURLOPT_MAX_RECV_SPEED_LARGE => 10000
//CURLOPT_VERBOSE => true,
);
/**
* @var array
*/
private $headers = array();
/**
* @var Request[]
*
* The request queue
*/
private $requests = array();
/**
* @var RequestMap[]
*
* Maps handles to request indexes
*/
private $requestMap = array();
private $urlMap = array();
/**
* @param $callback
* Callback function to be applied to each result.
*
* Can be specified as 'my_callback_function'
* or array($object, 'my_callback_method').
*
* Function should take three parameters: $response, $info, $request.
* $response is response body, $info is additional curl info.
* $request is the original request
*
* @return void
*/
function __construct($callback = null) {
$this->callback = $callback;
}
/**
* @param string $name
* @return mixed
*/
public function __get($name) {
return (isset($this->{$name})) ? $this->{$name} : null;
}
/**
* @param string $name
* @param mixed $value
* @return bool
*/
public function __set($name, $value) {
// append the base options & headers
if ($name == "options" || $name == "headers") {
$this->{$name} = $value + $this->{$name};
} else {
$this->{$name} = $value;
}
return true;
}
/**
* Add a request to the request queue
*
* @param Request $request
* @return bool
*/
public function add($request) {
$this->requests[] = $request;
return true;
}
/**
* Create new Request and add it to the request queue
*
* @param string $url
* @param string $method
* @param $post_data
* @param $headers
* @param $options
* @return bool
*/
public function request($url, $method = "GET", $post_data = null, $headers = null, $options = null) {
$this->requests[] = new RollingCurlRequest($url, $method, $post_data, $headers, $options);
return true;
}
/**
* Perform GET request
*
* @param string $url
* @param $headers
* @param $options
* @return bool
*/
public function get($url, $headers = null, $options = null) {
return $this->request($url, "GET", null, $headers, $options);
}
/**
* Perform POST request
*
* @param string $url
* @param $post_data
* @param $headers
* @param $options
* @return bool
*/
public function post($url, $post_data = null, $headers = null, $options = null) {
return $this->request($url, "POST", $post_data, $headers, $options);
}
/**
* Execute processing
*
* @param int $window_size Max number of simultaneous connections
* @return string|bool
*/
public function execute($window_size = null) {
// rolling curl window must always be greater than 1
if (sizeof($this->requests) == 1) {
return $this->single_curl();
} else {
// start the rolling curl. window_size is the max number of simultaneous connections
return $this->rolling_curl($window_size);
}
}
/**
* Performs a single curl request
*
* @access private
* @return string
*/
private function single_curl() {
$ch = curl_init();
$request = array_shift($this->requests);
$options = $this->get_options($request);
curl_setopt_array($ch, $options);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
// it's not neccesary to set a callback for one-off requests
if ($this->callback) {
$callback = $this->callback;
if (is_callable($this->callback)) {
call_user_func($callback, $output, $info, $request);
}
}
else
return $output;
return true;
}
private function progress($resource, $downloadSize, $downloaded, $uploadSize, $uploaded) {
/*
echo " $resource, $downloadSize, $downloaded, $uploadSize, $uploaded, {$this->max_download_size} \n";
if ($downloadSize > $this->max_download_size) {
return 'test';
}
*/
if ($downloaded > $this->max_download_size) {
return false;
}
return true;
}
/**
* Performs multiple curl requests
*
* @access private
* @throws RollingCurlException
* @param int $window_size Max number of simultaneous connections
* @return bool
*/
private function rolling_curl($window_size = null) {
if ($window_size)
$this->window_size = $window_size;
// make sure the rolling window isn't greater than the # of urls
if (sizeof($this->requests) < $this->window_size)
$this->window_size = sizeof($this->requests);
if ($this->window_size < 2) {
throw new RollingCurlException("Window size must be greater than 1");
}
$master = curl_multi_init();
// start the first batch of requests
for ($i = 0; $i < $this->window_size; $i++) {
$ch = curl_init();
//var_dump($this->requests[$i]);
$options = $this->get_options($this->requests[$i]);
//print_r($options);
//exit;
if ($this->max_download_size) {
$options[CURLOPT_NOPROGRESS] = false;
//$options[CURLOPT_BUFFERSIZE] = 1024;
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function ($resource, $downloadSize, $downloaded, $uploadSize, $uploaded) {
$this->progress($resource, $downloadSize, $downloaded, $uploadSize, $uploaded);
});
}
curl_setopt_array($ch, $options);
curl_multi_add_handle($master, $ch);
// Add to our request Maps
//$key = (string) serialize($ch);
// php 8 fix
$key = (string) $options[CURLOPT_URL];
/*
$key = str_replace(array('http://www.', 'http://', 'https://www.', 'https://'), '', $key);
if ($_SERVER['TEST_ENV']) {
echo "set key " . $options[CURLOPT_URL] . " ... {$key} \n";
}
*/
$this->requestMap[$key] = $i;
//print_r($this->requestMap);
//echo "
";
}
do {
while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM) ;
if ($execrun != CURLM_OK)
break;
// a request was just completed -- find out which one
while ($done = curl_multi_info_read($master)) {
// get the info and content returned on the request
$info = curl_getinfo($done['handle']);
$output = curl_multi_getcontent($done['handle']);
// send the return values to the callback function.
$callback = $this->callback;
if (is_callable($callback)) {
//$key = (string) $done['handle'];
$key = $info['url'];
if (!$this->requests[$this->requestMap[$key]]) {
//echo 'no key: ' . $key;
//print_r($this->requestMap);
reset($this->requestMap);
foreach ($this->requestMap as $map_k => $map_v) {
$k1 = str_replace(array('http://www.', 'http://', 'https://www.', 'https://'), '', $map_k);
$k2 = str_replace(array('http://www.', 'http://', 'https://www.', 'https://'), '', $info['url']);
if ($k1 == $k2) {
$key = $map_k;
//var_dump($key);
//break;
}
}
}
$request = $this->requests[$this->requestMap[$key]];
$request->handle_id = $this->requestMap[$key];
unset($this->requestMap[$key]);
call_user_func($callback, $output, $info, $request);
}
// start a new request (it's important to do this before removing the old one)
if ($i < sizeof($this->requests) && isset($this->requests[$i]) && $i < count($this->requests)) {
$ch = curl_init();
$options = $this->get_options($this->requests[$i]);
curl_setopt_array($ch, $options);
curl_multi_add_handle($master, $ch);
// Add to our request Maps
//$key = (string) $ch;
$key = (string) $options[CURLOPT_URL];
$this->requestMap[$key] = $i;
$i++;
}
// remove the curl handle that just completed
curl_multi_remove_handle($master, $done['handle']);
}
// Block for data in / output; error handling is done by curl_multi_exec
if ($running)
curl_multi_select($master, $this->timeout);
} while ($running);
curl_multi_close($master);
return true;
}
/**
* Helper function to set up a new request by setting the appropriate options
*
* @access private
* @param Request $request
* @return array
*/
private function get_options($request) {
// options for this entire curl object
$options = $this->__get('options');
if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {
$options[CURLOPT_FOLLOWLOCATION] = 1;
$options[CURLOPT_MAXREDIRS] = 5;
}
$headers = $this->__get('headers');
// append custom options for this specific request
if ($request->options) {
$options = $request->options + $options;
}
// set the request URL
$options[CURLOPT_URL] = $request->url;
// posting data w/ this request?
if ($request->post_data) {
$options[CURLOPT_POST] = 1;
$options[CURLOPT_POSTFIELDS] = $request->post_data;
}
if ($headers) {
$options[CURLOPT_HEADER] = 0;
$options[CURLOPT_HTTPHEADER] = $headers;
}
return $options;
}
/**
* @return void
*/
public function __destruct() {
unset($this->window_size, $this->callback, $this->options, $this->headers, $this->requests);
}
}
function curl_get_file($url) {
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_URL => $url,
));
$output = curl_exec($ch);
return array(
'info' => curl_getinfo($ch),
'body' => $output
);
}
class prompt {
var $tty;
function __constuct() {
if (substr(PHP_OS, 0, 3) == "WIN") {
$this->tty = fopen("\con", "rb");
} else {
if (!($this->tty = fopen("/dev/tty", "r"))) {
$this->tty = fopen("php://stdin", "r");
}
}
if (!$this->tty) die("Can not open tty for input " );
}
function get($string, $length = 1024) {
if (!$this->tty) $this->__constuct();
echo $string;
$result = trim(fgets($this->tty, $length));
echo "\n";
return $result;
}
}