<?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;
}
}
/*
* 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);
}
}
?>