array('timeout' => 5))); if (trim(@file_get_contents('https://api.github.com/', false, $context))) { //file_get_contents works $httpBackend = 'php'; } } //TODO probably implement curl (from cli), curl (php module), fsockopen and others } define('HTTP_BACKEND', $httpBackend); $steps = array( 'welcome' => 'StepWelcome', 'check' => 'StepCheck', 'downloadApp' => 'StepDownloadApp', 'extractApp' => 'StepExtractApp', 'downloadKwf' => 'StepDownloadKwf', 'downloadLibrary' => 'StepDownloadLibrary', 'extractKwf' => 'StepExtractKwf', 'extractLibrary' => 'StepExtractLibrary', 'moveApp' => 'StepMoveApp', ); $step = isset($_GET['step']) ? $_GET['step'] : 'welcome'; if (!isset($steps[$step])) throw new Exception("Invalid step"); $stepClass = $steps[$step]; $stepNum = array_search($step, array_keys($steps)); $step = new $stepClass(); echo "
Welcome to the Koala Framework Downloader
"; echo "This script will download a koala framework application plus the required libraries to run.
"; echo "The recommended way is to use git on the server, but if you don't have shell access or git is not installed this downloader can be helpful.
"; } } class StepCheck extends Step { public $name = 'Check Server Configuration'; private $_foundError = false; private function _printError($msg) { echo "".htmlspecialchars($msg)."
"; $this->_foundError = true; } public function getShowNextStep() { return !$this->_foundError; } public function execute() { global $selfFileName, $selfBaseUrl; //test required executables exec('ls', $out, $ret); if ($ret) { $this->_printError("can't execute system commands"); } exec('tar --version', $out, $ret); if ($ret) { $this->_printError("can't find tar executable"); } //test permissions if (!is_writeable('.')) { $this->_printError("Downloader script needs write permissions to current folder"); } //test .htaccess functionality $htAccessTestContents = "RewriteEngine on RewriteCond %{REQUEST_URI} !^/*($selfFileName)/? RewriteRule ^(.*)$ $selfFileName [L] "; if (file_exists('.htaccess') && file_get_contents('.htaccess') != $htAccessTestContents) { $this->_printError("There exists already a .htaccess in the current folder"); } file_put_contents('.htaccess', $htAccessTestContents); $url = 'http://'.$_SERVER['HTTP_HOST'].$selfBaseUrl.'/ping'; if (HTTP_BACKEND == 'none') { //with 'none' httpBackend we still might can access ourselves (as no firewall blocks) //this eventually still fails because of allow_url_fopen=Off //TODO try other alternatives, fsockopen and friends $pingResponse = trim(file_get_contents($url)); } else { $pingResponse = trim(httpRequestGet($url)); } unlink('.htaccess'); if ($pingResponse != 'pong') { $this->_printError(".htaccess broken"); } if (HTTP_BACKEND == 'none') { echo "WARNING The downloader script can't download files as requests are not allowed/get blocked. You can still use this tool by manually uploading the required files onto your server using eg. ftp
\n"; } if (!$this->_foundError) { echo "All checks required for the downloader passed.
\n"; echo "Note: this doesn't include all requirements needed by kwf.
\n"; } } } abstract class StepDownload extends Step { protected $_url; protected $_target; public function execute() { if (isset($_REQUEST['downloadUrl'])) { $url = $_REQUEST['downloadUrl']; if (HTTP_BACKEND == 'wget') { exec("wget -O ".escapeshellarg($this->_target)." ".escapeshellarg($url), $out, $ret); if ($ret) { echo "Download failed
"; } } else if (HTTP_BACKEND == 'php') { $fpr = fopen($url, 'r'); $fpw = fopen($this->_target, 'w'); while(!feof($fpr)) { fwrite($fpw, fread($fpr, 1024)); } fclose($fpr); fclose($fpw); } else { } echo "Successfully Downloaded: $this->_target
"; } if (!file_exists($this->_target)) { if (HTTP_BACKEND == 'none') { echo "Please upload $this->_target and refresh this page
\n"; } else { //that's a bit ugly - probably this should be a function. But it works :D $updateUrlJs = "if (document.getElementById('predefUrls').value=='github') { "; $updateUrlJs .= " if (document.getElementById('ghUser').value && document.getElementById('ghRepo').value && document.getElementById('ghBranch').value) { "; $updateUrlJs .= " document.getElementById('downloadUrl').value = 'https://github.com/'+document.getElementById('ghUser').value+'/'+document.getElementById('ghRepo').value+'/archive/'+document.getElementById('ghBranch').value+'.tar.gz'; "; $updateUrlJs .= " } else { document.getElementById('downloadUrl').value = ''; }"; $updateUrlJs .= "} else { "; $updateUrlJs .= " document.getElementById('downloadUrl').value=document.getElementById('predefUrls').value; "; $updateUrlJs .= "}"; echo "\n"; } } else { echo "Using: $this->_target
"; } } abstract protected function _getDownloadUrls(); public function getShowNextStep() { return file_exists($this->_target); } } abstract class StepExtract extends Step { protected $_file; protected $_targetDir; protected function _alreadyExtracted() { return file_exists($this->_targetDir); } public function execute() { if (!$this->_alreadyExtracted()) { $dir = tempnam('.', 'downloader'); unlink($dir); mkdir($dir); exec("tar xfz $this->_file -C $dir", $out, $ret); if ($ret) { throw new Exception("Extraction failed"); } $dirs = glob("$dir/*"); if (count($dirs) != 1) { throw new Exception("more than one directory extracted"); } if (!is_dir($dirs[0])) { throw new Exception("no directory extracted"); } rename("$dirs[0]", $this->_targetDir); rmdir($dir); unlink($this->_file); echo "Successfully Extracted: $this->_targetDir
"; } else { echo "Already Extracted: $this->_targetDir
"; } } } class StepDownloadApp extends StepDownload { public $name = 'Download App'; protected $_target = 'app.tar.gz'; public function execute() { if (HTTP_BACKEND == 'none') { echo "Plase upload the application you want to install. This can be either
a kwf demo application or your own. If the application code is hosted on github you can
use the github archive functionality.
Download Example: kwf-cms-demo
Plase choose the application you want to install. This can be either
a kwf demo application or your own. If the application code is hosted on github you can
use the github archive functionality.
You can also upload $this->_target manually.
Plase upload the Koala Framework Version you want to install. (it has to match the required version for your application)
Download Example: master branch
Plase choose the Koala Framework Version you want to install. (it has to match the required version for your application)
You can also upload $this->_target manually.
Plase upload the library you want to install.
Download Default
Plase choose the library you want to install, usually default should suffice.
You can also upload $this->_target manually.
".realpath($dir).""; echo "(you won't have to download the 50MB)"; break; } } } } public function getShowNextStep() { if (parent::getShowNextStep()) return true; return is_dir('library'); } protected function _getDownloadUrls() { $ret = array( 'https://github.com/vivid-planet/library/archive/master.tar.gz' => 'Default (Recommended)' ); return $ret; } } class StepExtractKwf extends StepExtract { public $name = 'Extract Kwf'; protected $_file = 'kwf.tar.gz'; protected $_targetDir = 'kwf-lib'; public function execute() { parent::execute(); file_put_contents($this->_targetDir.'/include_path', getcwd().'/library/zend/%version%'); } } class StepExtractLibrary extends StepExtract { public $name = 'Extract Library'; protected $_file = 'library.tar.gz'; protected $_targetDir = 'library'; } class StepExtractApp extends StepExtract { public $name = 'Extract App'; protected $_file = 'app.tar.gz'; protected $_targetDir = 'app-temp'; } class StepMoveApp extends Step { public $name = 'Move App'; public function execute() { global $selfFileName, $selfBaseUrl; exec("mv app-temp/* .", $out, $ret); if ($ret) { throw new Exception("Moving app failed"); } exec("mv app-temp/.* .", $out, $ret); rmdir("app-temp"); $cfg = "[production]\n"; $cfg .= "server.domain = ".$_SERVER['HTTP_HOST']."\n"; $cfg .= "server.baseUrl = \"".$selfBaseUrl."\"\n"; $cfg .= "setupFinished = false\n"; file_put_contents('config.local.ini', $cfg); //if the apache configuration doesn't allow setting php_flag remove it if (HTTP_BACKEND == 'wget') { $response = shell_exec('wget -O /dev/null -S '.escapeshellarg('http://'.$_SERVER['HTTP_HOST'].$selfBaseUrl).' 2>&1'); } else { @file_get_contents('http://'.$_SERVER['HTTP_HOST'].$selfBaseUrl); $response = implode("\n", $http_response_header); } if (preg_match("#HTTP/1\.\d\s+(\d{3})\s+#", $response, $m)) { if ($m[1] == 500) { //internal server error $htAccess = file_get_contents('.htaccess'); $htAccess = str_replace('php_flag magic_quotes_gpc off', '', $htAccess); file_put_contents('.htaccess', $htAccess); } } echo "
Congratulations, downloader finished!
"; echo ""; unlink($selfFileName); //our job is done, now commit suicide } }