Page MenuHomeDevCentral

No OneTemporary

diff --git a/workspaces/src/content/help/credits.html b/workspaces/src/content/help/credits.html
index 8dd63cf..68a8886 100644
--- a/workspaces/src/content/help/credits.html
+++ b/workspaces/src/content/help/credits.html
@@ -1,65 +1,65 @@
<ol class="breadcrumb">
<li><a href="{get_url('help')}">Help</a></li>
<li>About Obsidian Workspaces</li>
<li class="active">Credits</li>
</ol>
<h1>Credits</h1>
<h2>Code</h2>
<h3>PHP engine and libraries</h3>
<dl class="definition">
<dt>Obsidian Workspaces</dt>
<dd>Copyright © 2012-2014 <a href="http://www.dereckson.be/">Sébastien Santoro aka Dereckson</a></dd>
<dd>Licensed under BSD license</dd>
<dd>Powered by <a href="http://keruald.sf.net">Keruald</a>, open source modular library.</dd>
</dl>
<h3>JavaScript</h3>
<dl class="definition">
<dt>SyntaxHighlighter</dt>
<dd>Copyright © <a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">alexgorbatchev.com</a><br>
SyntaxHighlighter is licenced under <a href="http://www.gnu.org/copyleft/lesser.html">LGPL 3</a></dd>
</dl>
<h2>Content</h2>
<h3>Obsidian Workspaces content</h3>
<dl class="definition">
<dt>Help content</dt>
<dd>The Obsidian Workspaces documentation is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" rel="license">Creative Commons BY 4.0 license</a>.</dd>
</dl>
<h3>User-generated content</h3>
<dl class="definition">
<dt>Data</dt>
<dd>All works uploaded to the site by users keeps its original copyright status, under their responsibility.</dd>
</dl>
<h2>Design</h2>
<h3>Web UI</h3>
<dl class="definition">
<dt>Main design</dt>
<dd>Copyright © 2013 <a href="http://www.ironsummitmedia.com/">Iron Summit Media Strategies</a><br>
Licensed under <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License 2.0 </a></dd>
</dl>
<h3>Icons</h3>
<dl class="definition">
<dt>Arrow obsidian</dt>
<dd>This image is a work of a United States Department of Energy (or predecessor organization) employee, taken or made during the course of an employee's official duties. As a work of the U.S. federal government, the image is in the public domain.
<br>&nbsp;<br>Thank you to Julien Torres for the cutout operation.</dd>
</dl>
<h3>Photography</h3>
<dl class="definition">
<dt><a href="http://www.flickr.com/photos/travelingotter/5351260684/">Gray Glacier - Torres del Paine, Chile</a></dt>
<dd>Photography by <a href="http://www.flickr.com/photos/travelingotter/">TravelingOtter</a>, licensed under <a href="http://creativecommons.org/licenses/by/2.0/" rel="license">Creative Commons BY 2.0 license</a>.</dd>
<dt><a href="http://www.army.mil/media/31779">Majestic McKinley</a></dt>
<dd class="description">Capt. Keelan McNulty surveys the majesty of the Alaskan mountain range during his climb of Mount McKinley. 2008-07-15.</dd>
<dd>Photography by 1st Lt. Graham Ward, U.S. Army, in the public domain.</dd>
<dt><a href="https://commons.wikimedia.org/wiki/File:Rock_Mesa_obsidian_flow_in_Oregon_in_2011_%289%29.JPG">Rock Mesa obsidian flow in Oregon in 2011</a></dt>
- <dd class="description">Obsidian lava flow Rock Mesa in in Three Sisters Area, protected area Three Sisters Wilderness, Oregon, USA. 3 September 2011, 01:04:12</dd>
+ <dd class="description">Obsidian lava flow Rock Mesa in Three Sisters Area, protected area Three Sisters Wilderness, Oregon, USA. 3 September 2011, 01:04:12</dd>
<dd>Photography by <a href="https://commons.wikimedia.org/wiki/User:Chmee2">Petr Brož</a>, under <a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license">Creative Commons BY-SA 3.0 license</a>.</dd>
</dl>
diff --git a/workspaces/src/includes/GlobalFunctions.php b/workspaces/src/includes/GlobalFunctions.php
index a5a2076..47451e4 100644
--- a/workspaces/src/includes/GlobalFunctions.php
+++ b/workspaces/src/includes/GlobalFunctions.php
@@ -1,331 +1,331 @@
<?php
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Information helper functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/**
* Gets the username matching specified user id
*
* @param string $user_id the user ID
* @return string the username
*/
function get_username ($user_id) {
global $db;
$user_id = $db->sql_escape($user_id);
$sql = 'SELECT username FROM '. TABLE_USERS . " WHERE user_id = '$userid'";
return $db->sql_query_express($sql, "Can't get username from specified user id");
}
/**
* Gets the user id matching specified username
*
* @param string $username the username
* @return string the user ID
*/
function get_userid ($username) {
global $db;
$username = $db->sql_escape($username);
$sql = 'SELECT user_id FROM '. TABLE_USERS . " WHERE username LIKE '$username'";
return $db->sql_query_express($sql, "Can't get user id from specified username");
}
/**
* Gets the resource ID from an identifier
*
* @param $resource_type the resource type
* @param $identifier resource identifier
* @return mixed the resource ID (as integer), or NULL if unknown
*/
function resolve_resource_id ($resource_type, $identifier) {
//Trivial cases: already an ID, null or void ID
if (is_numeric($identifier)) {
return $identifier;
}
if (!$identifier) {
return NULL;
}
//Searches identifier
switch ($resource_type) {
case 'U':
return get_user_id($identifier);
case 'G':
$group = UserGroup::fromCode($identifier);
return $group->id;
case 'W':
$workspace = Workspace::fromCode($identifier);
return $workspace->id;
default:
throw new Exception("Unknown resource type: $resource_type", E_USER_ERROR);
}
}
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Misc helper functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//Plural management
/*
* Gets a "s" if the specified amount requests the plural
* @param mixed $amount the quantity (should be numeric)
* @return string 's' if the amount is greater or equal than 2 ; otherwise, ''
*/
function s ($amount) {
if ($amount >= 2 || $amount <= -2 ) return 's';
}
/*
* Prints human-readable information about a variable, wrapped in a <pre> block
* @param mixed $mixed the variable to dump
*/
function dprint_r ($mixed) {
echo '<pre>';
print_r($mixed);
echo '</pre>';
}
/*
* Generates a new GUID
* @return string a guid (without {})
*/
function new_guid () {
//The guid chars
$chars = explode(',', 'a,b,c,d,e,f,0,1,2,3,4,5,6,7,8,9');
//Let's build our 36 characters string
//e.g. 68ed40c6-f5bb-4a4a-8659-3adf23536b75
$guid = "";
for ($i = 0 ; $i < 36 ; $i++) {
if ($i == 8 || $i == 13 || $i == 18 || $i == 23) {
//Dashes at position 9, 14, 19 and 24
$guid .= "-";
} else {
//0-f hex digit elsewhere
$guid .= $chars[mt_rand() % sizeof($characters)];
}
}
return $guid;
}
/*
* Determines if the expression is a valid guid (in uuid notation, without {})
* @param string $expression the guid to check
* @return true if the expression is a valid guid ; otherwise, false
*/
function is_guid ($expression) {
//We avoid regexp to speed up the check
//A guid is a 36 characters string
if (strlen($expression) != 36) return false;
$expression = strtolower($expression);
for ($i = 0 ; $i < 36 ; $i++) {
if ($i == 8 || $i == 13 || $i == 18 || $i == 23) {
//with dashes
if ($expression[$i] != '-') return false;
} else {
//and hex numbers
if (!is_numeric($expression[$i]) && $expression[$i] != 'a' && $expression[$i] != 'b' && $expression[$i] != 'c' && $expression[$i] != 'd' && $expression[$i] != 'e' && $expression[$i] != 'f' ) return false;
}
}
return true;
}
/**
* Gets file extension
* @param string $file the file to get the extension
* @return string the file extension
*/
function get_extension ($file) {
$dotPosition = strrpos($file, ".");
return substr($file, $dotPosition + 1);
}
/**
* Gets file name
* @param string $file the file to get the extension
* @return string the file name
*/
function get_filename ($file) {
//TODO: clear directory
$dotPosition = strrpos($file, ".");
return substr($file, 0, $dotPosition);
}
/*
* Determines if a string starts with specified substring
* @param string $haystack the string to check
* @param string $needle the substring to determines if it's the start
* @param boolean $case_sensitive determines if the search must be case sensitive
* @return boolean true if $haystack starts with $needle ; otherwise, false.
*/
function string_starts_with ($haystack, $needle, $case_sensitive = true) {
if (!$case_sensitive) {
$haystack = strtoupper($haystack);
$needle = strtoupper($needle);
}
if ($haystack == $needle) return true;
return strpos($haystack, $needle) === 0;
}
////////////////////////////////////////////////////////////////////////////////
/// ///
/// URL helpers functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
* Gets URL
* @return string URL
*/
function get_url () {
global $Config;
if (func_num_args() > 0) {
$pieces = func_get_args();
return $Config['BaseURL'] . '/' . implode('/', $pieces);
} elseif ($Config['BaseURL'] == "" || $Config['BaseURL'] == "/index.php") {
return "/";
} else {
return $Config['BaseURL'];
}
}
/*
* Gets page URL
* @return string URL
*/
function get_page_url () {
$url = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
if (substr($url, -10) == "/index.php") {
return substr($url, 0, -9);
}
return $url;
}
/*
* Gets server URL
* @todo find a way to detect https:// on non standard port
* @return string the server URL
*/
function get_server_url () {
if (php_sapi_name() == 'cli') {
return '';
}
switch ($port = $_SERVER['SERVER_PORT']) {
case '80':
return "http://$_SERVER[SERVER_NAME]";
case '443':
return "https://$_SERVER[SERVER_NAME]";
default:
return "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]";
}
}
/*
* Gets $_SERVER['PATH_INFO'] or computes the equivalent if not defined.
* @return string the relevant URL part
*/
function get_current_url () {
global $Config;
//Gets relevant URL part from relevant $_SERVER variables
if (array_key_exists('PATH_INFO', $_SERVER)) {
//Without mod_rewrite, and url like /index.php/controller
//we use PATH_INFO. It's the easiest case.
return $_SERVER["PATH_INFO"];
}
//In other cases, we'll need to get the relevant part of the URL
$current_url = get_server_url() . $_SERVER['REQUEST_URI'];
//Relevant URL part starts after the site URL
$len = strlen($Config['SiteURL']);
//We need to assert it's the correct site
if (substr($current_url, 0, $len) != $Config['SiteURL']) {
dieprint_r(GENERAL_ERROR, "Edit includes/config.php and specify the correct site URL<br /><strong>Current value:</strong> $Config[SiteURL]<br /><strong>Expected value:</strong> a string starting by " . get_server_url(), "Setup");
}
if (array_key_exists('REDIRECT_URL', $_SERVER)) {
//With mod_rewrite, we can use REDIRECT_URL
- //We takes the end of the URL, ie *FROM* $len position
+ //We take the end of the URL, ie *FROM* $len position
return substr(get_server_url() . $_SERVER["REDIRECT_URL"], $len);
}
//Last possibility: use REQUEST_URI, but remove QUERY_STRING
//If you need to edit here, use $_SERVER['REQUEST_URI']
//but you need to discard $_SERVER['QUERY_STRING']
- //We takes the end of the URL, ie *FROM* $len position
+ //We take the end of the URL, ie *FROM* $len position
$url = substr(get_server_url() . $_SERVER["REQUEST_URI"], $len);
//But if there are a query string (?action=... we need to discard it)
if ($_SERVER['QUERY_STRING']) {
return substr($url, 0, strlen($url) - strlen($_SERVER['QUERY_STRING']) - 1);
}
return $url;
}
/*
* Gets an array of url fragments to be processed by controller
* @return array an array containing URL fragments
*/
function get_current_url_fragments () {
$url_source = get_current_url();
if ($url_source == '/index.php') return array();
return explode('/', substr($url_source, 1));
}
////////////////////////////////////////////////////////////////////////////////
/// ///
/// URL xmlHttpRequest helpers functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
- * Gets an hash value to check the integrity of URLs in /do.php calls
+ * Gets a hash value to check the integrity of URLs in /do.php calls
* @param Array $args the args to compute the hash
* @return the hash paramater for your xmlHttpRequest url
*/
function get_xhr_hash ($args) {
global $Config;
array_shift($args);
return md5($_SESSION['ID'] . $Config['SecretKey'] . implode('', $args));
}
/*
* Gets the URL to call do.php, the xmlHttpRequest controller
* @return string the xmlHttpRequest url, with an integrity hash
*/
function get_xhr_hashed_url () {
global $Config;
$args = func_get_args();
$args[] = get_xhr_hash($args);
return $Config['DoURL'] . '/' . implode('/', $args);
}
/*
* Gets the URL to call do.php, the xmlHttpRequest controller
* @return string the xmlHttpRequest url
*/
function get_xhr_url () {
global $Config;
$args = func_get_args();
return $Config['DoURL'] . '/' .implode('/', $args);
}
diff --git a/workspaces/src/includes/auth/AddToGroupUserAction.php b/workspaces/src/includes/auth/AddToGroupUserAction.php
index 7f28ca2..d025872 100644
--- a/workspaces/src/includes/auth/AddToGroupUserAction.php
+++ b/workspaces/src/includes/auth/AddToGroupUserAction.php
@@ -1,60 +1,60 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Add to group user action class
*
* @package ObsidianWorkspaces
* @subpackage Auth
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
/**
- * User action to add an user into a group
+ * User action to add a user into a group
*/
class AddToGroupUserAction extends UserAction implements ObjectDeserializable {
/**
* @var UserGroup The group to add the user to
*/
public $group;
/**
* @var boolean Determines if the target user has to be added to the group in the quality of admin
*/
public $isAdmin;
/**
* Executes the user action
*/
public function run () {
if ($this->targetUser->isMemberOfGroup($this->group)) {
if ($this->isAdmin) {
//Promotes to admin if needed
$this->targetUser->addToGroup($this->group, true);
}
} else {
//Adds user to the group
$this->targetUser->addToGroup($this->group, $this->isAdmin);
}
}
/**
* Loads a AddToGroupUserAction instance from an object.
*
* @param object $data The object to deserialize
* @return AddToGroupUserAction The deserialized instance
*/
public static function loadFromObject ($data) {
$instance = new AddToGroupUserAction();
$instance->group = UserGroup::fromCode($data->code);
$instance->isAdmin = ($data->isAdmin == true);
return $instance;
}
}
diff --git a/workspaces/src/includes/auth/AuthenticationMethod.php b/workspaces/src/includes/auth/AuthenticationMethod.php
index bbe0cda..183fc69 100644
--- a/workspaces/src/includes/auth/AuthenticationMethod.php
+++ b/workspaces/src/includes/auth/AuthenticationMethod.php
@@ -1,241 +1,241 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Authentication method class
*
* @package ObsidianWorkspaces
* @subpackage Auth
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* Authentication method class
*
* This class has to be extended to implement custom authentication methods.
*/
abstract class AuthenticationMethod implements ObjectDeserializable {
/**
* @var User The local user matching the authentication
*/
public $localUser;
/**
* @var string The username
*/
public $name;
/**
* @var string The e-mail address
*/
public $email;
/**
* @var string The authentication method identifiant
*/
public $id;
/**
* @var string The remote identity provider user identifiant
*/
public $remoteUserId;
/**
* @var Message The localized authentication login message
*/
public $loginMessage;
/**
* @var boolean Determines if the authentication method could be used to register new users
*/
public $canCreateUser = false;
/**
- * @var Array Actions to execute if an user is created, eacth instance a member of UserAction
+ * @var Array Actions to execute if a user is created, each instance a member of UserAction
*/
public $createUserActions = [];
/**
* @var Context The site context
*/
public $context;
/**
* @var Message The localized authentication error message
*/
public $loginError;
/**
* Gets authentication link for this method
*/
public abstract function getAuthenticationLink();
/**
* Handles request
*/
public abstract function handleRequest();
/**
* Runs actions planned on user create
*/
protected function runCreateUserActions () {
foreach ($this->createUserActions as $action) {
$action->targetUser = $this->localUser;
$action->run();
}
}
/**
* Finds user from available data
*
- * @return User the user if an user has been found; otherwise, false.
+ * @return User the user if a user has been found; otherwise, false.
*/
private function findUser () {
if ($this->remoteUserId != '') {
$user = User::getUserFromRemoteIdentity(
$this->id, $this->remoteUserId
);
if ($user !== null) return $user;
}
if ($this->email != '') {
$user = User::get_user_from_email($this->email);
if ($user !== null) return $user;
}
return null;
}
/**
* Signs in or creates a new user
*
* @return boolean true if user has been successfully logged in; otherwise, false.
*/
public function signInOrCreateUser () {
- // At this stage, if we don't already have an user instance,
+ // At this stage, if we don't already have a user instance,
// we're fetching it by remote user id or mail.
//
// If no result is returned, we're creating a new user if needed.
//
// Finally, we proceed to log in.
if ($this->localUser === null) {
$this->localUser = $this->findUser();
}
if ($this->localUser === null) {
if (!$this->canCreateUser) {
$this->loginError = Language::get("ExternalLoginCantCreateAccount");
return false;
} else {
$this->createUser();
if ($this->localUser === null) {
- throw new Exception("Can't sign in: after correct remote authentication, an error occured creating locally a new user.");
+ throw new Exception("Can't sign in: after correct remote authentication, an error occurred creating locally a new user.");
}
}
}
$this->signIn($this->localUser);
return true;
}
/**
* Signs in the specified user
*
* @param User The user to log in
*/
public function signIn(User $user) {
$this->context->session->user_login($user->id);
}
/**
- * Creates a new user based on the authentication provisionning information
+ * Creates a new user based on the authentication provisioning information
*
* @return User The user created
*/
public function createUser () {
if (!$this->canCreateUser) {
throw new Exception("Can't create user: the canCreateUser property is set at false.");
}
$user = User::create();
$user->name = $this->name;
$user->email = $this->email;
$user->save_to_database();
$user->setRemoteIdentity(
$this->id, $this->remoteUserId
);
$this->localUser = $user;
$this->runCreateUserActions();
}
/**
* Gets authentication method from ID
*
* @param string $id The authentication method id
* @param Context $context The site context
* @return AuthenticationMethod The authentication method matching the id
*/
public static function getFromId ($id, $context) {
if ($context->workspace != null) {
foreach ($context->workspace->configuration->authenticationMethods as $authenticationMethod) {
if ($authenticationMethod->id == $id) {
return $authenticationMethod;
}
}
}
return null;
}
/**
* Loads a AuthenticationMethod instance from a generic object. Typically used to deserialize a JSON document.
*
* @param object $data The object to deserialize
* @return AuthenticationMethod The deserialized instance
*/
public static function loadFromObject ($data) {
$instance = new static;
if (!property_exists($data, 'id')) {
throw new InvalidArgumentException("Authentication method id is required.");
}
$instance->id = $data->id;
if (property_exists($data, 'loginMessage')) {
$instance->loginMessage = new Message($data->loginMessage);
} else {
$instance->loginMessage = new Message(Language::get("SignIn"));
}
if (property_exists($data, 'createUser')) {
if (property_exists($data->createUser, 'enabled')) {
$instance->canCreateUser = ($data->createUser->enabled == true);
}
if (property_exists($data->createUser, 'addToGroups')) {
foreach ($data->createUser->addToGroups as $actionData) {
$instance->createUserActions[] = AddToGroupUserAction::loadFromObject($actionData);
}
}
if (property_exists($data->createUser, 'givePermissions')) {
foreach ($data->createUser->givePermissions as $actionData) {
$instance->createUserActions[] = GivePermissionUserAction::loadFromObject($actionData);
}
}
}
return $instance;
}
}
diff --git a/workspaces/src/includes/cache/cache.php b/workspaces/src/includes/cache/cache.php
index 8f74a43..3c070de 100644
--- a/workspaces/src/includes/cache/cache.php
+++ b/workspaces/src/includes/cache/cache.php
@@ -1,84 +1,84 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Cache loader class.
*
* This file provides a calling class, which read the configuration, ensures
* the cache class for the cache engine given in config exists and initializes
* it.
*
* You'll find a sample of implementation in the CacheMemcached.
* @see CacheMemcached
*
* If no caching mechanism, a "blackhole" void cache will be used.
* @see CacheVoid.
*
* The class to call is determined from the following preference:
* <code>
* $Config['cache']['engine'] = 'memcached'; //will use CacheMemcached class.
* </code>
*
* @package ObsidianWorkspaces
* @subpackage Cache
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
/**
* Cache caller
*/
class Cache {
/**
* Gets the cache instance, initializing it if needed
*
* The correct cache instance to initialize will be determined from the
* $Config['cache']['engine'] preference.
*
* The class cache to use will be Cache + (preference engine, capitalized)
*
- * This method will creates an instance of the specified object,
+ * This method will create an instance of the specified object,
* calling the load static method from this object class.
*
* Example:
* <code>
* $Config['cache']['engine'] = 'quux';
* $cache = Cache::load(); //Cache:load() will call CacheQuux:load();
* </code>
*
* @return Cache the cache instance
*/
static function load () {
global $Config;
if (
!array_key_exists('cache', $Config) ||
!array_key_exists('engine', $Config['cache'])
) {
//cache is not configured or engine is not specified
$engine = 'void';
} else {
//engine is specified in the configuration
$engine = $Config['cache']['engine'];
}
$engine_file = 'includes/cache/' . $engine . '.php';
$engine_class = 'Cache' . ucfirst($engine);
if (!file_exists($engine_file)) {
message_die(GENERAL_ERROR, "Can't initialize $engine cache engine.<br />$engine_file not found.", 'Cache');
}
require_once($engine_file);
if (!class_exists($engine_class)) {
message_die(GENERAL_ERROR, "Can't initialize $engine cache engine.<br />$engine_class class not found.", 'Cache');
}
return call_user_func(array($engine_class, 'load'));
}
}
diff --git a/workspaces/src/includes/cache/void.php b/workspaces/src/includes/cache/void.php
index f5cfe8e..bb33e58 100644
--- a/workspaces/src/includes/cache/void.php
+++ b/workspaces/src/includes/cache/void.php
@@ -1,73 +1,73 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* "Blackhole" void cache.
*
* @package ObsidianWorkspaces
* @subpackage Cache
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
/**
* "blackhole" void cache
*
- * This class doesn't cache information, it'a void wrapper
+ * This class doesn't cache information, it's a void wrapper
* get will always return null
* set and delete do nothing
*
* It will be used by default if no cache is specified.
*
* This class implements a singleton pattern.
*/
class CacheVoid {
/**
* @var CacheVoid the current cache instance
*/
static $instance = null;
/**
* Gets the cache instance, initializing it if needed
*
* @return Cache the cache instance, or null if nothing is cached
*/
static function load () {
if (self::$instance === null) {
self::$instance = new CacheVoid();
}
return self::$instance;
}
/**
* Gets the specified key's data
*
* @param string $key the key to fetch
* @return mixed the data at the specified key
*/
function get ($key) {
return null;
}
/**
* Sets the specified data at the specified key
*
* @param string $key the key where to store the specified data
* @param mixed $value the data to store
*/
function set ($key, $value) { }
/**
* Deletes the specified key's data
*
* @param string $key the key to delete
*/
function delete ($key) { }
}
diff --git a/workspaces/src/includes/collection/MySQLCollection.php b/workspaces/src/includes/collection/MySQLCollection.php
index c917049..37270f0 100644
--- a/workspaces/src/includes/collection/MySQLCollection.php
+++ b/workspaces/src/includes/collection/MySQLCollection.php
@@ -1,167 +1,167 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* MySQL Collection class
*
* @package ObsidianWorkspaces
* @subpackage Collection
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* MySQL Collection class
*
* This class represents a collection of documents, stored on MySQL.
*/
class MySQLCollection extends SQLCollection {
///
/// Singleton pattern to get the MySQLDatabase instance
///
/**
* @var MySQLDatabase The mongo client to the database the collection is hosted
*/
public static $client = null;
/**
* Gets the existing MySQLDatabase instance, or if not available, initializes one.
*
* @param Context $context
* @return MySQLDatabase The MySQLDatabase instance
*/
public static function getCurrentSiteDatabaseClient () {
if (self::$client === null) {
$client = Database::load();
if ($candidateClient instanceof MySQLDatabase) {
self::$client = $client;
} else {
throw new InvalidArgumentException("The MySQLDatabase driver is intended to be used when your main database product is MySQL. We recommend whether you pick the same engine for collections and other db use, whether you use a key/store storage solution for collections, like MongoDB.");
}
}
return self::$client;
}
///
/// Constructor
///
/**
* Initializes a new instance of MongoCollection
*
* @param string $id the collection identifiant
*/
public function __construct ($id, ?MySQLDatabase $client = null, $table = '') {
global $Config;
if ($client === null) {
self::getCurrentSiteDatabaseClient();
} else {
self::$client = $client;
}
if ($table == '') {
if (!array_key_exists('DocumentStorage', $Config) || !array_key_exists('Table', $Config['DocumentStorage'])) {
throw new Exception("Configuration parameter missing: \$Config['DocumentStorage']['Table']. Expected value for this parameter is the table to store the collections documents.");
}
$this->table = $Config['DocumentStorage']['Table'];
} else {
$this->table = $table;
}
$this->id = $id;
$this->initializeCollectionsTable();
}
///
/// Helper to create schema if required
///
/**
- * Initialiazes collections table
+ * Initializes collections table
*/
protected function initializeCollectionsTable () {
if (defined('COLLECTIONS_MYSQL_DATABASE_READY') && COLLECTIONS_MYSQL_DATABASE_READY) {
return;
}
self::$client->query("
CREATE TABLE if not exists $this->table (
collection_id VARCHAR(255),
document_id VARCHAR(255),
document_value BLOB,
PRIMARY KEY (collection_id, document_id)
);"
);
define('COLLECTIONS_MYSQL_DATABASE_READY', true);
}
///
/// SqlCollection implementation
///
/**
* Executes a SQL query
*
* @param string $sql The SQL query
- * @return mixed If the query doesn't return any result, null. If the query return a row with one field, the scalar value. Otheriwse, an aossciative array, the fields as keys, the row as values.
+ * @return mixed If the query doesn't return any result, null. If the query return a row with one field, the scalar value. Otherwise, an associative array, the fields as keys, the row as values.
*/
public function query ($sql) {
if ($sql == "") {
return null;
}
$db = self::$client;
if (!$result = $db->query($sql, MYSQL_ASSOC)) {
throw new Exception("Can't execute collection query.");
}
if (!$row = $db->fetchRow($result)) {
return null;
}
if (count($row) == 1) {
return array_shift($row);
} else {
return $row;
}
}
/**
* Escapes the SQL string
*
* @param string $value The value to escape
* @return string The escaped value
*/
public function escape ($value) {
return self::$client->escape($value);
}
/**
* Gets all the documents from the collection
*
* @return Iterator An iterator to the documents, each item an instance of CollectionDocument
*/
public function getAll () {
$db = self::$client;
$collectionId = $this->escape($this->id);
$sql = "SELECT * FROM $this->table WHERE collection_id = '$collectionId'";
if (!$result = $db->query($sql, MYSQL_ASSOC)) {
throw new Exception("Can't get each collection documents.");
}
$type = $this->documentType;
while ($row = $db->fetchRow($result)) {
$data = json_decode($row['document_value']);
yield $type::loadFromObject($data);
}
}
}
diff --git a/workspaces/src/includes/collection/SQLCollection.php b/workspaces/src/includes/collection/SQLCollection.php
index ea29761..8494c5f 100644
--- a/workspaces/src/includes/collection/SQLCollection.php
+++ b/workspaces/src/includes/collection/SQLCollection.php
@@ -1,139 +1,139 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* SQL Collection abstract class
*
* @package ObsidianWorkspaces
* @subpackage Collection
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* Abstract class with SQL standard implementation of CRUD features for collections using a SQL database.
*/
abstract class SQLCollection extends Collection {
/**
* @var string The SQL collections table
*/
public $table;
/**
* Executes a SQL query
*
* @param string $sql The SQL query
- * @return mixed If the query doesn't return any null, nothing. If the query return a row with one field, the scalar value. Otheriwse, an aossciative array, the fields as keys, the row as values.
+ * @return mixed If the query doesn't return any null, nothing. If the query return a row with one field, the scalar value. Otherwise, an associative array, the fields as keys, the row as values.
*/
public abstract function query ($sql);
/**
* Escapes the SQL string
*
* @param string $value The value to escape
* @return string The escaped value
*/
public abstract function escape ($value);
/**
* Adds a document to the collection
*
* @param CollectionDocument $document The document to add
* @return boolean true if the operation succeeded; otherwise, false.
*/
public function add (CollectionDocument &$document) {
if ($document->id === '') {
$document->id = uniqid();
}
$collectionId = $this->escape($this->id);
$documentId = $this->escape($document->id);
$value = $this->escape(json_encode($document));
$sql = "INSERT INTO $this->table "
. "(collection_id, document_id, document_value) VALUES "
. "('$collectionId', '$documentId', '$value')";
$this->query($sql);
}
/**
* Deletes a document from the collection
*
* @param string $documentId The identifiant of the document to delete
* @return boolean true if the operation succeeded; otherwise, false.
*/
public function delete ($documentId) {
$collectionId = $this->escape($this->id);
$documentId = $this->escape($documentId);
$sql = "DELETE FROM $this->table WHERE collection_id = '$collectionId' AND document_id = '$documentId'";
$this->query($sql);
}
/**
* Determines if a document exists
*
* @param CollectionDocument $document The document to check
* @return boolean true if the document exists; otherwise, false.
*/
public function exists (CollectionDocument $document) {
$collectionId = $this->escape($this->id);
$documentId = $this->escape($document->id);
$sql = "SELECT count(*) FROM $this->table WHERE collection_id = '$collectionId' AND document_id = '$documentId'";
return $this->query($sql) == 1;
}
/**
* Updates a document in the collection
*
* @param CollectionDocument $document The document to update
* @return boolean true if the operation succeeded; otherwise, false.
*/
public function update (CollectionDocument &$document) {
$collectionId = $this->escape($this->id);
$documentId = $this->escape($document->id);
$value = $this->escape(json_encode($document));
$sql = "UPDATE $this->table SET document_value = '$value' WHERE collection_id = '$collectionId' AND document_id = '$documentId'";
$this->query($sql);
}
/**
* Gets a document from the collection
*
* @param string $documentId The identifiant of the document to get
* @param CollectionDocument $document The document
*/
public function get ($documentId){
$type = $this->documentType;
if (!class_exists($type)) {
throw new Exception("Can't create an instance of $type. If the class exists, did you registered a SPL autoloader or updated includes/autoload.php?");
}
$collectionId = $this->escape($this->id);
$documentId = $this->escape($documentId);
$sql = "SELECT document_value FROM $this->table WHERE collection_id = '$collectionId' AND document_id = '$documentId'";
$data = $this->query($sql);
$data = json_decode($data);
return $type::loadFromObject($data);
}
/**
* Gets a count of the documents in the collection
*
* @return int The number of documents
*/
public function count () {
$collectionId = $this->escape($this->id);
$sql = "SELECT count(*) FROM $this->table WHERE collection_id = '$collectionId'";
return $this->query($sql);
}
}
diff --git a/workspaces/src/includes/collection/SQLiteCollection.php b/workspaces/src/includes/collection/SQLiteCollection.php
index e948c73..1545f99 100644
--- a/workspaces/src/includes/collection/SQLiteCollection.php
+++ b/workspaces/src/includes/collection/SQLiteCollection.php
@@ -1,184 +1,184 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* SQLite Collection class
*
* @package ObsidianWorkspaces
* @subpackage Collection
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* SQLite Collection class
*
* This class represents a collection of documents, stored on MySQL.
*/
class SQLiteCollection extends SQLCollection {
///
/// Singleton pattern to get or initialize the SQLite instance
///
/**
* @var SQLite3 The SQLite client to the database the collection is hosted
*/
public static $client = null;
/**
* Gets the existing SQLite3 instance, or if not available, initializes one.
*
* @return SQLite3 The SQLite3 instance
*/
public static function getClient () {
if (self::$client === null) {
self::$client = self::initializeClient();
}
return self::$client;
}
/**
* Initializes a new SQLite3 instance
*
* @return SQLite3 the client
*/
public static function initializeClient () {
global $Config;
if (!array_key_exists('DocumentStorage', $Config) || !array_key_exists('File', $Config['DocumentStorage'])) {
throw new Exception("Configuration parameter missing: \$Config['DocumentStorage']['File']. Expected value for this parameter is the path to the SQLite database file.");
}
return new SQLite3($Config['DocumentStorage']['File']);
}
///
/// Constructor
///
/**
* Initializes a new instance of MongoCollection
*
* @param string $id the collection identifiant
*/
public function __construct ($id) {
$this->table = 'collections';
$this->id = $id;
$this->initializeCollectionsTable();
}
///
/// Helper to create SQLite3 schema if required
///
/**
- * Initializaes collections table
+ * Initializes collections table
*/
protected function initializeCollectionsTable () {
if (defined('COLLECTIONS_SQLITE_DATABASE_READY') && COLLECTIONS_SQLITE_DATABASE_READY) {
return;
}
$client = static::getClient();
$client->exec("
CREATE TABLE if not exists $this->table (
collection_id TEXT,
document_id TEXT,
document_value BLOB,
PRIMARY KEY (collection_id, document_id)
);"
);
define('COLLECTIONS_SQLITE_DATABASE_READY', true);
}
///
/// SqlCollection implementation
///
/**
* Determines if the SQL query is a statement
*
* @return boolean true is a SELECT one; otherwise, false.
* @todo To use this outside the Collection scope, adds the other cases where a query is indicated.
*/
public static function isStatement ($sql) {
$instruction = strtoupper(strstr($sql, ' ', true));
return $instruction != "SELECT" && $instruction != "PRAGMA";
}
/**
* Executes a SQL query
*
* @param string $sql The SQL query
* @return mixed If the query doesn't return any result, null. If the query return a row with one field, the scalar value. Otherwise, an associative array, the fields as keys, the row as values.
*/
public function query ($sql) {
$client = static::getClient();
if (static::isStatement($sql)) {
if (!$client->exec($sql)) {
throw new Exception(
"Can't execute collection query. "
. $client->lastErrorMsg()
);
}
return null;
}
$result = $client->query($sql);
if ($result === true) {
return null;
}
if ($result === false) {
throw new Exception(
"Can't execute collection query. "
. $client->lastErrorMsg()
);
}
$row = $result->fetchArray(SQLITE3_ASSOC);
$scalar = ($result->numColumns() == 1);
$result->finalize();
if ($scalar) {
return array_shift($row);
} else {
return $row;
}
}
/**
* Escapes the SQL string
*
* @param string $value The value to escape
* @return string The escaped value
*/
public function escape ($value) {
return SQLite3::escapeString($value);
}
/**
* Gets all the documents from the collection
*
* @return Iterator An iterator to the documents, each item an instance of CollectionDocument
*/
public function getAll () {
$collectionId = $this->escape($this->id);
$sql = "SELECT document_value FROM $this->table WHERE collection_id = '$collectionId'";
$client = static::getClient();
$type = $this->documentType;
$result = $client->query($sql);
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$data = json_decode($row['document_value']);
yield $type::loadFromObject($data);
}
}
}
diff --git a/workspaces/src/includes/config.php b/workspaces/src/includes/config.php
index ee6d24a..0de7fab 100755
--- a/workspaces/src/includes/config.php
+++ b/workspaces/src/includes/config.php
@@ -1,284 +1,284 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Configuration file
*
* This file will contain your site/application settings. Ideally, you should
* make this file autogenerable by a setup process.
*
* @package ObsidianWorkspaces
* @subpackage Keruald
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
use Keruald\Database\Engines\MySQLiEngine;
////////////////////////////////////////////////////////////////////////////////
/// ///
/// I. SQL configuration ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//SQL configuration
$Config['sql']['engine'] = MySQLiEngine::class;
$Config['sql']['host'] = 'localhost';
$Config['sql']['username'] = 'obsidian';
$Config['sql']['password'] = 'obsidian';
$Config['sql']['database'] = 'obsidian';
//SQL tables
$prefix = '';
define('TABLE_PERMISSIONS', $prefix . 'permissions');
define('TABLE_USERS', $prefix . 'users');
define('TABLE_USERS_AUTH', $prefix . 'users_auth');
define('TABLE_UGROUPS', $prefix . 'users_groups');
define('TABLE_UGROUPS_MEMBERS', $prefix . 'users_groups_members');
define('TABLE_SESSIONS', $prefix . 'sessions');
define('TABLE_WORKSPACES', $prefix . 'workspaces');
//TODO: you can add here your own tables and views
////////////////////////////////////////////////////////////////////////////////
/// ///
/// II. Site configuration ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//TODO: you can add here settings like default site theme or the app title.
//Dates
date_default_timezone_set("UTC");
//Secret key, used for some verification hashes in URLs (e.g. xhr calls)
//or forms.
$Config['SecretKey'] = 'Replace this by a secret key, like AdYN}"p/+D.U]M^MC&-Q~KFthXZCT*g<V:dL.@{Mt-Di1mEA\&~_Eh\I\WA';
//When reading files, buffer size
define('BUFFER_SIZE', 4096);
//Site theme
$Config['Theme'] = 'bluegray';
////////////////////////////////////////////////////////////////////////////////
/// ///
/// III. Script URLs ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
* The following settings give your script/application URL.
*
* Without mod_rewrite:
*
* Subdirectory:
* - $Config['SiteURL'] = 'http://www.yourdomain.tld/application/index.php';
* - $Config['BaseURL'] = '/application/index.php';
*
* Root directory:
* - $Config['SiteURL'] = 'http://www.yourdomain.tld/index.php';
* - $Config['BaseURL'] = '/index.php';
*
* With mod_rewrite:
*
* Subdirectory:
* - $Config['SiteURL'] = 'http://www.yourdomain.tld/application';
* - $Config['BaseURL'] = '/application';
*
* In .htaccess or your vhost definition:
* RewriteEngine On
* RewriteBase /application/
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteCond %{REQUEST_FILENAME} !-d
* RewriteRule . /application/index.php [L]
*
* Root directory:
* - $Config['SiteURL'] = 'http://www.yourdomain.tld';
* - $Config['BaseURL'] = '';
*
* In .htaccess or your vhost definition:
* RewriteEngine On
* RewriteBase /
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteCond %{REQUEST_FILENAME} !-d
* RewriteRule . /index.php [L]
*
*
* If you don't want to specify the server domain, you can use get_server_url:
* $Config['SiteURL'] = get_server_url() . '/application';
* $Config['SiteURL'] = get_server_url();
*
* !!! No trailing slash !!!
*
*/
$Config['SiteURL'] = get_server_url();
$Config['BaseURL'] = '';
//xmlHttpRequest callbacks URL
$Config['DoURL'] = $Config['SiteURL'] . "/do.php";
////////////////////////////////////////////////////////////////////////////////
/// ///
/// IV. Static content ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//Where the static content is located?
//Static content = 4 directories: js, css, img and content
//On default installation, those directories are at site root.
//To improve site performance, you can use a CDN for that.
//
//Recommanded setting: $Config['StaticContentURL'] = $Config['SiteURL'];
//Or if this is the site root: $Config['StaticContentURL'] = '';
//With CoralCDN: $Config['StaticContentURL'] = . '.nyud.net';
//
$Config['StaticContentURL'] = '';
//$Config['StaticContentURL'] = get_server_url() . '.nyud.net';
//Content directories
$Config['Content']['Cache'] = 'content/cache';
$Config['Content']['Help'] = 'content/help';
$Config['Content']['Workspaces'] = 'content/workspaces';
$Config['Content']['Disclaimers'] = 'content/disclaimers';
/*
* The following settings configure your document storage engine.
*
* To use MongoDB:
*
* $Config['DocumentStorage'] = [
* 'Type' => 'MongoDB',
* 'Host' => 'mymongoinstance.domain.tld',
* 'Port' => 27017,
* 'Database' => 'obsidian'
* ];
*
* To use MongoDB, and authenticate with a username and a password:
*
* $Config['DocumentStorage'] = [
* 'Type' => 'MongoDB',
* 'Host' => 'mymongoinstance.domain.tld',
* 'Port' => 27017,
* 'Database' => 'obsidian',
* 'Username' => 'yourusername',
* 'Password' => 'yourpassword'
* ];
*
- * To connect to MongoDB with SSL, use the same syanx and add a SSL context as 'SSL' parameter.
+ * To connect to MongoDB with SSL, use the same syntax and add a SSL context as 'SSL' parameter.
* Documentation about SSL context is located at the following PHP documentation URL:
* http://www.php.net/manual/en/context.ssl.php
*
* $Config['DocumentStorage'] = [
* 'Type' => 'MongoDB',
* 'Host' => 'mymongoinstance.domain.tld',
* 'Port' => 27017,
* 'Database' => 'obsidian',
* 'SSL' => [
* 'cafile' => '/path/to/CAcertificate.crt',
* 'local_cert' => '/path/to/yourcertificate.pem',
* 'verify_peer' => true,
* 'allow_self_signed' => false,
* 'CN_match' => 'the server certificate expected CN'
* ]
* ];
*
*
* If you don't want to deploy a MongoDB server, you can use either MySQL
* or SQLite 3 if you need concurrency, either plain text files if you're
* the only user as a fallback.
*
*
* For MySQL, it uses the same connection as the main application.
*
* $Config['DocumentStorage'] = [
* 'Type' => 'MySQL',
* 'Table' => $prefix . 'collections',
* ];
*
* Engine will automatically intialize the database if the file hasn't been found.
*
* You can also store the table in another database with the db.table syntax:
*
* $Config['DocumentStorage'] = [
* 'Type' => 'MySQL',
* 'Table' => 'obsidian_data.collections',
* ];
*
*
* To use SQLite 3:
*
* $Config['DocumentStorage'] = [
* 'Type' => 'SQLite',
* 'File' => 'content/collections.db',
* ];
*
* Engine will automatically intialize the database if the file hasn't been found.
*
*
* To use file storage, create a folder and gives it as path parameter:
*
* $Config['DocumentStorage'] = [
* 'Type' => 'Files',
* 'Path' => 'content/collections',
* ];
*
*/
$Config['DocumentStorage'] = [
'Type' => 'MongoDB',
'Host' => 'localhost',
'Port' => 27017
];
//ImageMagick paths
//Be careful on Windows platform convert could match the NTFS convert command.
$Config['ImageMagick']['convert'] = 'convert';
$Config['ImageMagick']['mogrify'] = 'mogrify';
$Config['ImageMagick']['composite'] = 'composite';
$Config['ImageMagick']['identify'] = 'identify';
////////////////////////////////////////////////////////////////////////////////
/// ///
/// V. Caching ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
* Some data (Smarty, OpenID and sessions) are cached in the cache directory.
*
* Security tip: you can move this cache directory outside the webserver tree.
*/
define('CACHE_DIR', 'cache');
/*
* Furthermore, you can also enable a cache engine, like memcached, to store
* data from heavy database queries, or frequently accessed stuff.
*
* To use memcached:
* - $Config['cache']['engine'] = 'memcached';
* - $Config['cache']['server'] = 'localhost';
* - $Config['cache']['port'] = 11211;
*
* To disable cache:
* - $Config['cache']['engine'] = 'void';
- * (or don't write nothing at all)
+ * (or omit the cache key)
*/
$Config['cache']['engine'] = 'void';
////////////////////////////////////////////////////////////////////////////////
/// ///
/// VI. Sessions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//If you want to use a common table of sessions / user handling
//with several websites, specify a different resource id for each site.
$Config['ResourceID'] = 32;
diff --git a/workspaces/src/includes/objects/user.php b/workspaces/src/includes/objects/user.php
index ad1137e..bdbccc7 100755
--- a/workspaces/src/includes/objects/user.php
+++ b/workspaces/src/includes/objects/user.php
@@ -1,412 +1,412 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* User class
*
* @package ObsidianWorkspaces
* @subpackage Model
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
/**
* User class
*/
class User {
public $id;
public $name;
public $password;
public $active = 0;
public $email;
public $regdate;
/**
* @var Array An array of users already loaded, the username as user id
*/
public static $hashtableById = [];
/**
* @var array|null An array of the workspaces the user has access to, each element an instance of the Workspace object. As long as the field hasn't been initialized by get_workspaces, null.
*/
private $workspaces = null;
/*
* Initializes a new instance
*
* @param int $id the primary key
*/
function __construct ($id = null) {
if ($id) {
$this->id = $id;
$this->load_from_database();
}
}
/**
* Initializes a new User instance if needed or get already available one.
*
* @param iint $id the user ID
* @return User the user instance
*/
static function get ($id = NULL) {
if ($id && array_key_exists($id, User::$hashtableById)) {
return self::$hashtableById[$id];
}
$user = new self($id);
return $user;
}
/**
* Loads the object User (ie fill the properties) from the $_POST array
*/
function load_from_form () {
if (array_key_exists('name', $_POST)) $this->name = $_POST['name'];
if (array_key_exists('password', $_POST)) $this->password = $_POST['password'];
if (array_key_exists('active', $_POST)) $this->active = $_POST['active'];
if (array_key_exists('actkey', $_POST)) $this->actkey = $_POST['actkey'];
if (array_key_exists('email', $_POST)) $this->email = $_POST['email'];
if (array_key_exists('regdate', $_POST)) $this->regdate = $_POST['regdate'];
}
/**
* Loads the object User (ie fill the properties) from the database
*/
function load_from_database () {
global $db;
$sql = "SELECT * FROM " . TABLE_USERS . " WHERE user_id = '" . $this->id . "'";
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Unable to query users", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
- $this->lastError = "User unkwown: " . $this->id;
+ $this->lastError = "User unknown: " . $this->id;
return false;
}
$this->load_from_row($row);
return true;
}
/**
* Loads the object User (ie fill the properties) from the database row
*/
function load_from_row ($row) {
$this->id = $row['user_id'];
$this->name = $row['username'];
$this->password = $row['user_password'];
$this->active = $row['user_active'] ? true : false;
$this->email = $row['user_email'];
$this->regdate = $row['user_regdate'];
//Puts object in hashtable, so it's accessible in future call of
//this run through User::get($id).
self::$hashtableById[$this->id] = $this;
}
/**
* Saves to database
*/
function save_to_database () {
global $db;
$id = $this->id ? "'" . $db->sql_escape($this->id) . "'" : 'NULL';
$name = $db->sql_escape($this->name);
$password = $db->sql_escape($this->password);
$active = $this->active ? 1 : 0;
$email = $db->sql_escape($this->email);
$regdate = $this->regdate ? "'" . $db->sql_escape($this->regdate) . "'" : 'NULL';
//Updates or inserts
$sql = "REPLACE INTO " . TABLE_USERS . " (`user_id`, `username`, `user_password`, `user_active`, `user_email`, `user_regdate`) VALUES ($id, '$name', '$password', $active, '$email', $regdate)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save user", '', __LINE__, __FILE__, $sql);
}
if (!$this->id) {
//Gets new record id value
$this->id = $db->sql_nextid();
}
}
/**
* Updates the specified field in the database record
*/
function save_field ($field) {
global $db;
if (!$this->id) {
message_die(GENERAL_ERROR, "You're trying to update a record not yet saved in the database");
}
$id = $db->sql_escape($this->id);
$value = $db->sql_escape($this->$field);
$sql = "UPDATE " . TABLE_USERS . " SET `$field` = '$value' WHERE user_id = '$id'";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save $field field", '', __LINE__, __FILE__, $sql);
}
}
//
// USER MANAGEMENT FUNCTIONS
//
/**
* Generates a unique user id
*/
function generate_id () {
global $db;
do {
$this->id = mt_rand(2001, 9999);
$sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE user_id = $this->id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't check if a user id is free", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
} while ($row[0]);
}
/**
* Fills password field with encrypted version
* of the specified clear password
*/
public function set_password ($newpassword) {
$this->password = md5($newpassword);
}
/**
* Checks if a login is available
*
* @param string $login the login to check
- * @return boolean true if the login is avaiable; otherwise, false.
+ * @return boolean true if the login is available; otherwise, false.
*/
public static function is_available_login ($login) {
global $db;
$sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE username = '$login'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't check if the specified login is available", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 0);
}
/**
* Initializes a new User instance ready to have its property filled
*
* @return User the new user instance
*/
public static function create () {
$user = new User();
$user->generate_id();
$user->active = true;
$user->regdate = time();
return $user;
}
/**
* Gets user from specified e-mail
*
* @return User the user matching the specified e-mail; null, if the mail were not found.
*/
public static function get_user_from_email ($mail) {
global $db;
$sql = "SELECT * FROM " . TABLE_USERS . " WHERE user_email = '$mail'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get user", '', __LINE__, __FILE__, $sql);
}
if ($row = $db->sql_fetchrow($result)) {
//E-mail found.
$user = new User();
$user->load_from_row($row);
return $user;
}
//E-mail not found.
return null;
}
//
// REMOTE IDENTITY PROVIDERS
//
/**
* Gets user from remote identity provider identifiant
*
* @param $authType The authentication method type
- * @param $remoteUserId The remote user idenfifiant
+ * @param $remoteUserId The remote user identifier
* @return User the user matching the specified identity provider and identifiant; null if no user were found.
*/
public static function getUserFromRemoteIdentity ($authType, $remoteUserId) {
global $db;
$authType = $db->sql_escape($authType);
$remoteUserId = $db->sql_escape($remoteUserId);
$sql = "SELECT user_id FROM " . TABLE_USERS_AUTH . " WHERE "
. "auth_type = '$authType' AND auth_identity = '$remoteUserId'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get user", '', __LINE__, __FILE__, $sql);
}
if ($row = $db->sql_fetchrow($result)) {
return User::get($row['user_id']);
}
return null;
}
/**
* Sets user's remote identity provider identifiant
*
* @param $authType The authentication method type
- * @param $remoteUserId The remote user idenfifiant
+ * @param $remoteUserId The remote user identifier
* */
public function setRemoteIdentity ($authType, $remoteUserId, $properties = null) {
global $db;
$authType = $db->sql_escape($authType);
$remoteUserId = $db->sql_escape($remoteUserId);
$properties = ($properties === NULL) ? 'NULL' : "'" . $db->sql_escape($properties) . "'";
$sql = "INSERT INTO " . TABLE_USERS_AUTH . " (auth_type, auth_identity, auth_properties, user_id) "
. "VALUES ('$authType', '$remoteUserId', $properties, $this->id)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't set user remote identity provider information", '', __LINE__, __FILE__, $sql);
}
}
//
// INTERACTION WITH OTHER OBJECTS
//
/**
* Gets the groups where the current user has access to.
*
* @return array an array containing group_id, matching groups the current user has access to.
*/
public function get_groups () {
return self::get_groups_from_user_id($this->id);
}
/**
* Determines if the user is a member of the specified group
*
* @param UserGroup $group The group to check
*/
public function isMemberOfGroup (UserGroup $group) {
global $db;
$sql = "SELECT count(*) FROM users_groups_members WHERE group_id = $group->id AND user_id = $this->id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't determine if the user belongs to the group", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return $row[0] == 1;
}
/**
* Adds user to the specified group
*
* @param UserGroup $group The group where to add the user
* @parap boolean $isAdmin if true, set the user admin; otherwise, set it regular user.
*/
public function addToGroup (UserGroup $group, $isAdmin = false) {
global $db;
$isAdmin = $isAdmin ? 1 : 0;
$sql = "REPLACE INTO users_groups_members VALUES ($group->id, $this->id, $isAdmin)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't add user to group", '', __LINE__, __FILE__, $sql);
}
}
/**
* Gets the SQL permission clause to select resources where the user is the subject.
*
* @return string The SQL WHERE clause
*/
public function get_permissions_clause () {
return self::get_permissions_clause_from_user_id($this->id);
}
/**
- * Gets workspaces this user has accces to.
+ * Gets workspaces this user has access to.
*
* @return Array A list of workspaces
*/
public function get_workspaces () {
if ($this->workspaces === null) {
$this->workspaces = Workspace::get_user_workspaces($this->id);
}
return $this->workspaces;
}
/**
* Sets user permission
*
* @param string $resourceType The target resource type
* @param int $resourceId The target resource ID
* @param string $permissionName The permission name
* @param int $permissionFlag The permission flag (facultative; by default, 1)
*/
public function setPermission ($resourceType, $resourceId, $permissionName, $permissionFlag = 1) {
global $db;
$resourceType = $db->sql_escape($resourceType);
if (!is_numeric($resourceId)) {
throw new Exception("Resource ID must be a positive or null integer, and not $resourceId.");
}
$permissionName = $db->sql_escape($permissionName);
if (!is_numeric($permissionFlag)) {
throw new Exception("Permission flag must be a positive or null integer, and not $permissionFlag.");
}
$sql = "REPLACE INTO permissions
(subject_resource_type, subject_resource_id,
target_resource_type, target_resource_id,
permission_name, permission_flag)
VALUES
('U', $this->id,
'$resourceType', $resourceId,
'$permissionName', $permissionFlag)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't set user permission", '', __LINE__, __FILE__, $sql);
}
}
/**
- * Gets the groups where an user has access to.
+ * Gets the groups where a user has access to.
*
* @param int $user_id the user to get the groups list
* @return array an array containing group_id, matching groups the specified user has access to.
*/
public static function get_groups_from_user_id ($user_id) {
global $db;
$sql = "SELECT group_id FROM " . TABLE_UGROUPS_MEMBERS . " WHERE user_id = " . $user_id;
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get user groups", '', __LINE__, __FILE__, $sql);
}
$gids = array();
while ($row = $db->sql_fetchrow($result)) {
$gids[] = $row['group_id'];
}
return $gids;
}
/**
* Gets the SQL permission clause to select resources where the specified user is the subject.
*
* @param $user_id The user ID
* @return string The SQL WHERE clause
*/
public static function get_permissions_clause_from_user_id ($user_id) {
$clause = "subject_resource_type = 'U' AND subject_resource_id = $user_id";
if ($groups = self::get_groups_from_user_id ($user_id)) {
$clause = "($clause) OR (subject_resource_type = 'G' AND subject_resource_id = ";
$clause .= join(") OR (subject_resource_type = 'G' AND subject_resource_id = ", $groups);
$clause .= ')';
}
return $clause;
}
}
diff --git a/workspaces/src/includes/objects/usergroup.php b/workspaces/src/includes/objects/usergroup.php
index 7682654..987b8d3 100644
--- a/workspaces/src/includes/objects/usergroup.php
+++ b/workspaces/src/includes/objects/usergroup.php
@@ -1,119 +1,119 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* UserGroup class
*
* @package ObsidianWorkspaces
* @subpackage Model
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* UserGroup class
*
* This class maps the users_groups table.
*/
class UserGroup {
public $id;
public $code;
public $title;
public $description;
/**
* Initializes a new instance
*
* @param int $id the primary key
*/
function __construct ($id = NULL) {
if ($id) {
$this->id = $id;
$this->load_from_database();
}
}
/**
* Loads the object UserGroup (ie fill the properties) from the $_POST array
*/
function load_from_form () {
if (array_key_exists('code', $_POST)) $this->code = $_POST['code'];
if (array_key_exists('title', $_POST)) $this->title = $_POST['title'];
if (array_key_exists('description', $_POST)) $this->description = $_POST['description'];
}
/**
* Loads the object UserGroup (ie fill the properties) from the SQL row
*/
function load_from_row ($row) {
$this->id = $row['group_id'];
$this->code = $row['group_code'];
$this->title = $row['group_title'];
$this->description = $row['group_description'];
}
/**
* Loads the object UserGroup (ie fill the properties) from the database
*/
function load_from_database () {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT * FROM " . TABLE_UGROUPS . " WHERE group_id = '" . $id . "'";
if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Unable to query users_groups", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
- $this->lastError = "UserGroup unkwown: " . $this->id;
+ $this->lastError = "UserGroup unknown: " . $this->id;
return false;
}
$this->load_from_row($row);
return true;
}
/**
* Loads the specified user group from code
*
* @param string $code The user group code
* @return UserGroup The specified user group instance
*/
public static function fromCode ($code) {
global $db;
$code = $db->sql_escape($code);
$sql = "SELECT * FROM " . TABLE_UGROUPS . " WHERE group_code = '" . $code . "'";
if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Unable to query group", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
- throw new Exception("Group unkwown: " . $code);
+ throw new Exception("Group unknown: " . $code);
}
$instance = new static();
$instance->load_from_row($row);
return $instance;
}
/**
* Saves to database
*/
function save_to_database () {
global $db;
$id = $this->id ? "'" . $db->sql_escape($this->id) . "'" : 'NULL';
$code = $db->sql_escape($this->code);
$title = $db->sql_escape($this->title);
$description = $db->sql_escape($this->description);
//Updates or inserts
$sql = "REPLACE INTO " . TABLE_UGROUPS . " (`group_id`, `group_code`, `group_title`, `group_description`) VALUES ('$id', '$code', '$title', '$description')";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save", '', __LINE__, __FILE__, $sql);
}
if (!$this->id) {
//Gets new record id value
$this->id = $db->sql_nextid();
}
}
}
diff --git a/workspaces/src/includes/session.php b/workspaces/src/includes/session.php
index 411a182..d2eafff 100755
--- a/workspaces/src/includes/session.php
+++ b/workspaces/src/includes/session.php
@@ -1,261 +1,261 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Session
*
* This class uses a singleton pattern, as we only need one single instance.
* Cf. http://www.php.net/manual/en/language.oop5.patterns.php
*
* @package ObsidianWorkspaces
* @subpackage Keruald
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
/**
* Session class
*/
class Session {
/**
* @var string session ID
*/
public $id;
/**
* @var string remote client IP
*/
public $ip;
/*
* @var Session current session instance
*/
private static $instance;
/*
* Gets or initializes current session instance
*
* @return Session current session instance
*/
public static function load () {
if (!isset(self::$instance)) {
//Creates new session instance
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/**
* Initializes a new instance of Session object
*/
private function __construct () {
//Starts PHP session, and gets id
session_start();
$_SESSION['ID'] = session_id();
$this->id = $_SESSION['ID'];
//Gets remote client IP
$this->ip = self::get_ip();
//Updates or creates the session in database
$this->update();
}
/**
* Gets remote client IP address
* @return string IP
*/
public static function get_ip () {
//mod_proxy + mod_rewrite (old pluton url scheme) will define 127.0.0.1
//in REMOTE_ADDR, and will store ip in HTTP_X_FORWARDED_FOR variable.
//Some ISP/orgz proxies also use this setting.
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
//Standard cases
return $_SERVER['REMOTE_ADDR'];
}
/**
* Cleans up session
* i. deletes expired session
* ii. sets offline relevant sessions
*/
public static function clean_old_sessions () {
global $db, $Config;
//Gets session and online status lifetime (in seconds)
//If not specified in config, sets default 5 and 120 minutes values
$onlineDuration = array_key_exists('OnlineDuration', $Config) ? $Config['OnlineDuration'] : 300;
$sessionDuration = array_key_exists('SessionDuration', $Config) ? $Config['SessionDuration'] : 7200;
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
//Deletes expired sessions
$sql = "DELETE FROM " . TABLE_SESSIONS . " WHERE session_resource = $resource AND TIMESTAMPDIFF(SECOND, session_updated, NOW()) > $sessionDuration";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Can't delete expired sessions", '', __LINE__, __FILE__, $sql);
//Online -> offline
$sql = "UPDATE " . TABLE_SESSIONS . " SET session_resource = $resource AND session_online = 0 WHERE TIMESTAMPDIFF(SECOND, session_updated, NOW()) > $onlineDuration";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Can\'t update sessions online statuses', '', __LINE__, __FILE__, $sql);
}
/**
* Updates or creates a session in the database
*/
public function update () {
global $db, $Config;
//Cleans up session
//To boost SQL performances, try a random trigger
// e.g. if (rand(1, 100) < 3) self::clean_old_sessions();
//or comment this line and execute a cron script you launch each minute.
self::clean_old_sessions();
//Saves session in database.
//If the session already exists, it updates the field online and updated.
$id = $db->sql_escape($this->id);
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
$user_id = $db->sql_escape(ANONYMOUS_USER);
$sql = "INSERT INTO " . TABLE_SESSIONS . " (session_id, session_ip, session_resource, user_id) VALUES ('$id', '$this->ip', $resource, '$user_id') ON DUPLICATE KEY UPDATE session_online = 1";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Can\'t save current session', '', __LINE__, __FILE__, $sql);
}
/**
* Gets the number of online users
*
* @return int the online users count
*/
public function count_online () {
//Keeps result for later method call
static $count = -1;
if ($count == -1) {
//Queries sessions table
global $db, $Config;
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
$sql = "SELECT count(*) FROM " . TABLE_SESSIONS . " WHERE session_resource = $resource AND session_online = 1";
$count = (int)$db->sql_query_express($sql, "Can't count online users");
}
//Returns number of users online
return $count;
}
/**
* Gets the value of a custom session table field
*
* @param string $info the field to get
* @return string the session specified field's value
*/
public function get_info ($info) {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT `$info` FROM " . TABLE_SESSIONS . " WHERE session_id = '$id'";
return $db->sql_query_express($sql, "Can't get session $info info");
}
/**
* Sets the value of a custom session table field to the specified value
*
* @param string $info the field to update
* @param string $value the value to set
*/
public function set_info ($info, $value) {
global $db;
$value = ($value === null) ? 'NULL' : "'" . $db->sql_escape($value) . "'";
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET `$info` = $value WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set session $info info", '', __LINE__, __FILE__, $sql);
}
/**
* Gets logged user information
*
* @return User the logged user information
*/
public function get_logged_user () {
global $db;
//Gets session information
$id = $db->sql_escape($this->id);
$sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id = '$id'";
if (!$result = $db->sql_query($sql))
message_die(SQL_ERROR, "Can't query session information", '', __LINE__, __FILE__, $sql);
$row = $db->sql_fetchrow($result);
//Gets user instance
require_once('includes/objects/user.php');
$user = new User($row['user_id']);
//Adds session property to this user instance
$user->session = $row;
//Returns user instance
return $user;
}
/**
* Cleans session
*
* This method is to be called when an event implies a session destroy
*/
public function clean () {
- //Destroies $_SESSION array values, help ID
+ //Destroys $_SESSION array values, help ID
foreach ($_SESSION as $key => $value) {
if ($key != 'ID') unset($_SESSION[$key]);
}
}
/**
- * Updates the session in an user login context
+ * Updates the session in a user login context
*
* @param string $user_id the user ID
*/
public function user_login ($user_id) {
global $db;
//Sets specified user ID in sessions table
$user_id = $db->sql_escape($user_id);
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set logged in status", '', __LINE__, __FILE__, $sql);
}
/**
- * Updates the session in an user logout context
+ * Updates the session in a user logout context
*/
public function user_logout () {
global $db;
//Sets anonymous user in sessions table
$user_id = $db->sql_escape(ANONYMOUS_USER);
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set logged out status", '', __LINE__, __FILE__, $sql);
//Cleans session
$this->clean();
}
}
//The user_id matching anonymous user (overridable in config file)
if (!defined('ANONYMOUS_USER')) {
define('ANONYMOUS_USER', -1);
}
diff --git a/workspaces/src/includes/workspaces/Workspace.php b/workspaces/src/includes/workspaces/Workspace.php
index f000a98..8e9fd69 100644
--- a/workspaces/src/includes/workspaces/Workspace.php
+++ b/workspaces/src/includes/workspaces/Workspace.php
@@ -1,222 +1,222 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Workspace class
*
* @package ObsidianWorkspaces
* @subpackage Workspaces
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* Workspace class
*
* This class maps the workspaces table.
*/
class Workspace {
public $id;
public $code;
public $name;
public $created;
public $description;
/**
* @var WorkspaceConfiguration The workspace configuration
*/
public $configuration;
/**
* Initializes a new instance
*
* @param int $id the primary key
*/
function __construct ($id = NULL) {
if ($id) {
$this->id = $id;
$this->load_from_database();
}
}
/**
* Loads the object Workspace (ie fill the properties) from the $_POST array
*/
function load_from_form () {
if (array_key_exists('code', $_POST)) $this->code = $_POST['code'];
if (array_key_exists('name', $_POST)) $this->name = $_POST['name'];
if (array_key_exists('created', $_POST)) $this->created = $_POST['created'];
if (array_key_exists('description', $_POST)) $this->description = $_POST['description'];
}
/**
* Loads the object zone (ie fill the properties) from the $row array
*/
function load_from_row ($row) {
$this->id = $row['workspace_id'];
$this->code = $row['workspace_code'];
$this->name = $row['workspace_name'];
$this->created = $row['workspace_created'];
$this->description = $row['workspace_description'];
}
/**
* Loads the specified workspace from code
*
* @param string $code The workspace code
* @return Workspace The specified workspace instance
*/
public static function fromCode ($code) {
global $db;
$code = $db->sql_escape($code);
$sql = "SELECT * FROM " . TABLE_WORKSPACES . " WHERE workspace_code = '" . $code . "'";
if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Unable to query workspaces", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
- throw new Exception("Workspace unkwown: " . $code);
+ throw new Exception("Workspace unknown: " . $code);
}
$workspace = new Workspace();
$workspace->load_from_row($row);
return $workspace;
}
/**
* Loads the object Workspace (ie fill the properties) from the database
*/
function load_from_database () {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT * FROM " . TABLE_WORKSPACES . " WHERE workspace_id = '" . $id . "'";
if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Unable to query workspaces", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
- $this->lastError = "Workspace unkwown: " . $this->id;
+ $this->lastError = "Workspace unknown: " . $this->id;
return false;
}
$this->load_from_row($row);
return true;
}
/**
* Saves to database
*/
function save_to_database () {
global $db;
$id = $this->id ? "'" . $db->sql_escape($this->id) . "'" : 'NULL';
$code = $db->sql_escape($this->code);
$name = $db->sql_escape($this->name);
$created = $db->sql_escape($this->created);
$description = $db->sql_escape($this->description);
//Updates or inserts
$sql = "REPLACE INTO " . TABLE_WORKSPACES . " (`workspace_id`, `workspace_code`, `workspace_name`, `workspace_created`, `workspace_description`) VALUES ('$id', '$code', '$name', '$created', '$description')";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save", '', __LINE__, __FILE__, $sql);
}
if (!$this->id) {
//Gets new record id value
$this->id = $db->sql_nextid();
}
}
/**
* Determines if the specified user has access to the current workspace
*
* @param User the user to check
* @return boolean true if the user has access to the current workspace ; otherwise, false.
*/
public function userCanAccess (User $user) {
if ($this->id === false || $this->id === null || $this->id === '') {
throw new LogicException("The workspace must has a valid id before to call userCanAccess.");
}
foreach ($user->get_workspaces() as $workspace) {
if ($workspace->id == $this->id) {
return true;
}
}
return false;
}
/**
* Loads configuration
*
* @param $context The site context
*/
public function loadConfiguration (Context $context) {
global $Config;
$file = $Config['Content']['Workspaces'] . '/' . $this->code . '/workspace.conf';
if (!file_exists($file)) {
$exceptionMessage = sprintf(Language::get('NotConfiguredWorkspace'), $file);
throw new Exception($exceptionMessage);
}
$this->configuration = WorkspaceConfiguration::loadFromFile($file, $context);
}
/**
* Gets workspaces specified user has access to.
*
* @param int $user_id The user to get his workspaces
* @return Array A list of workspaces
*/
public static function get_user_workspaces ($user_id) {
global $db;
//Gets the workspaces list from cache, as this complex request could take 100ms
//and is called on every page.
$cache = Cache::load();
if (!$workspaces = unserialize($cache->get("workspaces-$user_id"))) {
$clause = User::get_permissions_clause_from_user_id($user_id);
$sql = "SELECT DISTINCT w.*
FROM " . TABLE_PERMISSIONS . " p, " . TABLE_WORKSPACES . " w
WHERE p.target_resource_type = 'W' AND
p.target_resource_id = w.workspace_id AND
p.permission_name = 'accessLevel' AND
p.permission_flag > 0 AND
($clause)";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get user workspaces", '', __LINE__, __FILE__, $sql);
}
$workspaces = array();
while ($row = $db->sql_fetchrow($result)) {
$workspace = new Workspace();
$workspace->id = $row['workspace_id'];
$workspace->load_from_row($row);
$workspaces[] = $workspace;
}
$cache->set("workspaces-$user_id", serialize($workspaces));
}
return $workspaces;
}
/**
* Determines if a string matches an existing workspace code.
*
* @param string $code The workspace code to check
* @return boolean If the specified code matches an existing workspace, true; otherwise, false.
*/
public static function is_workspace ($code) {
global $db;
$code = $db->sql_escape($code);
$sql = "SELECT count(*) FROM " . TABLE_WORKSPACES . " WHERE workspace_code = '$code'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't check workspace code", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 1);
}
}
diff --git a/workspaces/src/includes/workspaces/WorkspaceConfiguration.php b/workspaces/src/includes/workspaces/WorkspaceConfiguration.php
index a48e136..6a75491 100644
--- a/workspaces/src/includes/workspaces/WorkspaceConfiguration.php
+++ b/workspaces/src/includes/workspaces/WorkspaceConfiguration.php
@@ -1,202 +1,202 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Workspace configuration class
*
* @package ObsidianWorkspaces
* @subpackage Workspaces
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*/
/**
* Workspace configuration class
*
* This class maps the workspaces table.
*/
class WorkspaceConfiguration implements ObjectDeserializableWithContext {
/**
* @var Array applications (each element is an instance of ApplicationConfiguration)
*/
public $applications = [];
/**
* @var Array authentication methods for this workspace (each element is an instance of AuthenticationMethod)
*/
public $authenticationMethods = [];
/**
* @var Array disclaimers (each element a string)
*/
public $disclaimers = [];
/**
* @var Array collections (each key a string to the collection name, each value a string to the collection document type)
*/
public $collections = [];
/**
* Determines if internal Obsidian Workspaces authentication can be used to login on this workspace URL
*
- * @return boolean True if an user not logged in Obsidian Workspaces going to a workspace URL should be offered to login through Obsidian ; otherwise, false.
+ * @return boolean True if a user not logged in Obsidian Workspaces going to a workspace URL should be offered to login through Obsidian ; otherwise, false.
*/
public $allowInternalAuthentication = true;
/**
* @var string The overall custom header to prepend to the header site
*/
public $header = '';
/**
* @var string The overall custom footer to append to the footer site
*/
public $footer = '';
/**
* Get applications controllers binds for this workspace
*/
public function getControllersBinds () {
$controllers = [];
foreach ($this->applications as $application) {
$controllers[$application->bind] = $application;
}
return $controllers;
}
/**
- * Determines if the URL fragment matches a controller binded to it.
+ * Determines if the URL fragment matches a controller bound to it.
*
* @param ApplicationConfiguration $applicationConfiguration The application configuration
* @return boolean true if the URL fragment matches an application controller's bind
*/
public function hasControllerBind ($url, &$applicationConfiguration) {
foreach ($this->applications as $application) {
if ($application->bind == $url) {
$applicationConfiguration = $application;
return true;
}
}
return false;
}
/**
* Loads a WorkspaceConfiguration instance from an object
*
* @param object $data The object to deserialize
* @param Context The site context
* @return WorkspaceConfiguration The deserialized instance
*/
public static function loadFromObject ($data, $context) {
$instance = new WorkspaceConfiguration();
//Applications array
if (property_exists($data, 'applications')) {
foreach ($data->applications as $applicationData) {
if (!property_exists($applicationData, 'name')) {
throw new Exception("Missing required property: application name");
}
$controllerClass = $applicationData->name;
if (!class_exists($controllerClass)) {
trigger_error("Application controller doesn't exist: $controllerClass. If you've just added application code, update includes/autoload.php file to register your new classes.", E_USER_WARNING);
continue;
}
$configurationClass = $controllerClass . 'Configuration';
if (!class_exists($configurationClass)) {
$configurationClass = "ApplicationConfiguration";
}
$instance->applications[] = $configurationClass::loadFromObject($applicationData);
}
}
//Login array
if (property_exists($data, 'login')) {
$instance->allowInternalAuthentication = false;
foreach ($data->login as $authData) {
if (!property_exists($authData, 'type')) {
throw new Exception("Missing required property: login type");
}
if ($authData->type == 'internal') {
$instance->allowInternalAuthentication = true;
continue;
}
$class = $authData->type;
if (!class_exists($class)) {
throw new Exception("Authentication method doesn't exist: $class. If you've just added authentication code, update includes/autoload.php file to register your new classes.");
}
$authenticationMethod = $class::loadFromObject($authData);
$authenticationMethod->context = $context;
$instance->authenticationMethods[] = $authenticationMethod;
}
}
//Disclaimers array
if (property_exists($data, 'disclaimers')) {
$instance->disclaimers = $data->disclaimers;
}
//Collections array
if (property_exists($data, 'collections')) {
foreach ($data->collections as $collection) {
if (!property_exists($collection, 'name')) {
throw new Exception("A collection has been declared without name in the workspace configuration.");
}
$name = $collection->name;
if (!property_exists($collection, 'global') || !$collection->global) {
$name = WorkspaceConfiguration::getCollectionNameWithPrefix($context->workspace, $name);
}
if (property_exists($collection, 'documentType')) {
$type = $collection->documentType;
if (!class_exists($type)) {
throw new Exception("CollectionDocument children class doesn't exist: $type. If you've just added authentication code, update includes/autoload.php file to register your new classes.");
}
} else {
$type = null;
}
$instance->collections[$name] = $type;
}
}
//Header string
if (property_exists($data, 'header')) {
$instance->header = $data->header;
}
//Footer string
if (property_exists($data, 'footer')) {
$instance->footer = $data->footer;
}
return $instance;
}
/**
* Gets the full name of a collection, with the workspace prefix
*
* @param $workspace The current workspace
* @param $workspace The collection name
* @return string The full name of the collection
*/
public static function getCollectionNameWithPrefix (Workspace $workspace, $name) {
return $workspace->code . '-' . $name;
}
/**
* Loads a WorkspaceConfiguration instance deserializing a JSON file
*/
public static function loadFromFile ($file, $context) {
$object = json_decode(file_get_contents($file));
if ($object === null) {
throw new Exception("Can't parse configuration file: " . json_last_error_msg());
}
return self::loadFromObject($object, $context);
}
}
diff --git a/workspaces/src/index.php b/workspaces/src/index.php
index 1578a7e..8b4de53 100755
--- a/workspaces/src/index.php
+++ b/workspaces/src/index.php
@@ -1,105 +1,105 @@
<?php
/**
* _, __, _, _ __, _ _, _, _
* / \ |_) (_ | | \ | /_\ |\ |
* \ / |_) , ) | |_/ | | | | \|
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* Main web application entry point
*
* @package ObsidianWorkspaces
* @subpackage Controllers
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @filesource
*
*/
use Keruald\Database\Database;
////////////////////////////////////////////////////////////////////////////////
///
/// Initialization
///
//Keruald and Obsidian Workspaces libraries
include('includes/core.php');
//Prepares the site context
$context = new Context();
$context->config = $Config;
$context->db = $db = Database::load($Config["sql"]);
$context->session = Session::load();
$context->url = get_current_url_fragments();
$context->initializeTemplateEngine($context->config['Theme']);
//Loads language files
Language::initialize();
Language::load($context)->configLoad('core.conf');
//Loads workspace
try {
if (Workspace::is_workspace($context->url[0])) {
$context->workspace = Workspace::fromCode(array_shift($context->url));
$context->workspace->loadConfiguration($context);
}
} catch (Exception $ex) {
message_die(GENERAL_ERROR, $ex->getMessage(), Language::get('CantLoadWorkspace'));
}
//Handles login or logout
include("includes/login.php");
//Gets current user information
$context->user = $context->session->get_logged_user();
////////////////////////////////////////////////////////////////////////////////
///
/// Serves the requested page
///
//If the user isn't logged in (is anonymous), prints login/invite page & dies.
if ($context->user->id == ANONYMOUS_USER) {
//Anonymous user
include('controllers/anonymous.php');
exit;
}
//If a workspace has been selected, ensures the current logged in user has access to it.
if ($context->workspace && !$context->workspace->userCanAccess($context->user)) {
message_die(HACK_ERROR, "You don't have access to this workspace.", 'Access control');
}
$controller = count($context->url) > 0 ? $context->url[0] : '';
switch ($controller) {
case '':
//Calls homepage controller
HomepageController::run($context);
break;
case 'help':
case 'reports':
//Calls requested controller
include("controllers/$controller.php");
break;
default:
//Current workspace application controller?
if ($context->workspace != null) {
$workspaceConfig = $context->workspace->configuration;
$applicationConfiguration = null;
if ($workspaceConfig != null && $workspaceConfig->hasControllerBind($controller, $applicationConfiguration)) {
//Runs controller
$controllerClass = $applicationConfiguration->name;
$appContext = ApplicationContext::loadFromContext($context, $applicationConfiguration);
$controllerClass::run($appContext);
break;
}
}
- //Not a workspace, nor a controller toponomy
+ //Not a workspace, nor a controller toponym
ErrorPageController::show($context, 404);
exit;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Nov 6, 11:14 (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3136695
Default Alt Text
(103 KB)

Event Timeline