/** * Read in all possible packages from the interface packages folder and * check if they are not ASP.net code (as this can't be processed). * * Note: There's no need to check if the packages to register are newer * than those in the database because this already happended in startCrawler() */ public function parseFolderToDB() { global $app; try { // This method must be used in interface mode if (!$this->interface_mode) { return false; } $pkg_list = array(); // Read in every package having a correct filename $temp_handle = @dir($this->interface_pkg_dir); if (!$temp_handle) { throw new Exception('The temp directory is not accessible'); } while ($folder = $temp_handle->read()) { if (substr($folder, -8) == '.app.zip') { $pkg_list[] = $folder; } } $temp_handle->close(); // If no packages are available -> exception (because at this point there should exist packages) if (empty($pkg_list)) { throw new Exception('No packages to read in'); } // Get registered packages and mark non-existant packages with an error code to omit the install $existing_packages = array(); $path_query = $app->db->queryAllRecords('SELECT path AS Path FROM aps_packages;'); foreach ($path_query as $path) { $existing_packages[] = $path['Path']; } $diff = array_diff($existing_packages, $pkg_list); foreach ($diff as $todelete) { /*$app->db->query("UPDATE aps_packages SET package_status = '".PACKAGE_ERROR_NOMETA."' WHERE path = '".$app->db->quote($todelete)."';");*/ $tmp = $app->db->queryOneRecord("SELECT id FROM aps_packages WHERE path = '" . $app->db->quote($todelete) . "';"); $app->db->datalogUpdate('aps_packages', "package_status = " . PACKAGE_ERROR_NOMETA, 'id', $tmp['id']); unset($tmp); } // Register all new packages $new_packages = array_diff($pkg_list, $existing_packages); foreach ($new_packages as $pkg) { // Load in meta file if existing and register its namespaces $metafile = $this->interface_pkg_dir . '/' . $pkg . '/APP-META.xml'; if (!file_exists($metafile)) { $app->log($this->log_prefix . 'Cannot read metadata from ' . $pkg, LOGLEVEL_ERROR); continue; } $metadata = file_get_contents($metafile); $metadata = str_replace("xmlns=", "ns=", $metadata); $sxe = new SimpleXMLElement($metadata); $namespaces = $sxe->getDocNamespaces(true); foreach ($namespaces as $ns => $url) { $sxe->registerXPathNamespace($ns, $url); } // Insert the new package $pkg_name = parent::getXPathValue($sxe, 'name'); $pkg_category = parent::getXPathValue($sxe, '//category'); $pkg_version = parent::getXPathValue($sxe, 'version'); $pkg_release = parent::getXPathValue($sxe, 'release'); //$pkg_url = $this->app_download_url_list[$pkg]; $pkg_url = @file_get_contents($this->interface_pkg_dir . '/' . $pkg . '/PKG_URL'); /* $app->db->query("INSERT INTO `aps_packages` (`path`, `name`, `category`, `version`, `release`, `package_status`) VALUES ('".$app->db->quote($pkg)."', '".$app->db->quote($pkg_name)."', '".$app->db->quote($pkg_category)."', '".$app->db->quote($pkg_version)."', ".$app->db->quote($pkg_release).", ".PACKAGE_ENABLED.");"); */ // Insert only if data is complete if ($pkg != '' && $pkg_name != '' && $pkg_category != '' && $pkg_version != '' && $pkg_release != '' && $pkg_url) { $insert_data = "(`path`, `name`, `category`, `version`, `release`, `package_url`, `package_status`) VALUES\n ('" . $app->db->quote($pkg) . "', '" . $app->db->quote($pkg_name) . "',\n '" . $app->db->quote($pkg_category) . "', '" . $app->db->quote($pkg_version) . "',\n " . $app->db->quote($pkg_release) . ", '" . $app->db->quote($pkg_url) . "', " . PACKAGE_ENABLED . ");"; $app->db->datalogInsert('aps_packages', $insert_data, 'id'); } else { if (file_exists($this->interface_pkg_dir . '/' . $pkg)) { $this->removeDirectory($this->interface_pkg_dir . '/' . $pkg); } } } } catch (Exception $e) { $app->log($this->log_prefix . $e->getMessage(), LOGLEVEL_ERROR); $app->error($e->getMessage()); return false; } }
/** * Setup a database (if needed) and the appropriate environment variables * * @param $task an array containing all install related data * @param $sxe a SimpleXMLElement handle, holding APP-META.xml */ private function prepareDatabase($task, $sxe) { global $app; $db_id = parent::getXPathValue($sxe, '//db:id'); if (empty($db_id)) { return; } // No database needed /* WARNING: if this will ever be uncommented please check the updated prefix handling for user and db names!!! * // Set the database owner to the domain owner // ISPConfig identifies the owner by the sys_groupid (not sys_userid!) // so sys_userid can be set to any value $perm = $app->db->queryOneRecord("SELECT sys_groupid, server_id FROM web_domain WHERE domain = '".$this->domain."';"); $task['sys_groupid'] = $perm['sys_groupid']; $serverid = $perm['server_id']; // Get the database prefix and db user prefix $app->uses('getconf'); $global_config = $app->getconf->get_global_config('sites'); $dbname_prefix = str_replace('[CLIENTID]', '', $global_config['dbname_prefix']); $dbuser_prefix = str_replace('[CLIENTID]', '', $global_config['dbuser_prefix']); $this->dbhost = DB_HOST; // Taken from config.inc.php if(empty($this->dbhost)) $this->dbhost = 'localhost'; // Just to ensure any hostname... ;) $this->newdb_name = $dbname_prefix.$task['CustomerID'].'aps'.$task['InstanceID']; $this->newdb_user = $dbuser_prefix.$task['CustomerID'].'aps'.$task['InstanceID']; $dbpw_res = $app->db->queryOneRecord("SELECT Value FROM aps_instances_settings WHERE Name = 'main_database_password' AND InstanceID = '".$app->db->quote($task['InstanceID'])."';"); $newdb_pw = $dbpw_res['Value']; // In any case delete an existing database (install and removal procedure) $app->db->query('DROP DATABASE IF EXISTS `'.$app->db->quote($this->newdb_name).'`;'); // Delete an already existing database with this name $app->db->query("DELETE FROM web_database WHERE database_name = '".$app->db->quote($this->newdb_name)."';"); // Create the new database and assign it to a user if($this->handle_type == 'install') { $app->db->query('CREATE DATABASE IF NOT EXISTS `'.$app->db->quote($this->newdb_name).'`;'); $app->db->query('GRANT ALL PRIVILEGES ON '.$app->db->quote($this->newdb_name).'.* TO '.$app->db->quote($this->newdb_user).'@'.$app->db->quote($this->dbhost).' IDENTIFIED BY \'password\';'); $app->db->query('SET PASSWORD FOR '.$app->db->quote($this->newdb_user).'@'.$app->db->quote($this->dbhost).' = PASSWORD(\''.$newdb_pw.'\');'); $app->db->query('FLUSH PRIVILEGES;'); // Add the new database to the customer databases // Assumes: charset = utf8 $app->db->query('INSERT INTO web_database (sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other, server_id, type, database_name, database_user, database_password, database_charset, remote_access, remote_ips, active) VALUES ('.$task['sys_userid'].', '.$task['sys_groupid'].', "'.$task['sys_perm_user'].'", "'.$task['sys_perm_group'].'", "'.$task['sys_perm_other'].'", '.$app->db->quote($serverid).', "mysql", "'.$app->db->quote($this->newdb_name).'", "'.$app->db->quote($this->newdb_user).'", "'.$app->db->quote($newdb_pw).'", "utf8", "n", "", "y");'); } */ $mysqlver_res = $app->db->queryOneRecord('SELECT VERSION() as ver;'); $mysqlver = $mysqlver_res['ver']; $tmp = $app->db->queryOneRecord("SELECT value FROM aps_instances_settings WHERE name = 'main_database_password' AND instance_id = '" . $app->db->quote($task['instance_id']) . "';"); $newdb_pw = $tmp['value']; $tmp = $app->db->queryOneRecord("SELECT value FROM aps_instances_settings WHERE name = 'main_database_host' AND instance_id = '" . $app->db->quote($task['instance_id']) . "';"); $newdb_host = $tmp['value']; $tmp = $app->db->queryOneRecord("SELECT value FROM aps_instances_settings WHERE name = 'main_database_name' AND instance_id = '" . $app->db->quote($task['instance_id']) . "';"); $newdb_name = $tmp['value']; $tmp = $app->db->queryOneRecord("SELECT value FROM aps_instances_settings WHERE name = 'main_database_login' AND instance_id = '" . $app->db->quote($task['instance_id']) . "';"); $newdb_login = $tmp['value']; /* Test if the new mysql connection is laready working to ensure that db servers in multiserver setups get enough time to create the database */ if ($this->handle_type == 'install') { for ($n = 1; $n < 15; $n++) { $link = mysql_connect($newdb_host, $newdb_login, $newdb_pw); if (!$link) { unset($link); sleep(5); } else { unset($link); break; } } } $this->putenv[] = 'DB_' . $db_id . '_TYPE=mysql'; $this->putenv[] = 'DB_' . $db_id . '_NAME=' . $newdb_name; $this->putenv[] = 'DB_' . $db_id . '_LOGIN='******'DB_' . $db_id . '_PASSWORD='******'DB_' . $db_id . '_HOST=' . $newdb_host; $this->putenv[] = 'DB_' . $db_id . '_PORT=3306'; $this->putenv[] = 'DB_' . $db_id . '_VERSION=' . $mysqlver; }
/** * Read the metadata of a package and returns some content * * @param $id the internal ID of the package * @return array */ public function getPackageDetails($id) { global $app; $pkg = $app->db->queryOneRecord('SELECT * FROM aps_packages WHERE id = ' . $app->db->quote($id) . ';'); // Load in meta file if existing and register its namespaces $metafile = $this->interface_pkg_dir . '/' . $pkg['path'] . '/APP-META.xml'; if (!file_exists($metafile)) { return array('error' => 'The metafile for ' . $pkg['name'] . ' couldn\'t be found'); } $metadata = file_get_contents($metafile); $metadata = str_replace("xmlns=", "ns=", $metadata); $sxe = new SimpleXMLElement($metadata); $namespaces = $sxe->getDocNamespaces(true); foreach ($namespaces as $ns => $url) { $sxe->registerXPathNamespace($ns, $url); } $pkg['Summary'] = htmlspecialchars(parent::getXPathValue($sxe, '//summary')); $pkg['Homepage'] = parent::getXPathValue($sxe, '//homepage'); $pkg['Description'] = nl2br(htmlspecialchars(trim(parent::getXPathValue($sxe, '//description')))); $pkg['Config script'] = strtoupper(parent::getXPathValue($sxe, '//configuration-script-language')); $installed_size = parent::getXPathValue($sxe, '//installed-size'); $pkg['Installed Size'] = !empty($installed_size) ? parent::convertSize((int) $installed_size) : ''; // License $pkg['License need agree'] = parent::getXPathValue($sxe, '//license/@must-accept'); $pkg['License name'] = parent::getXPathValue($sxe, '//license/text/name'); // might be empty $pkg['License type'] = 'file'; // default type $pkg['License content'] = ''; // default license filename on local system $license_url = parent::getXPathValue($sxe, '//license/text/url'); if (!empty($license_url)) { $pkg['License type'] = 'url'; $pkg['License content'] = htmlspecialchars($license_url); } else { $lic = @file_get_contents($this->interface_pkg_dir . '/' . $pkg['path'] . '/LICENSE'); $pkg['License content'] = htmlentities($lic, ENT_QUOTES, 'ISO-8859-1'); } // Languages $languages = parent::getXPathValue($sxe, '//languages/language', true); $pkg['Languages'] = is_array($languages) ? implode(' ', $languages) : ''; // Icon $icon = parent::getXPathValue($sxe, '//icon/@path'); if (!empty($icon)) { // Using parse_url() to filter malformed URLs $path = dirname(parse_url($_SERVER['PHP_SELF'], PHP_URL_PATH)) . '/' . basename($this->interface_pkg_dir) . '/' . $pkg['path'] . '/' . basename((string) $icon); // nginx: if $_SERVER['PHP_SELF'] is doubled, remove /sites/aps_packagedetails_show.php from beginning of path $path = preg_replace('@^/sites/aps_packagedetails_show.php(.*)@', '$1', $path); $pkg['Icon'] = $path; } else { $pkg['Icon'] = ''; } // Screenshots $screenshots = parent::getXPathValue($sxe, '//screenshot', true); if (!empty($screenshots)) { foreach ($screenshots as $screen) { // Using parse_url() to filter malformed URLs $path = dirname(parse_url($_SERVER['PHP_SELF'], PHP_URL_PATH)) . '/' . basename($this->interface_pkg_dir) . '/' . $pkg['path'] . '/' . basename((string) $screen['path']); // nginx: if $_SERVER['PHP_SELF'] is doubled, remove /sites/aps_packagedetails_show.php from beginning of path $path = preg_replace('@^/sites/aps_packagedetails_show.php(.*)@', '$1', $path); $pkg['Screenshots'][] = array('ScreenPath' => $path, 'ScreenDescription' => htmlspecialchars(trim((string) $screen->description))); } } else { $pkg['Screenshots'] = ''; } // if no screenshots are available, set the variable though // Changelog $changelog = parent::getXPathValue($sxe, '//changelog/version', true); if (!empty($changelog)) { foreach ($changelog as $change) { $entries = array(); foreach ($change->entry as $entry) { $entries[] = htmlspecialchars(trim((string) $entry)); } $pkg['Changelog'][] = array('ChangelogVersion' => (string) $change['version'], 'ChangelogDescription' => implode('<br />', $entries)); } } else { $pkg['Changelog'] = ''; } // PHP extensions $php_extensions = parent::getXPathValue($sxe, '//php:extension', true); $php_ext = ''; if (!empty($php_extensions)) { foreach ($php_extensions as $extension) { if (strtolower($extension) == 'php') { continue; } $php_ext .= $extension . ' '; } } $pkg['Requirements PHP extensions'] = trim($php_ext); // PHP bool options $pkg['Requirements PHP settings'] = ''; $php_bool_options = array('allow-url-fopen', 'file-uploads', 'magic-quotes-gpc', 'register-globals', 'safe-mode', 'short-open-tag'); foreach ($php_bool_options as $option) { $value = parent::getXPathValue($sxe, '//php:' . $option); if (!empty($value)) { $option = str_replace('-', '_', $option); $value = str_replace(array('false', 'true'), array('off', 'on'), $value); $pkg['Requirements PHP settings'][] = array('PHPSettingName' => $option, 'PHPSettingValue' => $value); } } // PHP integer value settings $memory_limit = parent::getXPathValue($sxe, '//php:memory-limit'); if (!empty($memory_limit)) { $pkg['Requirements PHP settings'][] = array('PHPSettingName' => 'memory_limit', 'PHPSettingValue' => parent::convertSize((int) $memory_limit)); } $max_exec_time = parent::getXPathValue($sxe, '//php:max-execution-time'); if (!empty($max_exec_time)) { $pkg['Requirements PHP settings'][] = array('PHPSettingName' => 'max-execution-time', 'PHPSettingValue' => $max_exec_time); } $post_max_size = parent::getXPathValue($sxe, '//php:post-max-size'); if (!empty($post_max_size)) { $pkg['Requirements PHP settings'][] = array('PHPSettingName' => 'post_max_size', 'PHPSettingValue' => parent::convertSize((int) $post_max_size)); } // Get supported PHP versions $pkg['Requirements Supported PHP versions'] = ''; $php_min_version = parent::getXPathValue($sxe, '//php:version/@min'); $php_max_not_including = parent::getXPathValue($sxe, '//php:version/@max-not-including'); if (!empty($php_min_version) && !empty($php_max_not_including)) { $pkg['Requirements Supported PHP versions'] = $php_min_version . ' - ' . $php_max_not_including; } else { if (!empty($php_min_version)) { $pkg['Requirements Supported PHP versions'] = '> ' . $php_min_version; } else { if (!empty($php_max_not_including)) { $pkg['Requirements Supported PHP versions'] = '< ' . $php_min_version; } } } // Database $db_id = parent::getXPathValue($sxe, '//db:id'); $db_server_type = parent::getXPathValue($sxe, '//db:server-type'); $db_min_version = parent::getXPathValue($sxe, '//db:server-min-version'); if (!empty($db_id)) { $db_server_type = str_replace('postgresql', 'PostgreSQL', $db_server_type); $db_server_type = str_replace('microsoft:sqlserver', 'MSSQL', $db_server_type); $db_server_type = str_replace('mysql', 'MySQL', $db_server_type); $pkg['Requirements Database'] = $db_server_type; if (!empty($db_min_version)) { $pkg['Requirements Database'] .= ' > ' . $db_min_version; } } else { $pkg['Requirements Database'] = ''; } return $pkg; }