From a362ac12b119b49519f5af51b92ebb7d6e127b87 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 31 Oct 2013 12:38:25 +0100 Subject: Comments, minor refactoring, possiblity to validate configuration parameters --- inc/crypto.inc.php | 29 ++++++++++++++++++ inc/db.inc.php | 27 +++++++++++++++- inc/message.inc.php | 85 +++++++++++++++++++++++++++++++++++++++------------ inc/user.inc.php | 2 +- inc/util.inc.php | 44 +++++++++++++++++++++----- inc/validator.inc.php | 43 ++++++++++++++++++++++++++ 6 files changed, 202 insertions(+), 28 deletions(-) create mode 100644 inc/crypto.inc.php create mode 100644 inc/validator.inc.php (limited to 'inc') diff --git a/inc/crypto.inc.php b/inc/crypto.inc.php new file mode 100644 index 00000000..54cdef8a --- /dev/null +++ b/inc/crypto.inc.php @@ -0,0 +1,29 @@ +fetch(PDO::FETCH_ASSOC); } + /** + * Execute the given query and return the number of rows affected. + * Mostly useful for UPDATEs or INSERTs + */ public static function exec($query, $args = array()) { $res = self::simpleQuery($query, $args); @@ -29,6 +44,12 @@ class Database return $res->rowCount(); } + /** + * Execute the given query and return the corresponding PDOStatement object + * Note that this will re-use PDOStatements, so if you run the same + * query again with different params, do not rely on the first PDOStatement + * still being valid. If you need to do something fancy, use Database::prepare + */ public static function simpleQuery($query, $args = array()) { self::init(); @@ -44,6 +65,10 @@ class Database return self::$statements[$query]; } + /** + * Simply calls PDO::prepare and returns the PDOStatement. + * You must call PDOStatement::execute manually on it. + */ public static function prepare($query) { self:init(); diff --git a/inc/message.inc.php b/inc/message.inc.php index b90ed630..4da277e7 100644 --- a/inc/message.inc.php +++ b/inc/message.inc.php @@ -6,10 +6,12 @@ $error_text = array( 'token' => 'Ungültiges Token. CSRF Angriff?', 'adduser-disabled' => 'Keine ausreichenden Rechte, um weitere Benutzer hinzuzufügen', 'password-mismatch' => 'Passwort und Passwortbestätigung stimmen nicht überein', - 'empty-field' => 'Ein benötigtes Feld wurde nicht ausgefüllt', + 'empty-field' => 'Ein Feld wurde nicht ausgefüllt', 'adduser-success' => 'Benutzer erfolgreich hinzugefügt', 'no-permission' => 'Keine ausreichenden Rechte, um auf diese Seite zuzugreifen', 'settings-updated' => 'Einstellungen wurden aktualisiert', + 'debug-mode' => 'Der Debug-Modus ist aktiv!', + 'value-invalid' => 'Der Wert {{1}} ist ungültig für die Option {{0}} und wurde ignoriert', ); class Message @@ -17,51 +19,96 @@ class Message private static $list = array(); private static $flushed = false; + /** + * Add error message to page. If messages have not been flushed + * yet, it will be added to the queue, otherwise it will be added + * in place during rendering. + */ public static function addError($id) { - self::$list[] = array( - 'type' => 'error', - 'id' => $id - ); - if (self::$flushed) self::renderList(); + self::add('error', $id, func_get_args()); } public static function addWarning($id) { - self::$list[] = array( - 'type' => 'warning', - 'id' => $id - ); - if (self::$flushed) self::renderList(); + self::add('warning', $id, func_get_args()); } public static function addInfo($id) { - self::$list[] = array( - 'type' => 'info', - 'id' => $id - ); - if (self::$flushed) self::renderList(); + self::add('info', $id, func_get_args()); } public static function addSuccess($id) { + self::add('success', $id, func_get_args()); + } + + /** + * Internal function that adds a message. Used by + * addError/Success/Info/... above. + */ + private static function add($type, $id, $params) + { + global $error_text; + if (!isset($error_text[$id])) Util::traceError('Invalid message id: ' . $id); self::$list[] = array( - 'type' => 'success', - 'id' => $id + 'type' => $type, + 'id' => $id, + 'params' => array_slice($params, 1) ); if (self::$flushed) self::renderList(); } + /** + * Render all currently queued messages, flushing the queue. + * After calling this, any further calls to add* will be rendered in + * place in the current page output. + */ public static function renderList() { global $error_text; foreach (self::$list as $item) { - Render::addTemplate('messagebox-' . $item['type'], array('message' => $error_text[$item['id']])); + $message = $error_text[$item['id']]; + foreach ($item['params'] as $index => $text) { + $message = str_replace('{{' . $index . '}}', $text, $message); + } + Render::addTemplate('messagebox-' . $item['type'], array('message' => $message)); } self::$list = array(); self::$flushed = true; } + /** + * Deserialize any messages from the current HTTP request and + * place them in the message queue. + */ + public static function fromRequest() + { + $messages = is_array($_REQUEST['message']) ? $_REQUEST['message'] : array($_REQUEST['message']); + foreach ($messages as $message) { + $data = explode('|', $message); + if (count($data) < 2 || !preg_match('/^(error|warning|info|success)$/', $data[0])) continue; + self::add($data[0], $data[1], array_slice($data, 1)); + } + } + + /** + * Turn the current message queue into a serialized version, + * suitable for appending to a GET or POST request + */ + public static function toRequest() + { + $parts = array(); + foreach (self::$list as $item) { + $str = 'message[]=' . urlencode($item['type'] . '|' .$item['id']); + if (!empty($item['params'])) { + $str .= '|' . implode('|', $item['params']); + } + $parts[] = $str; + } + return implode('&', $parts); + } + } diff --git a/inc/user.inc.php b/inc/user.inc.php index 38e57e33..b333c7e4 100644 --- a/inc/user.inc.php +++ b/inc/user.inc.php @@ -39,7 +39,7 @@ class User { $ret = Database::queryFirst('SELECT userid, passwd FROM user WHERE login = :user LIMIT 1', array(':user' => $user)); if ($ret === false) return false; - if (crypt($pass, $ret['passwd']) !== $ret['passwd']) return false; + if (!Crypto::verify($pass, $ret['passwd'])) return false; Session::create(); Session::set('uid', $ret['userid']); Session::set('token', md5(rand() . time() . rand() . $_SERVER['REMOTE_ADDR'] . rand() . $_SERVER['REMOTE_PORT'] . rand() . $_SERVER['HTTP_USER_AGENT'])); diff --git a/inc/util.inc.php b/inc/util.inc.php index 0d85b989..f456d164 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -1,30 +1,53 @@ $2$3', $string); diff --git a/inc/validator.inc.php b/inc/validator.inc.php new file mode 100644 index 00000000..72b7fa0b --- /dev/null +++ b/inc/validator.inc.php @@ -0,0 +1,43 @@ +