yellow = $yellow; } // Handle request public function onRequest($scheme, $address, $base, $location, $fileName) { $statusCode = 0; if (($this->yellow->lookup->isContentFile($fileName) || empty($fileName)) && $this->checkServer()) { $statusCode = $this->processRequestInstall($scheme, $address, $base, $location, $fileName); } return $statusCode; } // Handle command public function onCommand($args) { $statusCode = 0; if ($this->checkServer()) { $statusCode = $this->processCommandInstall(); } return $statusCode; } // Process request to install website public function processRequestInstall($scheme, $address, $base, $location, $fileName) { $author = trim(preg_replace("/[^\pL\d\-\. ]/u", "-", $_REQUEST["author"])); $email = trim($_REQUEST["email"]); $password = trim($_REQUEST["password"]); $language = trim($_REQUEST["language"]); $extension = trim($_REQUEST["extension"]); $status = trim($_REQUEST["status"]); $statusCode = $this->updateLog(); $statusCode = max($statusCode, $this->updateLanguage()); $this->yellow->content->pages["root/"] = array(); $this->yellow->page = new YellowPage($this->yellow); $this->yellow->page->setRequestInformation($scheme, $address, $base, $location, $fileName); $this->yellow->page->parseData($this->getRawDataInstall(), false, $statusCode, $this->yellow->page->get("pageError")); $this->yellow->page->safeMode = false; if ($status=="install") $status = $this->updateExtension($extension)==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateUser($email, $password, $author, $language)==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateContent($language, "installHome", "/")==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateContent($language, "installDefault", "/shared/page-new-default")==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateContent($language, "installBlog", "/shared/page-new-blog")==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateContent($language, "installWiki", "/shared/page-new-wiki")==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateContent($language, "coreError404", "/shared/page-error-404")==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateText($language)==200 ? "ok" : "error"; if ($status=="ok") $status = $this->updateSystem($this->getSystemData())==200 ? "ok" : "error"; if ($status=="ok") $status = $this->removeFiles()==200 ? "done" : "error"; if ($status=="done") { $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location); $statusCode = $this->yellow->sendStatus(303, $location); } else { $statusCode = $this->yellow->sendPage(); } return $statusCode; } // Process command to install website public function processCommandInstall() { $statusCode = $this->updateLog(); if ($statusCode==200) $statusCode = $this->updateLanguage(); if ($statusCode==200) $statusCode = $this->updateText("en"); if ($statusCode==200) $statusCode = $this->updateSystem($this->getSystemData()); if ($statusCode==200) $statusCode = $this->removeFiles(); if ($statusCode==200) { $statusCode = 0; } else { echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n"; echo "Your website has ".($statusCode!=200 ? "not " : "")."been updated: Please run command again\n"; } return $statusCode; } // Update log public function updateLog() { $statusCode = 200; $fileName = $this->yellow->system->get("coreExtensionDir").$this->yellow->system->get("coreLogFile"); if (!is_file($fileName)) { $serverVersion = $this->yellow->toolbox->getServerVersion(); $this->yellow->log("info", "Datenstrom Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverVersion"); if (!is_file($fileName)) { $statusCode = 500; $this->yellow->page->error(500, "Can't write file '$fileName'!"); } } return $statusCode; } // Update language public function updateLanguage() { $statusCode = 200; $path = $this->yellow->system->get("coreExtensionDir")."install-languages.zip"; if (is_file($path) && $this->yellow->extensions->isExisting("update")) { $zip = new ZipArchive(); if ($zip->open($path)===true) { $languages = $this->detectBrowserLanguages("en, de, fr"); $languagesFound = array(); foreach ($languages as $language) $languagesFound[$language] = ""; if (preg_match("#^(.*\/).*?$#", $zip->getNameIndex(0), $matches)) $pathBase = $matches[1]; $fileData = $zip->getFromName($pathBase.$this->yellow->system->get("updateExtensionFile")); foreach ($this->yellow->toolbox->getTextLines($fileData) as $line) { preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches); if (!empty($matches[1]) && !empty($matches[2]) && strposu($matches[1], "/")) { list($dummy, $entry) = explode(",", $matches[2], 3); $flags = explode(",", $matches[2]); $language = array_pop($flags); if (preg_match("/^(.*)\.php$/", basename($entry), $tokens) && in_array($language, $languages)) { $languagesFound[$language] = $tokens[1]; } } } $languagesFound = array_slice(array_filter($languagesFound, "strlen"), 0, 3); foreach ($this->yellow->toolbox->getTextLines($fileData) as $line) { preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches); if (lcfirst($matches[1])=="extension") $extension = lcfirst($matches[2]); if (lcfirst($matches[1])=="published") $modified = strtotime($matches[2]); if (!empty($matches[1]) && !empty($matches[2]) && strposu($matches[1], "/")) { $fileName = $matches[1]; list($dummy, $entry) = explode(",", $matches[2], 3); $fileData = $zip->getFromName($pathBase.basename($entry)); if (preg_match("/^(.*).php$/", basename($entry), $tokens) && in_array($tokens[1], $languagesFound) && !is_file($fileName)) { $statusCode = $this->yellow->extensions->get("update")->updateExtensionFile($fileName, $fileData, $modified, 0, 0, "create", false, $extension); } if (preg_match("/^(.*)-language\.txt$/", basename($entry), $tokens) && in_array($tokens[1], $languagesFound) && !is_file($fileName)) { $statusCode = $this->yellow->extensions->get("update")->updateExtensionFile($fileName, $fileData, $modified, 0, 0, "create", false, $extension); $this->yellow->log($statusCode==200 ? "info" : "error", "Install language '".ucfirst($tokens[1])."'"); } if ($statusCode!=200) break; } } $zip->close(); if ($statusCode==200) { $this->yellow->text->load($this->yellow->system->get("coreExtensionDir").$this->yellow->system->get("coreLanguageFile"), ""); } } else { $statusCode = 500; $this->yellow->page->error(500, "Can't open file '$path'!"); } } return $statusCode; } // Update extension public function updateExtension($extension) { $statusCode = 200; $path = $this->yellow->system->get("coreExtensionDir"); if (!empty($extension) && $this->yellow->extensions->isExisting("update")) { foreach ($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry) { if (preg_match("/^install-(.*?)\./", basename($entry), $matches)) { if (strtoloweru($matches[1])==strtoloweru($extension)) { $statusCode = $this->yellow->extensions->get("update")->updateExtensionArchive($entry, "install"); break; } } } } return $statusCode; } // Update user public function updateUser($email, $password, $name, $language) { $statusCode = 200; if (!empty($email) && !empty($password) && $this->yellow->extensions->isExisting("edit")) { if (empty($name)) $name = $this->yellow->system->get("sitename"); $fileNameUser = $this->yellow->system->get("coreSettingDir").$this->yellow->system->get("editUserFile"); $settings = array( "name" => $name, "language" => $language, "home" => "/", "access" => "create, edit, delete, upload, system, update", "hash" => $this->yellow->extensions->get("edit")->users->createHash($password), "stamp" => $this->yellow->extensions->get("edit")->users->createStamp(), "pending" => "none", "failed" => "0", "modified" => time(), "status" => "active"); if (!$this->yellow->extensions->get("edit")->users->save($fileNameUser, $email, $settings)) { $statusCode = 500; $this->yellow->page->error(500, "Can't write file '$fileNameUser'!"); } $this->yellow->log($statusCode==200 ? "info" : "error", "Add user '".strtok($name, " ")."'"); } return $statusCode; } // Update content public function updateContent($language, $name, $location) { $statusCode = 200; $fileName = $this->yellow->lookup->findFileFromLocation($location); $fileData = strreplaceu("\r\n", "\n", $this->yellow->toolbox->readFile($fileName)); if (!empty($fileData) && $language!="en") { $titleOld = "Title: ".$this->yellow->text->getText("{$name}Title", "en"); $titleNew = "Title: ".$this->yellow->text->getText("{$name}Title", $language); $textOld = strreplaceu("\\n", "\n", $this->yellow->text->getText("{$name}Text", "en")); $textNew = strreplaceu("\\n", "\n", $this->yellow->text->getText("{$name}Text", $language)); $fileData = strreplaceu($titleOld, $titleNew, $fileData); $fileData = strreplaceu($textOld, $textNew, $fileData); if (!$this->yellow->toolbox->createFile($fileName, $fileData)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); } } return $statusCode; } // Update text settings public function updateText($language) { $statusCode = 200; $fileName = $this->yellow->system->get("coreSettingDir").$this->yellow->system->get("coreTextFile"); $fileData = $this->yellow->toolbox->readFile($fileName); if (count($this->yellow->toolbox->getTextLines($fileData))<4) { $fileData .= "Language: $language\n"; $fileData .= "CoreDateFormatMedium: ".$this->yellow->text->getText("coreDateFormatMedium", $language)."\n"; $fileData .= "EditLoginTitle: ".$this->yellow->text->getText("editLoginTitle", $language)."\n"; $fileData .= "picture.jpg: ".$this->yellow->text->getText("installExampleImage", $language)."\n"; if (!$this->yellow->toolbox->createFile($fileName, $fileData)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); } } return $statusCode; } // Update system settings public function updateSystem($settings) { $statusCode = 200; $fileName = $this->yellow->system->get("coreSettingDir").$this->yellow->system->get("coreSystemFile"); if (!$this->yellow->system->save($fileName, $settings)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); } return $statusCode; } // Remove files used by installation public function removeFiles() { $statusCode = 200; if (function_exists("opcache_reset")) opcache_reset(); $path = $this->yellow->system->get("coreExtensionDir"); foreach ($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry) { if (preg_match("/^install-(.*?)\./", basename($entry), $matches)) { if (!$this->yellow->toolbox->deleteFile($entry)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't delete file '$entry'!"); } } } $path = $this->yellow->system->get("coreExtensionDir")."install.php"; if ($statusCode==200 && !$this->yellow->toolbox->deleteFile($path)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't delete file '$path'!"); } if ($statusCode==200) unset($this->yellow->extensions->extensions["install"]); return $statusCode; } // Check web server public function checkServer() { if ($this->yellow->isCommandLine()) { version_compare(PHP_VERSION, "5.6", ">=") || die("Datenstrom Yellow requires PHP 5.6 or higher!\n"); $this->checkServerExtensions() || die("Datenstrom Yellow requires PHP ".$this->getServerExtensionRequired()." extension!\n"); } else { $server = $this->yellow->toolbox->getServerVersion(true); $troubleshooting = "See troubleshooting."; version_compare(PHP_VERSION, "5.6", ">=") || die("Datenstrom Yellow requires PHP 5.6 or higher! $troubleshooting\n"); $this->checkServerExtensions() || die("Datenstrom Yellow requires PHP ".$this->getServerExtensionRequired()." extension for $server! $troubleshooting\n"); $this->checkServerConfiguration() || die("Datenstrom Yellow requires a configuration file for $server! $troubleshooting\n"); $this->checkServerRewrite() || die("Datenstrom Yellow requires rewrite support for $server! $troubleshooting\n"); $this->checkServerWrite() || die("Datenstrom Yellow requires write access for $server! $troubleshooting\n"); } return true; } // Check web server extensions public function checkServerExtensions() { return empty($this->getServerExtensionRequired()); } // Check web server configuration file public function checkServerConfiguration() { $server = $this->yellow->toolbox->getServerVersion(true); return strtoloweru($server)!="apache" || is_file(".htaccess"); } // Check web server rewrite support public function checkServerRewrite() { $curlHandle = curl_init(); list($scheme, $address, $base) = $this->yellow->getRequestInformation(); $location = $this->yellow->system->get("coreResourceLocation").$this->yellow->lookup->normaliseName($this->yellow->system->get("theme")).".css"; $url = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location); curl_setopt($curlHandle, CURLOPT_URL, $url); curl_setopt($curlHandle, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; YellowCore/".YellowCore::VERSION).")"; curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 30); $rawData = curl_exec($curlHandle); $statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE); curl_close($curlHandle); return !empty($rawData) && $statusCode==200; } // Check web server write access public function checkServerWrite() { $fileName = $this->yellow->system->get("coreSettingDir").$this->yellow->system->get("coreSystemFile"); return $this->yellow->system->save($fileName, array()); } // Detect web browser languages public function detectBrowserLanguages($languagesDefault) { $languages = array(); if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) { foreach (preg_split("/\s*,\s*/", $_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $string) { list($language) = explode(";", $string); if (!empty($language)) array_push($languages, $language); } } foreach (preg_split("/\s*,\s*/", $languagesDefault) as $language) { if (!empty($language)) array_push($languages, $language); } return array_unique($languages); } // Return web server extension required public function getServerExtensionRequired() { $extension = ""; $extensionsRequired = "curl, dom, gd, exif, mbstring, zip"; foreach (preg_split("/\s*,\s*/", $extensionsRequired) as $extensionRequired) { if (!extension_loaded($extensionRequired)) $extension = $extensionRequired; } return $extension; } // Return system data including static information public function getSystemData() { $data = array(); foreach ($_REQUEST as $key=>$value) { if (!$this->yellow->system->isExisting($key)) continue; if ($key=="password" || $key=="status") continue; $data[$key] = trim($value); } $data["coreStaticUrl"] = $this->yellow->toolbox->getServerUrl(); $data["coreServerTimezone"] = $this->yellow->toolbox->getTimezone(); if ($this->yellow->isCommandLine()) $data["coreStaticUrl"] = getenv("URL"); return $data; } // Return raw data for install page public function getRawDataInstall() { $language = $this->yellow->toolbox->detectBrowserLanguage($this->yellow->text->getLanguages(), $this->yellow->system->get("language")); $this->yellow->text->setLanguage($language); $rawData = "---\nTitle:".$this->yellow->text->get("installTitle")."\nLanguage:$language\nNavigation:navigation\nHeader:none\nFooter:none\nSidebar:none\n---\n"; $rawData .= "
yellow->page->getLocation(true)."\" method=\"post\">\n"; $rawData .= "


\n"; $rawData .= "


\n"; $rawData .= "


\n"; if (count($this->yellow->text->getLanguages())>1) { $rawData .= "

"; foreach ($this->yellow->text->getLanguages() as $language) { $checked = $language==$this->yellow->text->language ? " checked=\"checked\"" : ""; $rawData .= "
"; } $rawData .= "

\n"; } if (count($this->getExtensionsInstall())>1) { $rawData .= "

".$this->yellow->text->get("installExtension")."

"; foreach ($this->getExtensionsInstall() as $extension) { $checked = $extension=="website" ? " checked=\"checked\"" : ""; $rawData .= "
"; } $rawData .= "

\n"; } $rawData .= "yellow->text->get("editOkButton")."\" />\n"; $rawData .= "\n"; $rawData .= "
\n"; return $rawData; } // Return extensions for install page public function getExtensionsInstall() { $extensions = array("website"); $path = $this->yellow->system->get("coreExtensionDir"); foreach ($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false, false) as $entry) { if (preg_match("/^install-(.*?)\./", $entry, $matches) && $matches[1]!="languages") array_push($extensions, $matches[1]); } return $extensions; } }