diff options
Diffstat (limited to 'examples/app/class')
-rw-r--r-- | examples/app/class/controller.class.php | 66 | ||||
-rw-r--r-- | examples/app/class/database.iface.php | 27 | ||||
-rw-r--r-- | examples/app/class/externuser.class.php | 40 | ||||
-rw-r--r-- | examples/app/class/form.class.php | 243 | ||||
-rw-r--r-- | examples/app/class/framework.class.php | 144 | ||||
-rw-r--r-- | examples/app/class/group.class.php | 49 | ||||
-rw-r--r-- | examples/app/class/issue.class.php | 44 | ||||
-rw-r--r-- | examples/app/class/message.class.php | 40 | ||||
-rw-r--r-- | examples/app/class/model.class.php | 91 | ||||
-rw-r--r-- | examples/app/class/mysql.class.php | 77 | ||||
-rw-r--r-- | examples/app/class/object.class.php | 640 | ||||
-rw-r--r-- | examples/app/class/pad.class.php | 40 | ||||
-rw-r--r-- | examples/app/class/setting.class.php | 90 | ||||
-rw-r--r-- | examples/app/class/stage.class.php | 39 | ||||
-rw-r--r-- | examples/app/class/user.class.php | 241 |
15 files changed, 1871 insertions, 0 deletions
diff --git a/examples/app/class/controller.class.php b/examples/app/class/controller.class.php new file mode 100644 index 0000000..0ab1a69 --- /dev/null +++ b/examples/app/class/controller.class.php @@ -0,0 +1,66 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/framework.class.php"; + +/* + * Abstract controller -- Contains app security constraints and provides access to + * framework internals from concrete controllers + */ +abstract class Controller extends Framework +{ + /* + * Abstract function for concrete controller to handle the page request + */ + abstract function handle($argv); + + /* + * Security check + * Assert that the current connection to this server is secure. Redirects if not. + */ + function sec_require_https() + { + if (!isset($_SERVER['HTTPS'])) + $this->redirectTo("https://" . $_SERVER['SERVER_NAME'] . $this->ap()); + } + + /* + * Security check + * Assert that the current connection to this server is NOT secure. Redirects if not. + */ + function sec_forbid_https() + { + if (isset($_SERVER['HTTPS'])) + $this->redirectTo("http://" . $_SERVER['SERVER_NAME'] . $this->ap()); + } + + /* + * Security check + * Assert that the client's IP address does not change during its session. If a change is detected, logout. + */ + function sec_verify_ip() + { + $addr = $_SERVER['REMOTE_ADDR']; + + if ($this->getCurrentUser() && $addr != $this->getOriginIP()) + { + $this->setCurrentUser(); + $this->redirectTo($this->ar() . "/"); + } + } +} + +?> diff --git a/examples/app/class/database.iface.php b/examples/app/class/database.iface.php new file mode 100644 index 0000000..b1427a4 --- /dev/null +++ b/examples/app/class/database.iface.php @@ -0,0 +1,27 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +/* + * Generic interface for the various database drivers Scrott may implement support for + */ +interface Database +{ + function close(); + function query($query); + function esc($string); +} + +?> diff --git a/examples/app/class/externuser.class.php b/examples/app/class/externuser.class.php new file mode 100644 index 0000000..73c41bd --- /dev/null +++ b/examples/app/class/externuser.class.php @@ -0,0 +1,40 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * Non-application users + */ +class ExternUser extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "email", + "emailConfKey" + ); + + parent::__construct("extern-user", $cols); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/form.class.php b/examples/app/class/form.class.php new file mode 100644 index 0000000..8bb6506 --- /dev/null +++ b/examples/app/class/form.class.php @@ -0,0 +1,243 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +/* + * Model web-forms and simplify the process of accepting, validating, and sanitizing input + */ +class Form +{ + /* + * Constructor + */ + function __construct() + { + $this->textFields = array(); + $this->numbFields = array(); + $this->enumFields = array(); + + $this->errorlist = array(); + } + + /* + * Log an error + */ + function logError($str) + { + $this->errorlist[] = $str; + } + + /* + * Add new text field to the form + */ + function field_text($name, $deflt = null, $req = true) + { + if ($req !== true) + $req = false; + + $this->textFields[] = array( + 'name' => $name, + 'deflt' => $deflt, + 'req' => $req + ); + } + + /* + * Add new numeric field to the form + */ + function field_numeric($name, $min = null, $max = null, $deflt = null, $integer = true, $req = true) + { + if ($req !== true) + $req = false; + + if ($integer !== true) + $integer = false; + + $this->numbFields[] = array( + 'name' => $name, + 'min' => $min, + 'max' => $max, + 'deflt' => $deflt, + 'int' => $integer, + 'req' => $req + ); + } + + /* + * Add new enumeration field to the form + */ + function field_enum($name, $values, $deflt = null, $req = true) + { + if ($req !== true) + $req = false; + + $this->enumFields[] = array( + 'name' => $name, + 'vals' => $values, + 'deflt' => $deflt, + 'req' => $req + ); + } + + /* + * Add new boolean field to the form + */ + function field_bool($name) + { + $this->field_enum($name, array("1", "0"), "0"); + } + + /* + * Populate the form with input data from web page + */ + function populate($input) + { + /* detect duplicate names */ + $names = array(); + foreach ($this->textFields as $fld) + $names[] = $fld['name']; + foreach ($this->numbFields as $fld) + $names[] = $fld['name']; + foreach ($this->enumFields as $fld) + $names[] = $fld['name']; + + if (count(array_unique($names)) != count($names)) + { + $this->logError("Internal error: Duplicate field names defined in form"); + return false; + } + + /* init text fields */ + foreach ($this->textFields as $fld) + { + if (isset($input[$fld['name']]) && $input[$fld['name']] != "") + $this->{$fld['name']} = htmlEntities($input[$fld['name']], ENT_QUOTES); + + else if (!is_null($fld['deflt'])) + $this->{$fld['name']} = $fld['deflt']; + + else if ($fld['req']) + $this->logError($fld['name'] . " is required"); + } + + /* init numeric fields */ + foreach ($this->numbFields as $fld) + { + if (isset($input[$fld['name']]) && $input[$fld['name']] != "") + { + if (!is_numeric($input[$fld['name']])) + { + $this->logError($fld['name'] . " must be numeric"); + continue; + } + + if ($fld['int'] && (floor($input[$fld['name']]) != $input[$fld['name']])) + { + $this->logError($fld['name'] . " must be an integer"); + continue; + } + + if (!is_null($fld['min']) && ($input[$fld['name']] < $fld['min'])) + { + $this->logError($fld['name'] . " must be no less than " . $fld['min']); + continue; + } + + if (!is_null($fld['max']) && ($input[$fld['name']] > $fld['max'])) + { + $this->logError($fld['name'] . " must be no more than " . $fld['max']); + continue; + } + + $this->{$fld['name']} = $input[$fld['name']]; + } + + else if (!is_null($fld['deflt'])) + $this->{$fld['name']} = $fld['deflt']; + + else if ($fld['req']) + $this->logError($fld['name'] . " is required"); + } + + /* init enum fields */ + foreach ($this->enumFields as $fld) + { + if (isset($input[$fld['name']]) && $input[$fld['name']] != "") + { + if (array_search($input[$fld['name']], $fld['vals']) === false) + { + $this->logError($fld['name'] . " is not an appropriate value"); + continue; + } + + $this->{$fld['name']} = $input[$fld['name']]; + } + + else if (!is_null($fld['deflt'])) + $this->{$fld['name']} = $fld['deflt']; + + else if ($fld['req']) + $this->logError($fld['name'] . " is required"); + } + + /* return */ + return count($this->errorlist) == 0; + } + + /* + * Handle an uploaded file + */ + function saveFile($file, $maxsize, $allowed_mime, $path, $req = false) + { + if (isset($file) && !is_null($file)) + { + if ($file['error'] > 0) + { + if ($file['error'] != UPLOAD_ERR_NO_FILE) + $this->logError("An unknown error occurred"); + + return false; + } + + if ($file['size'] > $maxsize) + { + $this->logError("File must be no larger than " . $maxsize . " bytes"); + return false; + } + + if (is_array($allowed_mime) && array_search($file['type'], $allowed_mime) === false) + { + $this->logError("File type is not supported"); + return false; + } + + if (!move_uploaded_file($file['tmp_name'], $path)) + { + $this->logError("Error saving uploaded file"); + return false; + } + } + + else if ($req) + { + $this->logError("File upload is required"); + return false; + } + + return true; + } +} + +?> diff --git a/examples/app/class/framework.class.php b/examples/app/class/framework.class.php new file mode 100644 index 0000000..a3c36cb --- /dev/null +++ b/examples/app/class/framework.class.php @@ -0,0 +1,144 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +/* Define Scrott version number */ +define("__VERSION__", "v0.0"); + +/* Include the Scrott system-level configuration file if it exists */ +is_file("scrott.conf.php") && + require_once "scrott.conf.php"; + +/* Init PHP session */ +session_start(); + +require_once "class/mysql.class.php"; +require_once "class/user.class.php"; + +/* + * Global functions / operations and access to contextual or session-based information + */ +abstract class Framework +{ + static $dbobj = null; + + /* + * Check for the existence of Scrott's system-level config + */ + function scrottConfExists() + { + global $_SCROTT; + return isset($_SCROTT['conf']); + } + + /* + * Get the absolute path on this server for the root of this app + */ + function ar() + { + return substr($_SERVER['PHP_SELF'], 0, -10); // 10 = length of "/index.php" + } + + /* + * Get the absolute path to the current page + */ + function ap() + { + return $this->ar() . $_REQUEST['path']; + } + + /* + * Redirect to the given URL and die + */ + function redirectTo($url) + { + header("Location: " . $url); + exit; + } + + /* + * Get a user object for the currently logged in user. Returns false if session is logged out. + */ + function getCurrentUser() + { + if (isset($_SESSION['userguid'])) + { + $user = new User($_SESSION['userguid']); + + if ($user->type == "user") + return $user; + + $this->setCurrentUser(); + } + + return false; + } + + /* + * Get the IP address the client held when the current session began + */ + function getOriginIP() + { + return $_SESSION['userip']; + } + + /* + * Set the current logged in user + */ + function setCurrentUser($user = null) + { + if ($user != null && isset($user->guid)) + { + $_SESSION['userguid'] = $user->guid; + $_SESSION['userip'] = $_SERVER['REMOTE_ADDR']; + } + + else + { + unset($_SESSION['userguid']); + unset($_SESSION['userip']); + } + } + + /* + * Get or create the app's database connection object (this is a singleton object and dependent on system-level config) + */ + static function getDbConnection() + { + global $_SCROTT; + + if (self::$dbobj != null) + return self::$dbobj; + + switch ($_SCROTT['dbEngine']) + { + case "mysql": + $host = $_SCROTT['dbAddress']; + $username = $_SCROTT['dbUser']; + $password = $_SCROTT['dbPass']; + $dbName = $_SCROTT['dbName']; + self::$dbobj = new Mysql($host, $username, $password, $dbName); + break; + + default: + throw new Exception("Problem with Scrott Configuration. Invalid database engine specified."); + break; + } + + return self::$dbobj; + } +} + +?> diff --git a/examples/app/class/group.class.php b/examples/app/class/group.class.php new file mode 100644 index 0000000..246276a --- /dev/null +++ b/examples/app/class/group.class.php @@ -0,0 +1,49 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * User groups + */ +class Group extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + parent::__construct(); + $this->loadObj($guid); + } + + /* + * Create a new user group object. + * On success, this object should be initialized as the new group (use only on new + * Group() objects) + */ + function createNewGroup($name, $owner) + { + $this->perms = $this->DEFAULT_OBJECT_PERMISSIONS; + $this->owner = $owner->guid; + $this->name = $name; + $this->type = "group"; + + $this->saveObj(); + } +} + +?> diff --git a/examples/app/class/issue.class.php b/examples/app/class/issue.class.php new file mode 100644 index 0000000..10b1661 --- /dev/null +++ b/examples/app/class/issue.class.php @@ -0,0 +1,44 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * Pad issues + */ +class Issue extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "number", + "assignee", + "unread", + "desc", + "due", + "tags" + ); + + parent::__construct("issue", $cols); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/message.class.php b/examples/app/class/message.class.php new file mode 100644 index 0000000..ac8444c --- /dev/null +++ b/examples/app/class/message.class.php @@ -0,0 +1,40 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * User messages and log messages + */ +class Message extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "author", + "message" + ); + + parent::__construct("message", $cols); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/model.class.php b/examples/app/class/model.class.php new file mode 100644 index 0000000..7d74b36 --- /dev/null +++ b/examples/app/class/model.class.php @@ -0,0 +1,91 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/framework.class.php"; + +/* + * Abstract model class - defines logic common to all app MVC models + */ +abstract class Model extends Framework +{ + /* + * Constructor + */ + function __construct() + { + $this->errorlist = array(); + $this->warninglist = array(); + $this->noticelist = array(); + } + + /* + * Check for error + */ + function isError() + { + return count($this->errorlist) > 0; + } + + /* + * Check for warning + */ + function isWarning() + { + return count($this->warninglist) > 0; + } + + /* + * Check for notice + */ + function isNotice() + { + return count($this->noticelist) > 0; + } + + /* + * Log an error + */ + function logError($str) + { + $this->errorlist[] = $str; + } + + /* + * Log a warning + */ + function logWarning($str) + { + $this->warninglist[] = $str; + } + + /* + * Log a notice + */ + function logNotice($str) + { + $this->noticelist[] = $str; + } + + /* + * Log errors from a Form + */ + function logFormErrors($obj) + { + $this->errorlist = array_merge($this->errorlist, $obj->errorlist); + } +} + +?> diff --git a/examples/app/class/mysql.class.php b/examples/app/class/mysql.class.php new file mode 100644 index 0000000..f8f456a --- /dev/null +++ b/examples/app/class/mysql.class.php @@ -0,0 +1,77 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/database.iface.php"; + +/* + * MySQL support for Scrott + */ +class Mysql implements Database +{ + /* + * Constructor + */ + function __construct($host, $username, $password, $dbName) + { + $this->db = new mysqli($host, $username, $password, $dbName); + + if ($this->db->connect_error) + throw new Exception("Can not connect to Mysql database. Please check your Scrott configuration."); + } + + /* + * Destructor + */ + function __destruct() + { + $this->close(); + } + + /* + * Close connection to DB + */ + function close() + { + $this->db->close(); + } + + /* + * Make a query of the database. Return data as an array of arrays + */ + function query($query) + { + $arr = array(); + $res = $this->db->query($query); + + if ($res === true || $res === false) + return $arr; + + while ($r = $res->fetch_assoc()) + $arr[] = $r; + + return $arr; + } + + /* + * Escape a string for use in a query + */ + function esc($string) + { + return $this->db->real_escape_string($string); + } +} + +?> diff --git a/examples/app/class/object.class.php b/examples/app/class/object.class.php new file mode 100644 index 0000000..7c0b7bb --- /dev/null +++ b/examples/app/class/object.class.php @@ -0,0 +1,640 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/framework.class.php"; +require_once "class/user.class.php"; + +/* + * Base class for Scrott database objects + */ +abstract class Object extends Framework +{ + var $DEFAULT_OBJECT_PERMISSIONS = 120; + + /* + * Constructor + */ + function __construct($childTable = "object", $childCols = null) + { + $this->db = $this->getDbConnection(); + + $this->table = "object"; + $this->cols = array( + "guid", + "perms", + "owner", + "parent", + "name", + "timeCreated", + "timeUpdated", + "type" + ); + + $this->childTable = $this->db->esc($childTable); + $this->childCols = array(); + + if (is_array($childCols)) + { + foreach ($childCols as $col) + $this->childCols[] = $this->db->esc($col); + } + } + + /* + * Populate this object with data from the DB with a given GUID + */ + function loadObj($guid = null) + { + if (is_null($guid)) + return; + + if (!$this->isGUID($guid)) + return; + + $escdGuid = $this->db->esc($guid); + + /* Base fields */ + $query = "SELECT * FROM `" . $this->table . "` WHERE `guid` = '" . $escdGuid . "'"; + $result = $this->db->query($query)[0]; + + foreach ($this->cols as $col) + { + if (isset($result[$col])) + $this->$col = $result[$col]; + } + + /* Child Table fields */ + $query = "SELECT * FROM `" . $this->childTable . "` WHERE `guid` = '" . $escdGuid . "'"; + $result = $this->db->query($query)[0]; + + foreach ($this->childCols as $col) + { + if (isset($result[$col])) + $this->$col = $result[$col]; + } + } + + /* + * Write this object to the database + */ + function saveObj() + { + if (isset($this->guid)) + { + $this->timeUpdated = $this->getCurrentTimestamp(); + + /* Update Base */ + $updateStr = ""; + + foreach ($this->cols as $col) + { + if (!isset($this->$col)) + continue; + + $updateStr .= "`" . $col . "` = '" . $this->db->esc($this->$col) . "', "; + } + + if (strlen($updateStr) > 0) + { + $updateStr = substr($updateStr, 0, -2); // remove ", " from the end + $query = "UPDATE `" . $this->table . "` SET " . $updateStr . " WHERE `guid` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + } + + /* Update Child */ + $updateStr = ""; + + foreach ($this->childCols as $col) + { + if (!isset($this->$col)) + continue; + + $updateStr .= "`" . $col . "` = '" . $this->db->esc($this->$col) . "', "; + } + + if (strlen($updateStr) > 0) + { + $updateStr = substr($updateStr, 0, -2); // remove ", " from the end + $query = "UPDATE `" . $this->childTable . "` SET " . $updateStr . " WHERE `guid` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + } + } + + else + { + $this->guid = $this->getNewGUID(); + $this->timeCreated = $this->getCurrentTimestamp(); + $this->timeUpdated = $this->timeCreated; + + /* Insert Base */ + $colsStr = ""; + $valsStr = ""; + + foreach ($this->cols as $col) + { + if (!isset($this->$col)) + continue; + + $colsStr .= "`" . $col . "`, "; + $valsStr .= "'" . $this->db->esc($this->$col) . "', "; + } + + if (strlen($colsStr) > 0) + { + $colsStr = substr($colsStr, 0, -2); // remove ", " + $valsStr = substr($valsStr, 0, -2); + $query = "INSERT INTO `" . $this->table . "` (" . $colsStr . ") VALUES (" . $valsStr . ")"; + $this->db->query($query); + } + + /* Insert Child */ + $colsStr = ""; + $valsStr = ""; + + foreach ($this->childCols as $col) + { + if (!isset($this->$col)) + continue; + + $colsStr .= "`" . $col . "`, "; + $valsStr .= "'" . $this->db->esc($this->$col) . "', "; + } + + if (strlen($colsStr) > 0) + { + $colsStr = substr($colsStr, 0, -2); // remove ", " + $valsStr = substr($valsStr, 0, -2); + $query = "INSERT INTO `" . $this->childTable . "` (" . $colsStr . ") VALUES (" . $valsStr . ")"; + $this->db->query($query); + } + } + } + + /* + * Remove this object from the database + */ + function delObj() + { + if (!isset($this->guid)) + return; + + /* Delete Base */ + $query = "DELETE FROM `" . $this->table . "` WHERE `guid` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + + /* Delete Child */ + $query = "DELETE FROM `" . $this->childTable . "` WHERE `guid` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + + /* obj_member garbage collection */ + $query = "DELETE FROM `obj_member` WHERE `guid` = '" . $this->db->esc($this->guid) . "' OR `member` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + + /* msg_read garbage collection */ + $query = "DELETE FROM `msg_read` WHERE `guid` = '" . $this->db->esc($this->guid) . "' OR `user` = '" . $this->db->esc($this->guid) . "'"; + $this->db->query($query); + } + + /* + * Get current timestamp for object database purposes + */ + function getCurrentTimestamp() + { + $query = "SELECT now() AS stamp"; + $result = $this->db->query($query); + return $result[0]['stamp']; + } + + /* + * Check whether given GUID exists + */ + function isGUID($guid) + { + $query = "SELECT `guid` FROM `object` WHERE `guid` = '" . $this->db->esc($guid) . "'"; + $result = $this->db->query($query); + + if (count($result) > 0) + return true; + + return false; + } + + /* + * Get a new, unique GUID for a new system object + */ + function getNewGUID() + { + do + { + $guid = substr($this->getBlob(), 0, 8); + } + while ($this->isGUID($guid)); + + return $guid; + } + + /* + * Get a random sha256 blob + */ + function getBlob() + { + return hash("sha256", openssl_random_pseudo_bytes(64)); + } + + /* + * Get a user object for this object's owner + */ + function getOwner() + { + if (isset($this->owner)) + return new User($this->owner); + + return null; + } + + /* + * Get an array of all members of this object + */ + function getMembers() + { + $query = "SELECT member FROM obj_member WHERE guid = '" . $this->db->esc($this->guid) . "'"; + $result = $this->db->query($query); + + $members = array(); + + foreach ($result as $m) + $members[] = new User($m['member']); + + return $members; + } + + /* + * Check if given user (or group) is the owner of this object + */ + function isOwner($ug) + { + return $this->getOwner()->guid == $ug->guid; + } + + /* + * Check if given user (or group) is a member of this object + */ + function isMember($ug) + { + foreach ($this->getMembers() as $member) + { + if ($member->guid == $ug->guid) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canAccess($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user)) + return true; + + if ($this->perms & 0x004) // accessible by public + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canAccessSub($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canAccessSub($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModify($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x100) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySub($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySub($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModifyMembers($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x080) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySubMembers($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySubMembers($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModifyPermissions($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySubPermissions($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySubPermissions($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canAccessSub($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x040) + return true; + + if ($this->perms & 0x002) // accessible by public + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canAccessSub($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canAccessSub($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canCreateSub($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x020) + return true; + + if ($this->perms & 0x001) // accessible by public + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canCreateSub($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canCreateSub($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModifySub($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x010) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySub($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySub($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModifySubMembers($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->isMember($user) && $this->perms & 0x008) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySubMembers($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySubMembers($user)) + return true; + } + + return false; + } + + /* + * Check if given user has permissions for this object + */ + function canModifySubPermissions($user) + { + if ($user->admin) + return true; + + if ($this->isOwner($user)) + return true; + + if ($this->parent != "") + { + $parent = new DBObject($this->parent); + + if ($parent->canModifySubPermissions($user)) + return true; + } + else if ($this->owner != $this->guid) + { + $owner = new DBObject($this->owner); + + if ($owner->canModifySubPermissions($user)) + return true; + } + + return false; + } + + /* + * Get URL to this object + */ + function getURL() + { + return $this->ar() . "/" . $this->guid; + } + + /* + * Get object's head image + */ + function getHeadImage() + { + return $this->ar() . "/file.php?d=img/heads&f=" . $this->guid; + } + + /* + * Remove this object's head image + */ + function rmHeadImage() + { + if (!is_file("assets/img/heads/" . $this->guid)) + return true; + + return unlink("assets/img/heads/" . $this->guid); + } +} + +/* + * Concrete Database Object which can be used in a polymorphic way + */ +class DBObject extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + parent::__construct(); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/pad.class.php b/examples/app/class/pad.class.php new file mode 100644 index 0000000..32994e5 --- /dev/null +++ b/examples/app/class/pad.class.php @@ -0,0 +1,40 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * Scrott pads + */ +class Pad extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "stage", + "nextIssueNumber" + ); + + parent::__construct("pad", $cols); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/setting.class.php b/examples/app/class/setting.class.php new file mode 100644 index 0000000..c0965a3 --- /dev/null +++ b/examples/app/class/setting.class.php @@ -0,0 +1,90 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/framework.class.php"; + +/* + * Scrott administrative settings + */ +class Setting extends Framework +{ + /* + * Helper function for getting setting values from the database + */ + static function getValue($key) + { + $db = parent::getDbConnection(); + $escdKey = $db->esc($key); + + $query = "SELECT `value` FROM `setting` WHERE `key` = '" . $escdKey . "'"; + $res = $db->query($query); + + if (count($res) == 0) + return false; + + return $res[0]['value']; + } + + /* + * Helper function for setting setting values on the database + */ + static function setValue($key, $value) + { + $db = parent::getDbConnection(); + $escdKey = $db->esc($key); + $escdValue = $db->esc($value); + + if (self::getValue($key) === false) + $query = "INSERT INTO setting (`key`, value) VALUES('" . $escdKey . "', '" . $escdValue . "')"; + else + $query = "UPDATE setting SET value = '" . $escdValue . "' WHERE `key` = '" . $escdKey . "'"; + + $db->query($query); + } + + /* + * Force or forbid SSL connections? + */ + static function settSSL($value = null) + { + $opt = "settSSL"; + + if ($value != null) + self::setValue($opt, $value); + + $value = self::getValue($opt); + + if ($value === false) + return "neither"; + + return $value; + } + + /* + * Should the app allow the public to signup their own accounts with Scrott? + */ + static function allowPublicSignup($value = null) + { + $opt = "allowPublicSignup"; + + if ($value != null) + self::setValue($opt, $value); + + return self::getValue($opt); + } +} + +?> diff --git a/examples/app/class/stage.class.php b/examples/app/class/stage.class.php new file mode 100644 index 0000000..1a2aadb --- /dev/null +++ b/examples/app/class/stage.class.php @@ -0,0 +1,39 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; + +/* + * Pad stages + */ +class Stage extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "stage" + ); + + parent::__construct("stage", $cols); + $this->loadObj($guid); + } +} + +?> diff --git a/examples/app/class/user.class.php b/examples/app/class/user.class.php new file mode 100644 index 0000000..b8143a9 --- /dev/null +++ b/examples/app/class/user.class.php @@ -0,0 +1,241 @@ +<?php + +/* + * SCROTT Copyright (C) 2016 Malf Furious + * + * Scrott is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Scrott is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + */ + +require_once "class/object.class.php"; +require_once "class/group.class.php"; + +/* + * Application users + */ +class User extends Object +{ + /* + * Constructor + */ + function __construct($guid = null) + { + $cols = array( + "guid", + "key", + "salt", + "alias", + "admin", + "email", + "emailConf", + "emailConfKey" + ); + + parent::__construct("user", $cols); + $this->loadObj($guid); + } + + /* + * Initialize object by username + */ + function initByUsername($username) + { + $query = "SELECT guid FROM object WHERE type = 'user' AND name = '" . $this->db->esc($username) . "'"; + $result = $this->db->query($query); + + if (count($result) == 0) + return false; + + $this->loadObj($result[0]['guid']); + return true; + } + + /* + * Get all users -- ordered by name, ascending + */ + function getAllUsers_orderByName() + { + $query = "SELECT guid FROM `object` WHERE `type` = 'user' ORDER BY name"; + $result = $this->db->query($query); + + $users = array(); + + foreach ($result as $u) + $users[] = new User($u['guid']); + + return $users; + } + + /* + * Get all users -- ordered by admin DESC (admins first), then by name + */ + function getAllUsers_orderByAdminByName() + { + $query = "SELECT o.guid FROM object o JOIN user u ON o.guid = u.guid WHERE o.type = 'user' ORDER BY u.admin DESC, o.name"; + $result = $this->db->query($query); + + $users = array(); + + foreach ($result as $u) + $users[] = new User($u['guid']); + + return $users; + } + + /* + * Get the number of administrative accounts in the system + */ + function getNumAdmins() + { + $query = "SELECT count(*) as cnt FROM user WHERE admin = 1"; + $results = $this->db->query($query); + return $results[0]['cnt']; + } + + /* + * Check whether a given username is currently in use + */ + function usernameInUse($username) + { + $escd_username = $this->db->esc($username); + + $query = "SELECT name FROM object WHERE type = 'user' AND name = '" . $escd_username . "'"; + $results = $this->db->query($query); + + if (count($results) > 0) + return true; + + return false; + } + + /* + * Generate a key from a user's password and salt + */ + function getKey($password, $salt) + { + return hash("sha256", $salt . $password); + } + + /* + * Create a new User object with the given username and keyed with the given plain-text password + * This function returns false if $username is already being used + * On success, this object should be initialized as the new user (use only on new User() objects) + */ + function createNewUser($username, $password) + { + if ($this->usernameInUse($username)) + return false; + + /* if there exist no users already, make this new one an admin */ + if (count($this->getAllUsers_orderByName()) == 0) + $this->admin = 1; + + $this->perms = 0; + $this->name = $username; + $this->type = "user"; + $this->setPassword($password); + $this->setEmail(""); + + $this->saveObj(); + + $this->owner = $this->guid; + $this->saveObj(); + + return true; + } + + /* + * Validate the password for this user. Returns true if correct, false otherwise + */ + function validatePassword($password) + { + $key = $this->getKey($password, $this->salt); + return $key == $this->key; + } + + /* + * Validate the email confirmation key for a user, returns true if correct, false otherwise. On success, $this->emailConf is also set to 1 + */ + function confirmEmailKey($key) + { + if ($key != $this->emailConfKey) + return false; + + $this->emailConf = 1; + return true; + } + + /* + * Overwrite the salt and key for this user, given a new plaintext password + */ + function setPassword($password) + { + $this->salt = $this->getBlob(); + $this->key = $this->getKey($password, $this->salt); + } + + /* + * Overwrite the emailConfKey and flag, and change user's saved email address + */ + function setEmail($email) + { + $this->email = $email; + $this->emailConf = 0; + $this->emailConfKey = $this->getBlob(); + } + + /* + * If a user has an alias set, display it instead of their username + */ + function getDisplayName() + { + if ($this->alias != "") + return $this->alias; + + return $this->name; + } + + /* + * Get the glyphicon to use for this user + */ + function getGlyphicon() + { + if ($this->admin) + return "glyphicon glyphicon-sunglasses"; + + return "glyphicon glyphicon-user"; + } + + /* + * Get all groups this user owns or is a member of + */ + function getGroups() + { + /* owner */ + $query = "SELECT guid FROM object WHERE type = 'group' AND owner = '" . $this->db->esc($this->guid) . "'"; + $result = $this->db->query($query); + + $groups = array(); + + foreach ($result as $g) + $groups[] = new Group($g['guid']); + + /* member */ + $query = "SELECT o.guid FROM object o JOIN obj_member om ON o.guid = om.guid WHERE o.type = 'group' AND member = '" . $this->db->esc($this->guid) . "'"; + $result = $this->db->query($query); + + foreach ($result as $g) + $groups[] = new Group($g['guid']); + + return $groups; + } +} + +?> |