summaryrefslogtreecommitdiffstats
path: root/inc
diff options
context:
space:
mode:
authorSimon Rettberg2015-01-26 20:28:49 +0100
committerSimon Rettberg2015-01-26 20:28:49 +0100
commit5347ecd5ddb1803ec1c43240bafc84f5c427f855 (patch)
tree7a852cdaa44599dab5f4c98b9daa7c6443d81024 /inc
parentFix stupid bug in update query, check DB version before handling callbacks (diff)
downloadslx-admin-5347ecd5ddb1803ec1c43240bafc84f5c427f855.tar.gz
slx-admin-5347ecd5ddb1803ec1c43240bafc84f5c427f855.tar.xz
slx-admin-5347ecd5ddb1803ec1c43240bafc84f5c427f855.zip
Add configtgz class. Fix dozens of bugs
Diffstat (limited to 'inc')
-rw-r--r--inc/configmodule.inc.php67
-rw-r--r--inc/configmodule/adauth.inc.php1
-rw-r--r--inc/configmodule/branding.inc.php6
-rw-r--r--inc/configtgz.inc.php160
-rw-r--r--inc/event.inc.php5
-rw-r--r--inc/taskmanager.inc.php1
-rw-r--r--inc/util.inc.php40
7 files changed, 267 insertions, 13 deletions
diff --git a/inc/configmodule.inc.php b/inc/configmodule.inc.php
index 5eff92ba..6fd9e1b8 100644
--- a/inc/configmodule.inc.php
+++ b/inc/configmodule.inc.php
@@ -115,6 +115,33 @@ abstract class ConfigModule
}
/**
+ * 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)
+ {
+ $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
@@ -164,6 +191,16 @@ abstract class ConfigModule
}
/**
+ * Get module title.
+ *
+ * @return string
+ */
+ public final function title()
+ {
+ return $this->moduleTitle;
+ }
+
+ /**
* Get module archive file name.
*
* @return string tgz file absolute path
@@ -243,8 +280,12 @@ abstract class ConfigModule
// 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))
- return $this->markUpdated($tmpTgz); // Finished
+ if ($ret === true || (isset($ret['statusCode']) && $ret['statusCode'] === TASK_FINISHED)) {
+ // Already Finished
+ if (file_exists($this->moduleArchive) && !file_exists($tmpTgz))
+ $tmpTgz = false;
+ return $this->markUpdated($tmpTgz);
+ }
if (!is_array($ret) || !isset($ret['id']) || Taskmanager::isFailed($ret)) {
if (is_array($ret)) // Failed
Taskmanager::addErrorMessage($ret);
@@ -271,8 +312,8 @@ abstract class ConfigModule
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' => $id
- )) !== false;
+ 'moduleid' => $this->moduleId
+ ), true) !== false;
if ($ret !== false) {
if ($this->moduleArchive)
Taskmanager::submit('DeleteFile', array('file' => $this->moduleArchive), true);
@@ -281,6 +322,7 @@ abstract class ConfigModule
$this->moduleTitle = false;
$this->moduleArchive = false;
}
+ return $ret;
}
private final function markUpdated($tmpTgz)
@@ -312,11 +354,17 @@ abstract class ConfigModule
}
}
// Update DB entry
- return Database::exec("UPDATE configtgz_module SET filepath = :filename, version = :version, status = 'OK' WHERE moduleid = :id LIMIT 1", array(
+ $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->generate();
+ }
+ return $retval;
}
private final function markFailed()
@@ -356,11 +404,18 @@ abstract class ConfigModule
*/
public static function serverIpChanged()
{
- self::loadDb();
+ self::loadDb(); // Quick hack: Hard code AdAuth, should be a property of the config module class....
+ $list = self::getAll('AdAuth');
+ error_log('Changed: Telling ' - count($list) . ' modules');
+ foreach ($list as $mod) {
+ $mod->event_serverIpChanged();
+ }
+ /* // TODO: Make this work
foreach (self::$moduleTypes as $module) {
$instance = new $module['moduleClass'];
$instance->event_serverIpChanged();
}
+ */
}
/**
diff --git a/inc/configmodule/adauth.inc.php b/inc/configmodule/adauth.inc.php
index 06ac5460..828469c3 100644
--- a/inc/configmodule/adauth.inc.php
+++ b/inc/configmodule/adauth.inc.php
@@ -54,6 +54,7 @@ class ConfigModule_AdAuth extends ConfigModule
*/
public function event_serverIpChanged()
{
+ error_log('Calling generate on ' . $this->title());
$this->generate(false);
}
diff --git a/inc/configmodule/branding.inc.php b/inc/configmodule/branding.inc.php
index e8bd1da7..6e452a93 100644
--- a/inc/configmodule/branding.inc.php
+++ b/inc/configmodule/branding.inc.php
@@ -19,9 +19,7 @@ class ConfigModule_Branding extends ConfigModule
protected function generateInternal($tgz, $parent)
{
if (!$this->validateConfig()) {
- if ($this->archive() !== false && file_exists($this->archive()))
- return true; // No new temp file given, old archive still exists, pretend it worked...
- return false;
+ 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,
@@ -44,7 +42,7 @@ class ConfigModule_Branding extends ConfigModule
public function setData($key, $value)
{
- if ($key !== 'tmpFile' || !file_exists($value))
+ if ($key !== 'tmpFile' || !is_string($value) || !file_exists($value))
return false;
$this->tmpFile = $value;
}
diff --git a/inc/configtgz.inc.php b/inc/configtgz.inc.php
new file mode 100644
index 00000000..783f8b80
--- /dev/null
+++ b/inc/configtgz.inc.php
@@ -0,0 +1,160 @@
+<?php
+
+class ConfigTgz
+{
+
+ private $configId = 0;
+ private $configTitle = false;
+ private $file = false;
+ private $modules = array();
+
+ private function __construct()
+ {
+ ;
+ }
+
+ public function id()
+ {
+ return $this->configId;
+ }
+
+ public function title()
+ {
+ return $this->configTitle;
+ }
+
+ 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;
+ }
+
+ public function generate()
+ {
+ if (!($this->configId > 0) || !is_array($this->modules) || $this->file === false)
+ Util::traceError ('configId <= 0 or modules not array in ConfigTgz::rebuild()');
+ $files = array();
+ $successStatus = 'OK';
+ foreach ($this->modules as $module) {
+ if (!empty($module['filepath']) && file_exists($module['filepath'])) {
+ $files[] = $module['filepath'];
+ if ($module['status'] !== 'OK')
+ $successStatus = 'OUTDATED';
+ } else {
+ $successStatus = 'OUTDATED';
+ }
+ }
+ // Hand over to tm
+ $task = Taskmanager::submit('RecompressArchive', array(
+ 'inputFiles' => $files,
+ 'outputFile' => $this->file
+ ));
+ // Wait for completion
+ if (!Taskmanager::isFailed($task) && !Taskmanager::isFinished($task))
+ $task = Taskmanager::waitComplete($task, 5000);
+ // Failed...
+ if (Taskmanager::isFailed($task)) {
+ Taskmanager::addErrorMessage($task);
+ $successStatus = file_exists($this->file) ? 'OUTDATED' : 'MISSING';
+ }
+ Database::exec("UPDATE configtgz SET status = :status WHERE configid = :configid LIMIT 1", array(
+ 'configid' => $this->configId,
+ 'status' => $successStatus
+ ));
+ return $successStatus;
+ }
+
+ 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;
+ }
+
+}
diff --git a/inc/event.inc.php b/inc/event.inc.php
index 95d75e33..6b303493 100644
--- a/inc/event.inc.php
+++ b/inc/event.inc.php
@@ -73,9 +73,10 @@ class Event
*/
public static function serverIpChanged()
{
- global $tidAdModules, $tidIpxe;
- $tidAdModules = Trigger::rebuildAdModules();
+ error_log('Server ip changed');
+ global $tidIpxe;
$tidIpxe = Trigger::ipxe();
+ ConfigModule::serverIpChanged();
}
/**
diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php
index 5045fc75..2cdaf69f 100644
--- a/inc/taskmanager.inc.php
+++ b/inc/taskmanager.inc.php
@@ -216,7 +216,6 @@ class Taskmanager
if (++$tries > 10)
return false;
}
- //error_log(socket_strerror(socket_last_error(self::$sock)));
return false;
}
diff --git a/inc/util.inc.php b/inc/util.inc.php
index 9d0eced9..d2ecba6f 100644
--- a/inc/util.inc.php
+++ b/inc/util.inc.php
@@ -232,5 +232,45 @@ SADFACE;
}
return true;
}
+
+ /**
+ * Send a file to user for download.
+ *
+ * @param type $file path of local file
+ * @param type $name name of file to send to user agent
+ * @param type $delete delete the file when done?
+ * @return boolean false: file could not be opened.
+ * true: error while reading the file
+ * - on success, the function does not return
+ */
+ public static function sendFile($file, $name, $delete = false)
+ {
+ while ((@ob_get_level()) > 0)
+ @ob_end_clean();
+ $fh = @fopen($file, 'rb');
+ if ($fh === false) {
+ Message::addError('error-read', $file);
+ return false;
+ }
+ Header('Content-Type: application/octet-stream', true);
+ Header('Content-Disposition: attachment; filename=' . str_replace(array(' ', '=', ',', '/', '\\', ':', '?'), '_', iconv('UTF-8', 'ASCII//TRANSLIT', $name)));
+ Header('Content-Length: ' . @filesize($file));
+ while (!feof($fh)) {
+ $data = fread($fh, 16000);
+ if ($data === false) {
+ echo "\r\n\nDOWNLOAD INTERRUPTED!\n";
+ if ($delete)
+ @unlink($file);
+ return true;
+ }
+ echo $data;
+ @ob_flush();
+ @flush();
+ }
+ @fclose($fh);
+ if ($delete)
+ @unlink($file);
+ exit(0);
+ }
}