From 1cc1c2ed092c46eb35893c1d85accb24cf43d7f9 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 11 May 2016 19:00:30 +0200 Subject: Still working in modularization cleanup and refinement --- inc/configmodule.inc.php | 515 ----------------------------------- inc/configmodule/adauth.inc.php | 74 ----- inc/configmodule/branding.inc.php | 55 ---- inc/configmodule/customodule.inc.php | 55 ---- inc/configmodule/ldapauth.inc.php | 76 ------ inc/configmodule/sshconfig.inc.php | 63 ----- inc/configtgz.inc.php | 317 --------------------- inc/database.inc.php | 1 + inc/message.inc.php | 4 +- inc/module.inc.php | 5 + inc/property.inc.php | 1 + inc/render.inc.php | 52 ++-- inc/request.inc.php | 5 +- inc/session.inc.php | 1 + inc/taskmanagercallback.inc.php | 8 + inc/up_json_encode.php | 4 +- inc/validator.inc.php | 1 + 17 files changed, 55 insertions(+), 1182 deletions(-) delete mode 100644 inc/configmodule.inc.php delete mode 100644 inc/configmodule/adauth.inc.php delete mode 100644 inc/configmodule/branding.inc.php delete mode 100644 inc/configmodule/customodule.inc.php delete mode 100644 inc/configmodule/ldapauth.inc.php delete mode 100644 inc/configmodule/sshconfig.inc.php delete mode 100644 inc/configtgz.inc.php (limited to 'inc') diff --git a/inc/configmodule.inc.php b/inc/configmodule.inc.php deleted file mode 100644 index 909136ee..00000000 --- a/inc/configmodule.inc.php +++ /dev/null @@ -1,515 +0,0 @@ - $title, - 'description' => $description, - 'group' => $group, - 'unique' => $unique, - 'sortOrder' => $sortOrder, - 'moduleClass' => $moduleClass, - 'wizardClass' => $wizardClass - ); - } - - /** - * Get fresh instance of ConfigModule subclass for given module type. - * - * @param string $moduleType name of module type - * @return \ConfigModule module instance - */ - public static function getInstance($moduleType) - { - self::loadDb(); - if (!isset(self::$moduleTypes[$moduleType])) - return false; - return new self::$moduleTypes[$moduleType]['moduleClass']; - } - - /** - * Get module instance from id. - * - * @param int $moduleId module id to get - * @return ConfigModule The requested module from DB, or false on error - */ - public static function get($moduleId) - { - $ret = Database::queryFirst("SELECT title, moduletype, filepath, contents, version FROM configtgz_module " - . " WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleId)); - if ($ret === false) - return false; - $instance = self::getInstance($ret['moduletype']); - if ($instance === false) - return false; - $instance->currentVersion = $ret['version']; - $instance->moduleArchive = $ret['filepath']; - $instance->moduleData = json_decode($ret['contents'], true); - $instance->moduleId = $moduleId; - $instance->moduleTitle = $ret['title']; - return $instance; - } - - /** - * Get module instances from module type. - * - * @param int $moduleType module type to get - * @return array The requested modules from DB, or false on error - */ - public static function getAll($moduleType = false) - { - if ($moduleType === false) { - $ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version FROM configtgz_module"); - } else { - $ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version FROM configtgz_module " - . " WHERE moduletype = :moduletype", array('moduletype' => $moduleType)); - } - if ($ret === false) - return false; - $list = array(); - while ($row = $ret->fetch(PDO::FETCH_ASSOC)) { - $instance = self::getInstance($row['moduletype']); - if ($instance === false) - return false; - $instance->currentVersion = $row['version']; - $instance->moduleArchive = $row['filepath']; - $instance->moduleData = json_decode($row['contents'], true); - $instance->moduleId = $row['moduleid']; - $instance->moduleTitle = $row['title']; - $list[] = $instance; - } - return $list; - } - - /** - * Get the module version. - * - * @return int module version - */ - protected abstract function moduleVersion(); - - /** - * Validate the module's configuration. - * - * @return boolean ok or not - */ - protected abstract function validateConfig(); - - /** - * Set module specific data. - * - * @param string $key key, name or id of data being set - * @param mixed $value Module specific data - * @return boolean true if data was successfully set, false otherwise (i.e. invalid data being set) - */ - public abstract function setData($key, $value); - - /** - * Get module specific data. - * Can be overridden by modules. - * - * @param string $key key, name or id of data to get, or false to get the raw moduleData array - * @return mixed Module specific data - */ - public function getData($key) - { - if ($key === false) - return $this->moduleData; - if (!is_array($this->moduleData) || !isset($this->moduleData[$key])) - return false; - return $this->moduleData[$key]; - } - - /** - * Module specific version of generate. - * - * @param string $tgz File name of tgz module to write final output to - * @param string $parent Parent task of this task - * @return array|boolean true if generation is completed immediately, - * a task struct if some task needs to be run for generation, - * false on error - */ - protected abstract function generateInternal($tgz, $parent); - - private final function createFileName() - { - return CONFIG_TGZ_LIST_DIR . '/modules/' - . $this->moduleType() . '_id-' . $this->moduleId . '__' . mt_rand() . '-' . time() . '.tgz'; - } - - /** - * Get module id (in db) - * - * @return int id - */ - public final function id() - { - return $this->moduleId; - } - - /** - * Get module title. - * - * @return string - */ - public final function title() - { - return $this->moduleTitle; - } - - /** - * Get module archive file name. - * - * @return string tgz file absolute path - */ - public final function archive() - { - return $this->moduleArchive; - } - - /** - * Get the module type. - * - * @return string module type - */ - public final function moduleType() - { - $name = get_class($this); - if ($name === false) - Util::traceError('ConfigModule::moduleType: get_class($this) returned false!'); - // ConfigModule_* - if (!preg_match('/^ConfigModule_(\w+)$/', $name, $out)) - Util::traceError('ConfigModule::moduleType: get_class($this) returned "' . $name . '"'); - return $out[1]; - } - - /** - * Insert this config module into DB. Only - * valid if the object was created using the creating constructor, - * not if the instance was created using a database entry (static get method). - * - * @param string $title display name of the module - * @return boolean true if inserted successfully, false if module config is invalid - */ - public final function insert($title) - { - if ($this->moduleId !== 0) - Util::traceError('ConfigModule::insert called when moduleId != 0'); - if (!$this->validateConfig()) - return false; - $this->moduleTitle = $title; - // Insert - Database::exec("INSERT INTO configtgz_module (title, moduletype, filepath, contents, version, status) " - . " VALUES (:title, :type, '', :contents, :version, :status)", array( - 'title' => $title, - 'type' => $this->moduleType(), - 'contents' => json_encode($this->moduleData), - 'version' => 0, - 'status' => 'MISSING' - )); - $this->moduleId = Database::lastInsertId(); - if (!is_numeric($this->moduleId)) - Util::traceError('Inserting new config module into DB did not yield a numeric insert id'); - $this->moduleArchive = $this->createFileName(); - Database::exec("UPDATE configtgz_module SET filepath = :path WHERE moduleid = :moduleid LIMIT 1", array( - 'path' => $this->moduleArchive, - 'moduleid' => $this->moduleId - )); - return true; - } - - /** - * Update the given module in database. This will not regenerate - * the module's tgz. - * - * @return boolean true on success, false otherwise - */ - public final function update($title) - { - if ($this->moduleId === 0) - Util::traceError('ConfigModule::update called when moduleId == 0'); - if (empty($title)) - $title = $this->moduleTitle; - if (!$this->validateConfig()) - return false; - // Update - Database::exec("UPDATE configtgz_module SET title = :title, contents = :contents, status = :status " - . " WHERE moduleid = :moduleid LIMIT 1", array( - 'moduleid' => $this->moduleId, - 'title' => $title, - 'contents' => json_encode($this->moduleData), - 'status' => 'OUTDATED' - )); - return true; - } - - /** - * Generate the module's tgz, don't wait for completion. - * Updating the database etc. will happen later through a callback. - * - * @param boolean $deleteOnError if true, the db entry will be deleted if generation failed - * @param string $parent Parent task of this task - * @param int $timeoutMs maximum time in milliseconds we wait for completion - * @return string|boolean task id if deferred generation was started, - * true if generation succeeded (without using a task or within $timeoutMs) - * false on error - */ - public final function generate($deleteOnError, $parent = NULL, $timeoutMs = 0) - { - if ($this->moduleId === 0 || $this->moduleTitle === false) - Util::traceError('ConfigModule::generateAsync called on uninitialized/uninserted module!'); - $tmpTgz = '/tmp/bwlp-id-' . $this->moduleId . '_' . mt_rand() . '_' . time() . '.tgz'; - $ret = $this->generateInternal($tmpTgz, $parent); - // Wait for generation if requested - if ($timeoutMs > 0 && isset($ret['id']) && !Taskmanager::isFinished($ret)) - $ret = Taskmanager::waitComplete($ret, $timeoutMs); - if ($ret === true || (isset($ret['statusCode']) && $ret['statusCode'] === TASK_FINISHED)) { - // Already Finished - if (file_exists($this->moduleArchive) && !file_exists($tmpTgz)) - $tmpTgz = false; // If generateInternal succeeded and there's no tmpTgz, it means the file didn't have to be updated - return $this->markUpdated($tmpTgz); - } - if (!is_array($ret) || !isset($ret['id']) || Taskmanager::isFailed($ret)) { - if (is_array($ret)) // Failed - Taskmanager::addErrorMessage($ret); - if ($deleteOnError) - $this->delete(); - else - $this->markFailed(); - return false; - } - // Still running, add callback - TaskmanagerCallback::addCallback($ret, 'cbConfModCreated', array( - 'moduleid' => $this->moduleId, - 'deleteOnError' => $deleteOnError, - 'tmpTgz' => $tmpTgz - )); - return $ret['id']; - } - - /** - * Delete the module. - */ - public final function delete() - { - if ($this->moduleId === 0) - Util::traceError('ConfigModule::delete called with invalid module id!'); - $ret = Database::exec("DELETE FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array( - 'moduleid' => $this->moduleId - ), true) !== false; - if ($ret !== false) { - if ($this->moduleArchive) - Taskmanager::submit('DeleteFile', array('file' => $this->moduleArchive), true); - $this->moduleId = 0; - $this->moduleData = false; - $this->moduleTitle = false; - $this->moduleArchive = false; - } - return $ret; - } - - private final function markUpdated($tmpTgz) - { - if ($this->moduleId === 0) - Util::traceError('ConfigModule::markUpdated called with invalid module id!'); - if ($this->moduleArchive === false) - $this->moduleArchive = $this->createFileName(); - // Move file - if ($tmpTgz === false) { - if (!file_exists($this->moduleArchive)) { - EventLog::failure('ConfigModule::markUpdated for "' . $this->moduleTitle . '" called with no tmpTgz and no existing tgz!'); - $this->markFailed(); - return false; - } - } else { - $task = Taskmanager::submit('MoveFile', array( - 'source' => $tmpTgz, - 'destination' => $this->moduleArchive - )); - $task = Taskmanager::waitComplete($task, 5000); - if (Taskmanager::isFailed($task) || !Taskmanager::isFinished($task)) { - if (!API && !AJAX) - Taskmanager::addErrorMessage($task); - else - EventLog::failure('Could not move ' . $tmpTgz . ' to ' . $this->moduleArchive . ' while generating "' . $this->moduleTitle . '"'); - $this->markFailed(); - return false; - } - } - // Update DB entry - $retval = Database::exec("UPDATE configtgz_module SET filepath = :filename, version = :version, status = 'OK' WHERE moduleid = :id LIMIT 1", array( - 'id' => $this->moduleId, - 'filename' => $this->moduleArchive, - 'version' => $this->moduleVersion() - )) !== false; - // Update related config.tgzs - $configs = ConfigTgz::getAllForModule($this->moduleId); - foreach ($configs as $config) { - $config->markOutdated(); - $config->generate(); - } - return $retval; - } - - private final function markFailed() - { - if ($this->moduleId === 0) - Util::traceError('ConfigModule::markFailed called with invalid module id!'); - if ($this->moduleArchive === false) - $this->moduleArchive = $this->createFileName(); - if (!file_exists($this->moduleArchive)) - $status = 'MISSING'; - else - $status = 'OUTDATED'; - return Database::exec("UPDATE configtgz_module SET filepath = :filename, status = :status WHERE moduleid = :id LIMIT 1", array( - 'id' => $this->moduleId, - 'filename' => $this->moduleArchive, - 'status' => $status - )) !== false; - } - - ################# Callbacks ############## - - /** - * Event callback for when the server ip changed. - * Override this if you need to handle this, otherwise - * the base implementation does nothing. - */ - public function event_serverIpChanged() - { - // Do::Nothing() - } - - ##################### STATIC CALLBACKS ##################### - - /** - * Will be called if the server's IP address changes. The event will be propagated - * to all config module classes so action can be taken if appropriate. - */ - public static function serverIpChanged() - { - self::loadDb(); - $list = self::getAll(); - foreach ($list as $mod) { - $mod->event_serverIpChanged(); - } - } - - /** - * Called when (re)generating a config module failed, so we can - * update the status in the DB and add a server log entry. - * - * @param array $task - * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz' - */ - public static function generateFailed($task, $args) - { - if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) { - EventLog::warning('Ignoring generateFailed event as it has no moduleid assigned.'); - return; - } - $module = self::get($args['moduleid']); - if ($module === false) { - EventLog::warning('generateFailed callback for module id ' . $args['moduleid'] . ', but no instance could be generated.'); - return; - } - if (isset($task['data']['error'])) - $error = $task['data']['error']; - elseif (isset($task['data']['messages'])) - $error = $task['data']['messages']; - else - $error = ''; - EventLog::failure("Generating module '" . $module->moduleTitle . "' failed.", $error); - if ($args['deleteOnError']) - $module->delete(); - else - $module->markFailed(); - } - - /** - * (Re)generating a config module succeeded. Update db entry. - * - * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz' - */ - public static function generateSucceeded($args) - { - if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) { - EventLog::warning('Ignoring generateSucceeded event as it has no moduleid assigned.'); - return; - } - $module = self::get($args['moduleid']); - if ($module === false) { - EventLog::warning('generateSucceeded callback for module id ' . $args['moduleid'] . ', but no instance could be generated.'); - return; - } - if (isset($args['tmpTgz'])) - $module->markUpdated($args['tmpTgz']); - else - $module->markUpdated(false); - } - -} diff --git a/inc/configmodule/adauth.inc.php b/inc/configmodule/adauth.inc.php deleted file mode 100644 index efc8afd7..00000000 --- a/inc/configmodule/adauth.inc.php +++ /dev/null @@ -1,74 +0,0 @@ -id(), $parent); - $config = $this->moduleData; - if (isset($config['certificate']) && !is_string($config['certificate'])) { - unset($config['certificate']); - } - if (preg_match('/^([^\:]+)\:(\d+)$/', $config['server'], $out)) { - $config['server'] = $out[1]; - $config['adport'] = $out[2]; - } else { - if (isset($config['certificate'])) { - $config['adport'] = 636; - } else { - $config['adport'] = 389; - } - } - $config['parentTask'] = $parent; - $config['failOnParentFail'] = false; - $config['proxyip'] = Property::getServerIp(); - $config['proxyport'] = 3100 + $this->id(); - $config['filename'] = $tgz; - $config['moduleid'] = $this->id(); - return Taskmanager::submit('CreateLdapConfig', $config); - } - - protected function moduleVersion() - { - return self::VERSION; - } - - protected function validateConfig() - { - // Check if required fields are filled - return Util::hasAllKeys($this->moduleData, self::$REQUIRED_FIELDS); - } - - public function setData($key, $value) - { - if (!in_array($key, self::$REQUIRED_FIELDS) && !in_array($key, self::$OPTIONAL_FIELDS)) - return false; - $this->moduleData[$key] = $value; - return true; - } - - // ############## Callbacks ############################# - - /** - * Server IP changed - rebuild all AD modules. - */ - public function event_serverIpChanged() - { - $this->generate(false); - } - -} diff --git a/inc/configmodule/branding.inc.php b/inc/configmodule/branding.inc.php deleted file mode 100644 index b2f28c2f..00000000 --- a/inc/configmodule/branding.inc.php +++ /dev/null @@ -1,55 +0,0 @@ -validateConfig()) { - return $this->archive() !== false && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked... - } - $task = Taskmanager::submit('MoveFile', array( - 'source' => $this->tmpFile, - 'destination' => $tgz, - 'parentTask' => $parent, - 'failOnParentFail' => false - )); - return $task; - } - - protected function moduleVersion() - { - return self::VERSION; - } - - protected function validateConfig() - { - return $this->tmpFile !== false && file_exists($this->tmpFile); - } - - public function setData($key, $value) - { - if ($key !== 'tmpFile' || !is_string($value) || !file_exists($value)) - return false; - $this->tmpFile = $value; - } - - public function getData($key) - { - return false; - } - -} diff --git a/inc/configmodule/customodule.inc.php b/inc/configmodule/customodule.inc.php deleted file mode 100644 index 31796e9c..00000000 --- a/inc/configmodule/customodule.inc.php +++ /dev/null @@ -1,55 +0,0 @@ -validateConfig()) { - return $this->archive() !== false && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked... - } - $task = Taskmanager::submit('MoveFile', array( - 'source' => $this->tmpFile, - 'destination' => $tgz, - 'parentTask' => $parent, - 'failOnParentFail' => false - )); - return $task; - } - - protected function moduleVersion() - { - return self::VERSION; - } - - protected function validateConfig() - { - return $this->tmpFile !== false && file_exists($this->tmpFile); - } - - public function setData($key, $value) - { - if ($key !== 'tmpFile' || !file_exists($value)) - return false; - $this->tmpFile = $value; - } - - public function getData($key) - { - return false; - } - -} diff --git a/inc/configmodule/ldapauth.inc.php b/inc/configmodule/ldapauth.inc.php deleted file mode 100644 index 67b1997a..00000000 --- a/inc/configmodule/ldapauth.inc.php +++ /dev/null @@ -1,76 +0,0 @@ -id(), $parent); - $config = $this->moduleData; - if (isset($config['certificate']) && !is_string($config['certificate'])) { - unset($config['certificate']); - } - if (preg_match('/^([^\:]+)\:(\d+)$/', $config['server'], $out)) { - $config['server'] = $out[1]; - $config['adport'] = $out[2]; // sic! - } else { - if (isset($config['certificate'])) { - $config['adport'] = 636; - } else { - $config['adport'] = 389; - } - } - $config['parentTask'] = $parent; - $config['failOnParentFail'] = false; - $config['proxyip'] = Property::getServerIp(); - $config['proxyport'] = 3100 + $this->id(); - $config['filename'] = $tgz; - $config['moduleid'] = $this->id(); - $config['plainldap'] = true; - return Taskmanager::submit('CreateLdapConfig', $config); - } - - protected function moduleVersion() - { - return self::VERSION; - } - - protected function validateConfig() - { - // Check if required fields are filled - return Util::hasAllKeys($this->moduleData, self::$REQUIRED_FIELDS); - } - - public function setData($key, $value) - { - if (!in_array($key, self::$REQUIRED_FIELDS) && !in_array($key, self::$OPTIONAL_FIELDS)) - return false; - $this->moduleData[$key] = $value; - return true; - } - - // ############## Callbacks ############################# - - /** - * Server IP changed - rebuild all LDAP modules. - */ - public function event_serverIpChanged() - { - error_log('Calling generate on ' . $this->title()); - $this->generate(false); - } - -} diff --git a/inc/configmodule/sshconfig.inc.php b/inc/configmodule/sshconfig.inc.php deleted file mode 100644 index 853acf6a..00000000 --- a/inc/configmodule/sshconfig.inc.php +++ /dev/null @@ -1,63 +0,0 @@ -validateConfig()) - return false; - $config = $this->moduleData + array( - 'filename' => $tgz, - 'failOnParentFail' => false, - 'parent' => $parent - ); - // Create config module, which will also check if the pubkey is valid - return Taskmanager::submit('SshdConfigGenerator', $config); - } - - protected function moduleVersion() - { - return self::VERSION; - } - - protected function validateConfig() - { - return isset($this->moduleData['publicKey']) && isset($this->moduleData['allowPasswordLogin']) && isset($this->moduleData['listenPort']); - } - - public function setData($key, $value) - { - switch ($key) { - case 'publicKey': - break; - case 'allowPasswordLogin': - if ($value === true || $value === 'yes') - $value = 'yes'; - elseif ($value === false || $value === 'no') - $value = 'no'; - else - return false; - break; - case 'listenPort': - if (!is_numeric($value) || $value < 1 || $value > 65535) - return false; - break; - default: - return false; - } - $this->moduleData[$key] = $value; - return true; - } - -} diff --git a/inc/configtgz.inc.php b/inc/configtgz.inc.php deleted file mode 100644 index b51d2787..00000000 --- a/inc/configtgz.inc.php +++ /dev/null @@ -1,317 +0,0 @@ -configId; - } - - public function title() - { - return $this->configTitle; - } - - public function areAllModulesUpToDate() - { - if (!$this->configId > 0) - Util::traceError('ConfigTgz::areAllModulesUpToDate called on un-inserted config.tgz!'); - foreach ($this->modules as $module) { - if (!empty($module['filepath']) && file_exists($module['filepath'])) { - if ($module['status'] !== 'OK') - return false; - } else { - return false; - } - } - return true; - } - - public function isActive() - { - return readlink(CONFIG_HTTP_DIR . '/default/config.tgz') === $this->file; - } - - public function getModuleIds() - { - $ret = array(); - foreach ($this->modules as $module) { - $ret[] = $module['moduleid']; - } - return $ret; - } - - public function update($title, $moduleIds) - { - if (!is_array($moduleIds)) - return false; - $this->configTitle = $title; - $this->modules = array(); - // Get all modules to put in config - $idstr = '0'; // Passed directly in query. Make sure no SQL injection is possible - foreach ($moduleIds as $module) { - $idstr .= ',' . (int)$module; // Casting to int should make it safe - } - $res = Database::simpleQuery("SELECT moduleid, filepath, status FROM configtgz_module WHERE moduleid IN ($idstr)"); - // Delete old connections - Database::exec("DELETE FROM configtgz_x_module WHERE configid = :configid", array('configid' => $this->configId)); - // Make connection - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - Database::exec("INSERT INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array( - 'configid' => $this->configId, - 'moduleid' => $row['moduleid'] - )); - $this->modules[] = $row; - } - // Update name - Database::exec("UPDATE configtgz SET title = :title, status = :status WHERE configid = :configid LIMIT 1", array( - 'configid' => $this->configId, - 'title' => $title, - 'status' => 'OUTDATED' - )); - return true; - } - - public static function insert($title, $moduleIds) - { - if (!is_array($moduleIds)) - return false; - $instance = new ConfigTgz; - $instance->configTitle = $title; - // Create output file name (config.tgz) - do { - $instance->file = CONFIG_TGZ_LIST_DIR . '/config-' . Util::sanitizeFilename($instance->configTitle) . '-' . mt_rand() . '-' . time() . '.tgz'; - } while (file_exists($instance->file)); - Database::exec("INSERT INTO configtgz (title, filepath, status) VALUES (:title, :filepath, :status)", array( - 'title' => $instance->configTitle, - 'filepath' => $instance->file, - 'status' => 'MISSING' - )); - $instance->configId = Database::lastInsertId(); - $instance->modules = array(); - // Get all modules to put in config - $idstr = '0'; // Passed directly in query. Make sure no SQL injection is possible - foreach ($moduleIds as $module) { - $idstr .= ',' . (int)$module; // Casting to int should make it safe - } - $res = Database::simpleQuery("SELECT moduleid, filepath, status FROM configtgz_module WHERE moduleid IN ($idstr)"); - // Make connection - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - Database::exec("INSERT INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array( - 'configid' => $instance->configId, - 'moduleid' => $row['moduleid'] - )); - $instance->modules[] = $row; - } - return $instance; - } - - public static function get($configId) - { - $ret = Database::queryFirst("SELECT configid, title, filepath FROM configtgz WHERE configid = :configid", array( - 'configid' => $configId - )); - if ($ret === false) - return false; - $instance = new ConfigTgz; - $instance->configId = $ret['configid']; - $instance->configTitle = $ret['title']; - $instance->file = $ret['filepath']; - $ret = Database::simpleQuery("SELECT moduleid, filepath, status FROM configtgz_x_module " - . " INNER JOIN configtgz_module USING (moduleid) " - . " WHERE configid = :configid", array('configid' => $instance->configId)); - $instance->modules = array(); - while ($row = $ret->fetch(PDO::FETCH_ASSOC)) { - $instance->modules[] = $row; - } - return $instance; - } - - public static function getAllForModule($moduleId) - { - $res = Database::simpleQuery("SELECT configid, title, filepath FROM configtgz_x_module " - . " INNER JOIN configtgz USING (configid) " - . " WHERE moduleid = :moduleid", array( - 'moduleid' => $moduleId - )); - if ($res === false) - return false; - $list = array(); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $instance = new ConfigTgz; - $instance->configId = $row['configid']; - $instance->configTitle = $row['title']; - $instance->file = $row['filepath']; - $innerRes = Database::simpleQuery("SELECT moduleid, filepath, status FROM configtgz_x_module " - . " INNER JOIN configtgz_module USING (moduleid) " - . " WHERE configid = :configid", array('configid' => $instance->configId)); - $instance->modules = array(); - while ($innerRow = $innerRes->fetch(PDO::FETCH_ASSOC)) { - $instance->modules[] = $innerRow; - } - $list[] = $instance; - } - return $list; - } - - /** - * Called when (re)generating a config tgz failed, so we can - * update the status in the DB and add a server log entry. - * - * @param array $task - * @param array $args contains 'configid' and optionally 'deleteOnError' - */ - public static function generateFailed($task, $args) - { - if (!isset($args['configid']) || !is_numeric($args['configid'])) { - EventLog::warning('Ignoring generateFailed event as it has no configid assigned.'); - return; - } - $config = self::get($args['configid']); - if ($config === false) { - EventLog::warning('generateFailed callback for config id ' . $args['configid'] . ', but no instance could be generated.'); - return; - } - if (isset($task['data']['error'])) - $error = $task['data']['error']; - elseif (isset($task['data']['messages'])) - $error = $task['data']['messages']; - else - $error = ''; - EventLog::failure("Generating config.tgz '" . $config->configTitle . "' failed.", $error); - if ($args['deleteOnError']) - $config->delete(); - else - $config->markFailed(); - } - - /** - * (Re)generating a config tgz succeeded. Update db entry. - * - * @param array $args contains 'configid' and optionally 'deleteOnError' - */ - public static function generateSucceeded($args) - { - if (!isset($args['configid']) || !is_numeric($args['configid'])) { - EventLog::warning('Ignoring generateSucceeded event as it has no configid assigned.'); - return; - } - $config = self::get($args['configid']); - if ($config === false) { - EventLog::warning('generateSucceeded callback for config id ' . $args['configid'] . ', but no instance could be generated.'); - return; - } - $config->markUpdated(); - } - - /** - * - * @param type $deleteOnError - * @param type $timeoutMs - * @return string - OK (success) - * - OUTDATED (updating failed, but old version still exists) - * - MISSING (failed and no old version available) - */ - public function generate($deleteOnError = false, $timeoutMs = 0) - { - if (!($this->configId > 0) || !is_array($this->modules) || $this->file === false) - Util::traceError ('configId <= 0 or modules not array in ConfigTgz::rebuild()'); - $files = array(); - foreach ($this->modules as $module) { - if (!empty($module['filepath']) && file_exists($module['filepath'])) - $files[] = $module['filepath']; - } - // Hand over to tm - $task = Taskmanager::submit('RecompressArchive', array( - 'inputFiles' => $files, - 'outputFile' => $this->file - )); - // Wait for completion - if ($timeoutMs > 0 && !Taskmanager::isFailed($task) && !Taskmanager::isFinished($task)) - $task = Taskmanager::waitComplete($task, $timeoutMs); - if ($task === true || (isset($task['statusCode']) && $task['statusCode'] === TASK_FINISHED)) { - // Success! - $this->markUpdated(); - return true; - } - if (!is_array($task) || !isset($task['id']) || Taskmanager::isFailed($task)) { - // Failed... - Taskmanager::addErrorMessage($task); - if (!$deleteOnError) - $this->markFailed(); - else - $this->delete(); - return false; - } - // Still running, add callback - TaskmanagerCallback::addCallback($task, 'cbConfTgzCreated', array( - 'configid' => $this->configId, - 'deleteOnError' => $deleteOnError - )); - return $task['id']; - } - - public function delete() - { - if ($this->configId === 0) - Util::traceError('ConfigTgz::delete called with invalid config id!'); - $ret = Database::exec("DELETE FROM configtgz WHERE configid = :configid LIMIT 1", array( - 'configid' => $this->configId - ), true) !== false; - if ($ret !== false) { - if ($this->file !== false) - Taskmanager::submit('DeleteFile', array('file' => $this->file), true); - $this->configId = 0; - $this->modules = false; - $this->file = false; - } - return $ret; - } - - public function markOutdated() - { - if ($this->configId === 0) - Util::traceError('ConfigTgz::markOutdated called with invalid config id!'); - return $this->mark('OUTDATED'); - } - - private function markUpdated() - { - if ($this->configId === 0) - Util::traceError('ConfigTgz::markUpdated called with invalid config id!'); - Event::activeConfigChanged(); - if ($this->areAllModulesUpToDate()) - return $this->mark('OK'); - return $this->mark('OUTDATED'); - } - - private function markFailed() - { - if ($this->configId === 0) - Util::traceError('ConfigTgz::markFailed called with invalid config id!'); - if ($this->file === false || !file_exists($this->file)) - return $this->mark('MISSING'); - return $this->mark('OUTDATED'); - } - - private function mark($status) - { - Database::exec("UPDATE configtgz SET status = :status WHERE configid = :configid LIMIT 1", array( - 'configid' => $this->configId, - 'status' => $status - )); - return $status; - } - -} diff --git a/inc/database.inc.php b/inc/database.inc.php index 735b2181..c3901453 100644 --- a/inc/database.inc.php +++ b/inc/database.inc.php @@ -113,6 +113,7 @@ class Database return false; Util::traceError("Database Error: \n" . $e->getMessage()); } + return false; } /** diff --git a/inc/message.inc.php b/inc/message.inc.php index d6a62f4e..15e89041 100644 --- a/inc/message.inc.php +++ b/inc/message.inc.php @@ -55,6 +55,7 @@ class Message */ public static function renderList() { + self::$flushed = true; if (empty(self::$list)) return; // Ajax @@ -75,11 +76,10 @@ class Message foreach ($item['params'] as $index => $text) { $message = str_replace('{{' . $index . '}}', '' . htmlspecialchars($text) . '', $message); } - Render::addTemplate('messagebox-' . $item['type'], array('message' => $message),'main'); + Render::addTemplate('messagebox-' . $item['type'], array('message' => $message), 'main'); self::$alreadyDisplayed[] = $item; } self::$list = array(); - self::$flushed = true; } /** diff --git a/inc/module.inc.php b/inc/module.inc.php index 261c2990..894bc0f6 100644 --- a/inc/module.inc.php +++ b/inc/module.inc.php @@ -178,4 +178,9 @@ class Module return Dictionary::getCategoryName($this->category); } + public function getDir() + { + return 'modules/' . $this->name; + } + } diff --git a/inc/property.inc.php b/inc/property.inc.php index 0cb57f81..13e3c66d 100644 --- a/inc/property.inc.php +++ b/inc/property.inc.php @@ -66,6 +66,7 @@ class Property EventLog::info('Server IP changed from ' . self::getServerIp() . ' to ' . $value . ($automatic ? ' (auto detected)' : '')); self::set('server-ip', $value); Event::serverIpChanged(); + return true; } public static function getBootMenu() diff --git a/inc/render.inc.php b/inc/render.inc.php index e3a23f23..5fc5be92 100644 --- a/inc/render.inc.php +++ b/inc/render.inc.php @@ -18,7 +18,7 @@ class Render private static $mustache = false; private static $body = ''; private static $header = ''; - private static $dashboard = ''; + private static $dashboard = false; private static $footer = ''; private static $title = ''; private static $templateCache = array(); @@ -28,7 +28,16 @@ class Render { if (self::$mustache !== false) Util::traceError('Called Render::init() twice!'); - self::$mustache = new Mustache_Engine; + $options = array(); + $tmp = '/tmp/bwlp-cache'; + $dir = is_dir($tmp); + if (!$dir) { + @mkdir($tmp, 0755, false); + } + if (($dir || is_dir($tmp)) && is_writable($tmp)) { + $options['cache'] = $tmp; + } + self::$mustache = new Mustache_Engine($options); } /** @@ -40,7 +49,6 @@ class Render $zip = isset($_SERVER['HTTP_ACCEPT_ENCODING']) && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false); if ($zip) ob_start(); - $page = strtolower($_GET['do']); echo ' @@ -63,7 +71,7 @@ class Render ' ', - self::$dashboard, + (self::$dashboard !== false ? self::parse('main-menu', self::$dashboard, 'main') : ''), '
', self::$body @@ -168,18 +176,20 @@ class Render /** * Parse template with given params and return; do not add to body * @param string $template name of template, relative to templates/, without .html extension + * @param array $params tags to render into template + * @param string $module name of module to load template from; defaults to currently active module * @return string Rendered template */ public static function parse($template, $params = false, $module = false) { + if ($module === false) { + $module = Page::getModule()->getIdentifier(); + } // Load html snippet - $html = self::getTemplate($template,$module); + $html = self::getTemplate($template, $module); if ($html === false) { return '

Template ' . htmlspecialchars($template) . '

' . nl2br(htmlspecialchars(print_r($params, true))) . '
'; } - if($module === false) { - $module = Page::getModule()->getIdentifier(); - } if (!is_array($params)) { $params = array(); } @@ -201,8 +211,10 @@ class Render } // Always add token to parameter list $params['token'] = Session::get('token'); - // Likewise, add currently selected language (its two letter code) to params - $params['current_lang'] = LANG; + if (defined('LANG')) { + // Likewise, add currently selected language (its two letter code) to params + $params['current_lang'] = LANG; + } // Add desired password field type $params['password_type'] = Property::getPasswordFieldType(); // Return rendered html @@ -242,20 +254,18 @@ class Render /** * Private helper: Load the given template and return it */ - private static function getTemplate($template, $module = false) + private static function getTemplate($template, $module) { - if (isset(self::$templateCache[$template])) { - return self::$templateCache[$template]; - } - // Select current module - if(!$module){ - $module = strtolower(empty($_REQUEST['do']) ? 'Main' : $_REQUEST['do']); + $id = "$template/$module"; + if (isset(self::$templateCache[$id])) { + return self::$templateCache[$id]; } // Load from disk $data = @file_get_contents('modules/' . $module . '/templates/' . $template . '.html'); - if ($data === false) - $data = 'Non-existent template ' . $template . ' requested!'; - self::$templateCache[$template] = & $data; + if ($data === false) { + $data = 'Non-existent/unreadable template ' . $template . ' requested!'; + } + self::$templateCache[$id] =& $data; return $data; } @@ -264,7 +274,7 @@ class Render */ public static function setDashboard($params) { - self::$dashboard = self::parse('main-menu', $params, 'main'); + self::$dashboard = $params; } } diff --git a/inc/request.inc.php b/inc/request.inc.php index 604a2b0e..f46210af 100644 --- a/inc/request.inc.php +++ b/inc/request.inc.php @@ -5,11 +5,12 @@ */ class Request { - + /** - * + * * @param string $key Key of field to get from $_GET * @param string $default Value to return if $_GET does not contain $key + * @param string $type if the parameter exists, cast it to given type * @return mixed Field from $_GET, or $default if not set */ public static function get($key, $default = false, $type = false) diff --git a/inc/session.inc.php b/inc/session.inc.php index a0f8ab4c..b4299e06 100644 --- a/inc/session.inc.php +++ b/inc/session.inc.php @@ -41,6 +41,7 @@ class Session if (self::readSessionData()) return true; // Loading session data failed self::delete(); + return false; } public static function get($key) diff --git a/inc/taskmanagercallback.inc.php b/inc/taskmanagercallback.inc.php index cec763fb..7d4e79f3 100644 --- a/inc/taskmanagercallback.inc.php +++ b/inc/taskmanagercallback.inc.php @@ -124,6 +124,10 @@ class TaskmanagerCallback */ public static function cbConfModCreated($task, $args) { + $mod = Module::get('sysconfig'); + if ($mod === false) + return; + $mod->activate(); if (Taskmanager::isFailed($task)) { ConfigModule::generateFailed($task, $args); } else { @@ -139,6 +143,10 @@ class TaskmanagerCallback */ public static function cbConfTgzCreated($task, $args) { + $mod = Module::get('sysconfig'); + if ($mod === false) + return; + $mod->activate(); if (Taskmanager::isFailed($task)) { ConfigTgz::generateFailed($task, $args); } else { diff --git a/inc/up_json_encode.php b/inc/up_json_encode.php index c33cb012..0f5776c2 100644 --- a/inc/up_json_encode.php +++ b/inc/up_json_encode.php @@ -164,7 +164,7 @@ function up_json_encode($var, $options = 0, $_indent = "") } elseif (is_float($var)) { if (is_nan($var) || is_infinite($var)) { ${'.json_last_error'} = JSON_ERROR_INF_OR_NAN; - return; + return false; } else { $json = "$var"; } @@ -174,7 +174,7 @@ function up_json_encode($var, $options = 0, $_indent = "") else { trigger_error("up_json_encode: don't know what a '" . gettype($var) . "' is.", E_USER_WARNING); ${'.json_last_error'} = JSON_ERROR_UNSUPPORTED_TYPE; - return; + return false; } #-- done diff --git a/inc/validator.inc.php b/inc/validator.inc.php index 6eac80f9..23debd2c 100644 --- a/inc/validator.inc.php +++ b/inc/validator.inc.php @@ -32,6 +32,7 @@ class Validator default: Util::traceError('Unknown validation method: ' . $data[0]); } + return false; // make code inspector happy - doesn't know traceError doesn't return } /** -- cgit v1.2.3-55-g7522