//******************************************************************************************************************************************* // // Application specific permissions // //******************************************************************************************************************************************* class SitePerms extends Perm { const ManageOwnAccount = 64; const Roles = 128; const RoleAdd = 256; const RoleEdit = 512; const RoleDelete = 1024; const Users = 2048; const UserAdd = 4096; const UserEdit = 8192; const UserDelete = 16384; const Groups = 32768; const GroupAdd = 65536; const GroupEdit = 131072; const GroupEditAny = 262144; const GroupDelete = 524288; const GroupDeleteAny = 1048576; const Fields = 2097152; const FieldAdd = 4194304; const FieldEdit = 8388608; const FieldEditAny = 16777216; const FieldDelete = 33554432; const FieldDeleteAny = 67108864; const Entries = 134217728; const EntryAdd = 268435456; const EntryEdit = 536870912; const EntryEditAny = 1073741824; const EntryDelete = 2147483648; const EntryDeleteAny = 4294967296; } //******************************************************************************************************************************************* // // Flags for various use around the site // //******************************************************************************************************************************************* class SiteFlags { const TextFormat_Single = 1; const TextFormat_Textarea = 2; const TextFormat_RichText = 4; const TextFormat_ProtectedSingle = 8; } //******************************************************************************************************************************************* // // Holds site configuration // //******************************************************************************************************************************************* class SiteConfig { public $cfgid = 0; public $rights_anon = 0; public $rights_auth = 0; public $pacl_group = ""; public $pacl_entry = ""; function __construct() { global $pdo; $data = getData($pdo, "config"); $this->cfgid = array_key_first($data); foreach ($data[$this->cfgid] AS $f=>$v) $this->$f = $v; } function flush() { global $pdo; $sqldata = []; foreach (["cfgid","rights_anon","rights_auth","pacl_group","pacl_entry"] AS $f) $sqldata[$f] = $this->$f; setData($pdo, "config", $sqldata); } } //******************************************************************************************************************************************* // // Fields used in the entries // //******************************************************************************************************************************************* class Field { public $id = 0; public $name = ""; public $dispname = ""; public $placeholder = ""; public $flags = 0; public $rows = 0; public $width = 0; public $columns = 0; public $datecreated = 0; public $style = ""; public $class = ""; public $createdby = 0; public $content = ""; public $disporder = 0; public $nameoverride = ""; function __construct($fid = "", $id = "") { if (empty($fid)) return; if (is_array($fid)) { $this->populate(["data"=>$fid]); return; } $this->id = $fid; $this->populate(["fid"=>$fid, "id"=>$id]); } function getDateCreated() { return date("m/d/Y @ g:i A", $this->datecreated); } function populate($opts = []) { global $pdo; if (array_key_exists("data", $opts) && count($opts["data"]) > 0) { foreach (["fid","fname","dispname","flags","datecreated","createdby","rows","columns","style","class","width","placeholder"] AS $f) { if (array_key_exists($f, $opts["data"])) continue; errorMsg("Attempted to load field object but data fields are missing! ($f)", false); return; } $this->id = $opts["data"]["fid"]; $this->name = $opts["data"]["fname"]; foreach (["dispname","style","class","placeholder"] AS $f) empty($opts["data"][$f]) ? "" : $opts["data"][$f]; foreach (["flags","rows","columns","width","createdby"] AS $f) $this->$f = getInt($opts["data"][$f]); $this->datecreated = is_numeric($opts["data"]["datecreated"]) ? $opts["data"]["datecreated"] : strtotime($opts["data"]["datecreated"]); if (array_key_exists("id", $opts["data"])) $this->populateData($opts["data"]["id"]); return; } $data = getData($pdo, "fieldspec", ["criteria"=>["fid = ?"=>$this->id], "onlyone"=>true]); if (count($data) == 0) return; $this->name = $data["fname"]; foreach (["dispname","style","class","placeholder"] AS $f) $this->$f = empty($data[$f]) ? "" : $data[$f]; foreach (["flags","rows","columns","width","createdby"] AS $f) $this->$f = getInt($data[$f]); $this->datecreated = strtotime($data["datecreated"]); if (array_key_exists("id", $opts) && !empty($opts["id"])) $this->populateData($opts["id"]); } function populateData($id) { global $pdo; if (empty($id)) return; $data = getData($pdo, "entries_fields", ["criteria"=>["id = ?"=>$id, "fid = ?"=>$this->id], "onlyone"=>true]); if (count($data) == 0) return; $this->content = $data["datavalue"]; } function flush() { global $pdo; $sqldata = [ "fname"=>$this->name, "dispname"=>$this->dispname, "placeholder"=>$this->placeholder, "flags"=>$this->flags, "datecreated"=>sqlDate(), "createdby"=>$_SESSION["user"]->uid, "rows"=>sqlIntSafe($this->rows), "columns"=>sqlIntSafe($this->columns), "width"=>sqlIntSafe($this->width), "style"=>$this->style, "class"=>$this->class ]; if (empty($this->id)) { $tmp = getData($pdo, "fieldspec", ["criteria"=>["fname = ?"=>$this->name]]); if (count($tmp) > 0) { errorMsg("Could not save! That field name already exists!", false); return; } $this->id = setData($pdo, "fieldspec", $sqldata); return; } $sqldata["fid"] = $this->id; setData($pdo, "fieldspec", $sqldata); } function getInputType() { if ($this->flags & SiteFlags::TextFormat_Single) return "single"; if ($this->flags & SiteFlags::TextFormat_ProtectedSingle) return "psingle"; if ($this->flags & SiteFlags::TextFormat_Textarea) return "textarea"; if ($this->flags & SiteFlags::TextFormat_RichText) return "richtext"; return ""; } function getInputField() { $ret = ""; $fieldid = empty($this->name) ? mt_rand(1000, 100000) : str_replace(" ", "", $this->name); $name = "name=\"$fieldid\" id=\"$fieldid\" "; $style = empty($this->style) ? "" : "style=\"{$this->style}\" "; $width = empty($this->width) ? "" : "size=\"{$this->width}\" "; $class = empty($this->class) ? "" : "class=\"{$this->class}\" "; if ($this->flags & SiteFlags::TextFormat_Single) return ["id"=>$fieldid, "html"=>"value}\">"]; if ($this->flags & SiteFlags::TextFormat_ProtectedSingle) return ["id"=>$fieldid, "html"=>"value}\">"]; if ($this->flags & SiteFlags::TextFormat_Textarea) return ["id"=>$fieldid, "html"=>""]; if ($this->flags & SiteFlags::TextFormat_RichText) { } } function getName() { return empty($this->nameoverride) ? $this->name : $this->nameoverride; } } //******************************************************************************************************************************************* // // Fields used in entry groups // //******************************************************************************************************************************************* class EntryGroupField extends Field { public $gfid = 0; public $nameoverride = ""; public $disporder = 0; function __construct($val = null, $nameoverride = "", $disporder = 0) { if ($val == null) return; if ($val instanceof Field) { $this->id = $val->id; $this->name = $val->name; $this->flags = $val->flags; $this->datecreated = $val->datecreated; $this->createdby = $val->createdby; $this->nameoverride = $nameoverride; $this->disporder = $disporder; } if (is_array($val)) { if (!array_key_exists("fid", $val)) return; $this->id = $val["fid"]; if (array_key_exists("fname", $val)) $this->name = $val["fname"]; foreach (["dispname","flags","datecreated","createdby","nameoverride","disporder"] AS $f) { if (!array_key_exists($f, $val)) continue; $this->$f = $val[$f]; } } } } //******************************************************************************************************************************************* // // Entry groups // //******************************************************************************************************************************************* class Group { public $id = 0; public $name = ""; public $flags = 0; public $datecreated = 0; public $createdby = 0; public $disporder = 0; public $acl = null; public $entries = []; public $fields = []; function __construct($id = "") { $acl = new ACL(); if (empty($id)) return; if (is_array($id)) { $this->populate($id); } else if (is_numeric($id)) { $this->id = $id; } else { $this->name = $id; } $this->populate(); } function loadEntries($user = null) { global $pdo; $sql = $pdo->prepare("SELECT * FROM "); } function getDateCreated() { return date("m/d/Y @ g:i A", $this->datecreated); } function getCreatedBy() { $system = new User(); $system->uid = 0; $system->username = "System Account"; if ($this->createdby == 0) return $system; $tmp = getUserObject(["uid"=>$this->createdby]); return $tmp == null ? $system : $tmp; } function populate($row = []) { global $pdo; if (count($row) == 0) { if (!empty($this->id)) { $sql = $pdo->prepare("SELECT * FROM entrygroups WHERE gid = ?"); $sql->execute([$this->id]); $row = $sql->fetch(PDO::FETCH_ASSOC); } else if (!empty($this->name)) { $sql = $pdo->prepare("SELECT * FROM entrygroups WHERE gname = ?"); $sql->execute([$this->name]); $row = $sql->fetch(PDO::FETCH_ASSOC); } else { return; } } else { foreach (["gid","gname","flags","createdby","disporder","datecreated","acl"] AS $f) { if (!array_key_exists($f, $row)) errorMsg("Cannot populate group; array is missing field(s)! ($f)"); } } if (!$row) return; $this->id = $row["gid"]; $this->name = $row["gname"]; $this->flags = $row["flags"]; $this->createdby = $row["createdby"]; $this->disporder = $row["disporder"]; $this->datecreated = strtotime($row["datecreated"]); $this->acl = empty($row["acl"]) ? new ACL() : unserialize($row["acl"]); $sql = $pdo->prepare("SELECT * FROM entrygroups_fields ef LEFT OUTER JOIN fieldspec f ON ef.fid = f.fid WHERE gid = ? ORDER BY disporder"); $sql->execute([$this->id]); $rows = $sql->fetchAll(); foreach ($rows AS $row) { $field = new EntryGroupField($row); $this->fields[$row["gfid"]] = $field; } } function flush() { global $pdo; if (empty($this->id)) { if (empty($this->name)) return; $tmp = new Group($this->name); if (!empty($tmp->id)) { showError("Could not save group; one already exists with the name {$this->name}!", false); return; } $sql = $pdo->prepare("INSERT INTO entrygroups (gname, flags, datecreated, createdby, acl, disporder) VALUES (?, ?, NOW(), ?, ?, ?)"); $sql->execute([$this->name, $this->flags, $_SESSION["user"]->uid, sqlObject($this->acl), $this->disporder]); $this->id = lastID($pdo, "entrygroups"); $this->dumpFields(); return; } $sql = $pdo->prepare("UPDATE entrygroups SET gname = ?, flags = ?, acl = ?, disporder = ? WHERE gid = ?"); $sql->execute([$this->name, $this->flags, sqlObject($this->acl), $this->disporder, $this->id]); $this->dumpFields(); } function dumpFields() { global $pdo; $sql = $pdo->prepare("DELETE FROM entrygroups_fields WHERE gid = ?"); $sql->execute([$this->id]); foreach ($this->fields AS $field) { $sql = $pdo->prepare("INSERT INTO entrygroups_fields (gid, fid, disporder, nameoverride) VALUES (?, ?, ?, ?)"); $sql->execute([$this->id, $field->id, $field->disporder, $field->nameoverride]); } } function delete() { global $pdo; $sql = $pdo->prepare("SELECT COUNT(*) AS tot FROM entries WHERE gid = ?"); $sql->execute([$this->id]); $row = $sql->fetch(PDO::FETCH_ASSOC); if (!empty($row["tot"])) return false; $sql = $pdo->prepare("DELETE FROM entrygroups WHERE gid = ?"); $sql->execute([$this->id]); $sql = $pdo->prepare("DELETE FROM entrygroups_fields WHERE gid = ?"); $sql->execute([$this->id]); return true; } function hasPermission($user = null, $perm = SitePerms::Entries) { if ($user == null) $user = getLoggedInUser(); if (empty($this->acl)) return isLoggedIn() ? $this->createdby == getLoggedInUser()->id : false; return $this->acl->hasPermission($user, SitePerms::Entries); } } //******************************************************************************************************************************************* // // Entries // //******************************************************************************************************************************************* class Entry { public $id = 0; public $gid = 0; public $name = ""; public $flags = 0; public $content = ""; public $datecreated = 0; public $createdby = 0; public $acl = null; public $group = null; public $fields = []; function __construct($id = null, $gid = 0) { $this->id = $id; $this->gid = $gid; $this->acl = new ACL(); $this->group = new Group(); $this->populate(); } function populate() { global $pdo; if (empty($this->id)) { if (empty($this->gid)) return; $this->group = new Group($this->gid); $sql = $pdo->prepare("SELECT * FROM entrygroups_fields WHERE gid = ?"); $sql->execute([$this->gid]); $rows = $sql->fetchAll(); foreach ($rows AS $row) { $field = new Field($row["fid"]); $field->disporder = $row["disporder"]; $field->nameoverride = $row["nameoverride"]; $this->fields[] = $field; } $this->datecreated = time(); $this->createdby = $_SESSION["user"]->uid; return; } $sqlstr = "SELECT e.id,gid,ename,e.flags AS flags,datecreated,createdby,acl,fid,datavalue, "; $sqlstr .= "(SELECT nameoverride FROM entrygroups_fields egf WHERE egf.fid = ef.fid AND egf.gid = e.gid) AS nameoverride, "; $sqlstr .= "(SELECT disporder FROM entrygroups_fields egf WHERE egf.fid = ef.fid AND egf.gid = e.gid) AS disporder "; $sqlstr .= "FROM entries e "; $sqlstr .= "INNER JOIN entries_fields ef ON ef.id = e.id "; $sqlstr .= "WHERE e.id = ?"; $sql = $pdo->prepare($sqlstr); $sql->execute([$this->id]); $rows = $sql->fetchAll(); foreach ($rows AS $row) { if (empty($this->name)) { $this->name = $row["ename"]; $this->datecreated = strtotime($row["datecreated"]); $this->createdby = $row["createdby"]; $this->acl = empty($row["acl"]) ? new ACL() : unserialize($row["acl"]); $this->group = new Group($row["gid"]); } $field = new Field($row["fid"], $this->id); $field->disporder = $row["disporder"]; $field->nameoverride = $row["nameoverride"]; $field->value = $row["datavalue"]; $this->fields[] = $field; } } function flush() { global $pdo; if (empty($this->name)) return; if (empty($this->id)) { $this->id = setData($pdo, "entries", ["gid"=>$this->gid, "ename"=>$this->name, "flags"=>$this->flags, "datecreated"=>sqlDate($this->datecreated), "createdby"=>$this->createdby, "acl"=>$this->acl == null ? null : serialize($this->acl)]); foreach ($this->fields AS $f) { setData($pdo, "entries_fields", ["id"=>$this->id, "fid"=>$f->id, "datavalue"=>$f->content, "flags"=>$f->flags]); } return; } setData($pdo, "entries", ["id"=>$this->id, "gid"=>$this->gid, "ename"=>$this->name, "flags"=>$this->flags, "datecreated"=>sqlDate($this->datecreated), "createdby"=>$this->createdby, "acl"=>$this->acl == null ? null : serialize($this->acl)]); foreach ($this->fields AS $f) { $sql = $pdo->prepare("UPDATE entries_fields SET datavalue = ?, flags = ? WHERE id = ? AND fid = ?"); $sql->execute([$f->content, $f->flags, $this->id, $this->gid]); } } function getPanel($opts = []) { $ret = ""; if (array_key_exists("del", $opts)) $ret .= " " . grabInput("del_{$this->id}", 1, "checkbox") . ""; if (array_key_exists("showgroup", $opts)) { $name = array_key_exists("group", $opts) ? $opts["group"] : ($this->group == null ? "" : $this->group->name); $ret .= " $name"; } $ret .= " "; $ret .= "<" . (array_key_exists("clicktag", $opts) ? $opts["clicktag"] : "a") . " id='r_{$this->id}'>"; $ret .= array_key_exists("maxlen", $opts) ? limitedDisplay($this->name, $opts["maxlen"], array_key_exists("maxlen.str", $opts) ? $opts["maxlen.str"] : "") : $this->name; $ret .= ""; $ret .= ""; return $ret; } function hasPermission($user = null, $perm = SitePerms::Entries) { debug($this); debug($this->acl); if ($user == null) $user = getLoggedInUser(); if ($this->group != null) { if (!$this->group->hasPermission($user)) return false; if (empty($this->acl)) return isLoggedIn() ? $this->createdby == getLoggedInUser()->id : false; return $this->acl->hasPermission($user, SitePerms::Entries); } if (empty($this->acl)) return isLoggedIn() ? $this->createdby == getLoggedInUser()->id : false; return $this->acl->hasPermission($user, SitePerms::Entries); } } //******************************************************************************************************************************************* // // Entry search interface // //******************************************************************************************************************************************* class Search { public $keyword = ""; public $gid = 0; public $page = 0; public $maxpages = 0; public $pagesize = 5; public $results = []; public $hasSearched = false; function __construct($opts = []) { global $cfg; $this->pagesize = array_key_exists("pagesize", $opts) ? $opts["pagesize"] : (array_key_exists("pagesize", $cfg) ? $cfg["pagesize"] : 5); foreach (["keyword","gid","page"] AS $f) { if (!array_key_exists($f, $_REQUEST)) continue; $this->$f = $_REQUEST[$f]; } $this->hasSearched = !empty($_REQUEST["gid"]) || !empty($_REQUEST["keyword"]); $this->performSearch(); } function getInterface($opts = []) { $ret = ""; $tmp = []; $jq = array_key_exists("jquery", $opts) ? $opts["jquery"] : "$"; if (!array_key_exists("buttons", $opts) || array_key_exists("*", $opts["buttons"])) { $tmp["btn_submit"] = ["disp"=>"Submit", "code"=>"document.data.submit();"]; $tmp["btn_reset"] = ["disp"=>"Reset", "code"=>"document.data.gid.value = '';document.data.keyword.value = '';document.data.submit();"]; } if (array_key_exists("buttons", $opts) && array_key_exists("*", $opts["buttons"])) { unset($opts["buttons"]["*"]); $tmp = array_merge($tmp, $opts["buttons"]); } $opts["buttons"] = $tmp; $opts["jquery"] = array_key_exists("jquery", $opts) ? $opts["jquery"] : "$"; $groups = getGroups(); if (count($groups) > 0) { $ret .= "

" . PHP_EOL; } $ret .= "

" . grabInput("keyword", 15, "text", $this->keyword) . "

" . PHP_EOL; foreach ($opts["buttons"] AS $id=>$data) { $ret .= "" . PHP_EOL; $ret .= "" . PHP_EOL; } if (array_key_exists("hr", $opts)) $ret .= "
" . PHP_EOL; if (!array_key_exists("nofocus", $opts)) { $focus = array_key_exists("focus", $opts) ? $opts["focus"] : "keyword"; $ret .= "" . PHP_EOL; } if (array_key_exists("groupchange", $opts)) { $ret .= ""; } return $ret; } function performSearch() { global $pdo; $sqldata = []; $start = $this->page * $this->pagesize; $sqlstr = ""; if (!empty($this->keyword)) { $sqlstr .= (empty($sqlstr) ? "" : " AND "); $sqlstr .= "(ename LIKE ?)"; $sqldata[] = "%{$this->keyword}%"; } if (!empty($this->gid)) { $sqlstr .= (empty($sqlstr) ? "" : " AND "); $sqlstr .= "(gid = ?)"; $sqldata[] = $this->gid; } $this->results = []; $sql = $pdo->prepare("SELECT id,(SELECT COUNT(id) FROM entries" . (empty($sqlstr)?"":" WHERE ($sqlstr)") . ") AS tot FROM entries" . (empty($sqlstr)?"":" WHERE ($sqlstr)") . " ORDER BY ename LIMIT $start,{$this->pagesize}"); $sql->execute(array_merge($sqldata, $sqldata)); $rows = $sql->fetchAll(); if (count($rows) == 0) return; $this->maxpages = ceil($rows[0]["tot"] / $this->pagesize); foreach ($rows AS $row) { $entry = new Entry($row["id"]); if (empty($entry->id)) continue; if (!$entry->hasPermission(getLoggedInUser())) continue; $this->results[] = $entry; } } function getPagination($opts = []) { if (count($this->results) == 0) return; foreach (["allow.first", "allow.prev", "allow.next", "allow.last", "allow.jump", "show.buttons"] AS $f) { $opts[$f] = array_key_exists($f, $opts) ? $opts[$f] : true; } $opts["jquery"] = array_key_exists("jquery", $opts) ? $opts["jquery"] : "$"; $ret = "
" . PHP_EOL; if ($opts["allow.first"]) $ret .= " " . PHP_EOL; if ($opts["allow.prev"]) $ret .= " " . PHP_EOL; if ($opts["allow.jump"]) { $ret .= " " . PHP_EOL; $ret .= " " . PHP_EOL; } else { Hidden("page", $this->page); } if ($opts["allow.next"]) $ret .= " " . PHP_EOL; if ($opts["allow.last"]) $ret .= " " . PHP_EOL; $ret .= "
" . PHP_EOL; if (!$opts["show.buttons"]) return $ret; $ret .= "" . PHP_EOL; return $ret; } function getResults($opts) { if (count($this->results) == 0) return; $ret = ""; foreach ($this->results AS $result) { $ret .= $result->getPanel($opts) . PHP_EOL;; } return $ret; } }