yellow = $yellow; $this->yellow->config->setDefault("updatePluginsUrl", "https://github.com/datenstrom/yellow-plugins"); $this->yellow->config->setDefault("updateThemesUrl", "https://github.com/datenstrom/yellow-themes"); $this->yellow->config->setDefault("updateVersionFile", "version.ini"); $this->yellow->config->setDefault("updateInformationFile", "update.ini"); } // Handle request function onRequest($serverScheme, $serverName, $base, $location, $fileName) { $statusCode = 0; if($this->isInstallation()) { $statusCode = $this->processRequestInstallation($serverScheme, $serverName, $base, $location, $fileName); } else { $statusCode = $this->processRequestUpdate($serverScheme, $serverName, $base, $location, $fileName); } return $statusCode; } // Handle command function onCommand($args) { list($command) = $args; switch($command) { case "update": $statusCode = $this->updateCommand($args); break; default: $statusCode = 0; } return $statusCode; } // Handle command help function onCommandHelp() { return "update [FEATURE]"; } // Show software updates function updateCommand($args) { $statusCode = 0; list($command, $feature) = $args; list($statusCode, $dataCurrent) = $this->getSoftwareVersion(); list($statusCode, $dataLatest) = $this->getSoftwareVersion(true); foreach($dataCurrent as $key=>$value) { if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key]) < 0) { if(empty($feature) || preg_match("/$feature/i", $key)) ++$updates; } } if($statusCode != 200) echo "ERROR checking updates: $data[error]\n"; if($updates) { echo "Yellow $command: $updates update".($updates==1 ? "":"s")." available\n"; } else { echo "Yellow $command: No updates available\n"; } return $statusCode; } // Update software function update() { $statusCode = 0; $path = $this->yellow->config->get("pluginDir"); foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry) { if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::update file:$entry
\n"; $statusCode = max($statusCode, $this->updateSoftwareArchive($entry)); } $path = $this->yellow->config->get("themeDir"); foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry) { if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::update file:$entry
\n"; $statusCode = max($statusCode, $this->updateSoftwareArchive($entry)); } return $statusCode; } // Update software from archive function updateSoftwareArchive($path) { $statusCode = 0; $zip = new ZipArchive(); if($zip->open($path) === true) { $fileNameInformation = $this->yellow->config->get("updateInformationFile"); for($i=0; $i<$zip->numFiles; ++$i) { $fileName = $zip->getNameIndex($i); if(empty($pathBase) && substru($fileName, -1, 1)=="/") $pathBase = $fileName; if($fileName == $pathBase.$fileNameInformation) { $fileData = $zip->getFromIndex($i); break; } } foreach($this->yellow->toolbox->getTextLines($fileData) as $line) { if(preg_match("/^\#/", $line)) continue; preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches); if(lcfirst($matches[1])=="plugin" || lcfirst($matches[1])=="theme") $software = $matches[2]; if(!empty($software) && !empty($matches[1]) && !empty($matches[2])) { list($fileName, $flags) = explode(',', $matches[2], 2); $modified = $zip->statName($pathBase.$fileName)["mtime"]; $rawData = $zip->getFromName($pathBase.$fileName); $statusCode = $this->updateSoftwareFile($matches[1], $modified, $rawData, $flags, $software); if($statusCode != 200) break; } } $zip->close(); if($statusCode==200 && !$this->yellow->toolbox->deleteFile($path)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't delete file '$path'!"); } } return $statusCode; } // Update software file function updateSoftwareFile($fileName, $modified, $rawData, $flags, $software) { $statusCode = 200; $fileName = $this->yellow->toolbox->normaliseTokens($fileName); if($this->yellow->lookup->isValidFile($fileName) && !empty($flags)) { $create = $update = $delete = false; if(preg_match("/create/i", $flags) && !empty($rawData)) $create = true; if(preg_match("/update/i", $flags) && !empty($rawData)) $update = true; if(preg_match("/delete/i", $flags)) $delete = true; if(preg_match("/optional/i", $flags) && $this->isSoftware($software)) $create = $update = $delete = false; if($create && !is_file($fileName)) { if(!$this->yellow->toolbox->createFile($fileName, $rawData, true) || !$this->yellow->toolbox->modifyFile($fileName, $modified)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't create file '$fileName'!"); } } if($update && is_file($fileName)) { if(!$this->yellow->toolbox->deleteFile($fileName, $this->yellow->config->get("trashDir")) || !$this->yellow->toolbox->createFile($fileName, $rawData) || !$this->yellow->toolbox->modifyFile($fileName, $modified)) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't update file '$fileName'!"); } } if($delete && is_file($fileName)) { if(!$this->yellow->toolbox->deleteFile($fileName, $this->yellow->config->get("trashDir"))) { $statusCode = 500; $this->yellow->page->error($statusCode, "Can't delete file '$fileName'!"); } } if(defined("DEBUG") && DEBUG>=3) echo "YellowUpdate::updateSoftwareFile file:$fileName flags:$flags
\n"; } return $statusCode; } // Process request to install updates function processRequestUpdate($serverScheme, $serverName, $base, $location, $fileName) { $statusCode = 0; if($this->isContentFile($fileName)) { $statusCode = $this->update(); if($statusCode == 200) { $statusCode = 303; $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location); $this->yellow->sendStatus($statusCode, $location); } } return $statusCode; } // Process request to install website function processRequestInstallation($serverScheme, $serverName, $base, $location, $fileName) { $statusCode = 0; if($this->isContentFile($fileName)) { $fileName = $this->yellow->lookup->findFileNew($fileName, $this->yellow->config->get("webinterfaceNewFile"), $this->yellow->config->get("configDir"), "installation"); $this->yellow->pages->pages["root/"] = array(); $this->yellow->page = new YellowPage($this->yellow); $this->yellow->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName); $this->yellow->page->parseData($this->getRawDataInstallation($fileName, $this->yellow->getRequestLanguage()), false, 404); $this->yellow->page->parserSafeMode = false; $this->yellow->page->parseContent(); $name = trim(preg_replace("/[^\pL\d\-\. ]/u", "-", $_REQUEST["name"])); $email = trim($_REQUEST["email"]); $password = trim($_REQUEST["password"]); $language = trim($_REQUEST["language"]); $status = trim($_REQUEST["status"]); if($status == "install") { $status = "ok"; $fileNameHome = $this->yellow->lookup->findFileFromLocation("/"); $fileData = strreplaceu("\r\n", "\n", $this->yellow->toolbox->readFile($fileNameHome)); if($fileData==$this->getRawDataHome("en") && $language!="en") { $status = $this->yellow->toolbox->createFile($fileNameHome, $this->getRawDataHome($language)) ? "ok" : "error"; if($status == "error") $this->yellow->page->error(500, "Can't write file '$fileNameHome'!"); } } if($status == "ok") { if(!empty($email) && !empty($password) && $this->yellow->plugins->isExisting("webinterface")) { $fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile"); $status = $this->yellow->plugins->get("webinterface")->users->update($fileNameUser, $email, $password, $name, $language) ? "ok" : "error"; if($status == "error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!"); } } if($status == "ok") { if($this->yellow->config->get("sitename") == "Yellow") $_REQUEST["sitename"] = $name; $fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile"); $status = $this->yellow->config->update($fileNameConfig, $this->getConfigData()) ? "done" : "error"; if($status == "error") $this->yellow->page->error(500, "Can't write file '$fileNameConfig'!"); } if($status == "done") { $statusCode = 303; $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location); $this->yellow->sendStatus($statusCode, $location); } else { $statusCode = $this->yellow->sendPage(); } } return $statusCode; } // Return raw data for installation page function getRawDataInstallation($fileName, $language) { $rawData = $this->yellow->toolbox->readFile($fileName); if(empty($rawData)) { $this->yellow->text->setLanguage($language); $rawData = "---\nTitle:".$this->yellow->text->get("webinterfaceInstallationTitle")."\nLanguage:$language\nNavigation:navigation\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"; } $rawData .= "yellow->text->get("webinterfaceOkButton")."\" />\n"; $rawData .= "\n"; $rawData .= "
\n"; } return $rawData; } // Return raw data for home page function getRawDataHome($language) { $rawData = "---\nTitle: Home\n---\n".strreplaceu("\\n", "\n", $this->yellow->text->getText("webinterfaceInstallationHomePage", $language)); return $rawData; } // Return configuration data function getConfigData() { $data = array(); foreach($_REQUEST as $key=>$value) { if(!$this->yellow->config->isExisting($key)) continue; $data[$key] = trim($value); } $data["# serverScheme"] = $this->yellow->toolbox->getServerScheme(); $data["# serverName"] = $this->yellow->toolbox->getServerName(); $data["# serverBase"] = $this->yellow->toolbox->getServerBase(); $data["# serverTime"] = $this->yellow->toolbox->getServerTime(); $data["installationMode"] = "0"; return $data; } // Return software version function getSoftwareVersion($latest = false) { $data = array(); if($latest) { list($statusCodePlugins, $dataPlugins) = $this->getSoftwareVersionFromUrl($this->yellow->config->get("updatePluginsUrl")); list($statusCodeThemes, $dataThemes) = $this->getSoftwareVersionFromUrl($this->yellow->config->get("updateThemesUrl")); $statusCode = max($statusCodePlugins, $statusCodeThemes); $data = array_merge($dataPlugins, $dataThemes); } else { $statusCode = 200; foreach($this->yellow->plugins->getData() as $key=>$value) $data[$key] = $value; foreach($this->yellow->themes->getData() as $key=>$value) $data[$key] = $value; } return array($statusCode, $data); } // Return software version from URL function getSoftwareVersionFromUrl($url) { $data = array(); $urlVersion = $url; if(preg_match("#^https://github.com/(.+)$#", $url, $matches)) { $urlVersion = "https://raw.githubusercontent.com/".$matches[1]."/master/".$this->yellow->config->get("updateVersionFile"); } if(extension_loaded("curl")) { $curlHandle = curl_init(); curl_setopt($curlHandle, CURLOPT_URL, $urlVersion); 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); if($statusCode == 200) { if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::getSoftwareVersionFromUrl location:$url\n"; foreach($this->yellow->toolbox->getTextLines($rawData) as $line) { preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches); if(!empty($matches[1]) && !empty($matches[2])) { list($version, $url) = explode(',', $matches[2]); $data[$matches[1]] = $version; if(defined("DEBUG") && DEBUG>=3) echo "YellowUpdate::getSoftwareVersionFromUrl $matches[1]:$version\n"; } } } if($statusCode == 0) $statusCode = 444; $data["error"] = "$url - ".$this->yellow->toolbox->getHttpStatusFormatted($statusCode); } else { $statusCode = 500; $data["error"] = "Plugin 'update' requires cURL library!"; } return array($statusCode, $data); } // Check if software exists function isSoftware($software) { $data = $this->yellow->plugins->getData(); return !is_null($data[$software]); } // Check if installation requested function isInstallation() { return $this->yellow->config->get("installationMode") && PHP_SAPI!="cli"; } // Check if content file function isContentFile($fileName) { $contentDirLength = strlenu($this->yellow->config->get("contentDir")); return substru($fileName, 0, $contentDirLength) == $this->yellow->config->get("contentDir"); } } $yellow->plugins->register("update", "YellowUpdate", YellowUpdate::Version); ?>