Subversion Repositories oidplus

Rev

Rev 112 | Rev 150 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('IN_OIDPLUS')) die();
  21.  
  22. abstract class OIDplusObject {
  23.         public static function parse($node_id) { // please overwrite this function!
  24.                 // TODO: in case we are not calling this class directly, check if function is overwritten and throw exception otherwise
  25.                 foreach (OIDplus::getRegisteredObjectTypes() as $ot) {
  26.                         if ($obj = $ot::parse($node_id)) return $obj;
  27.                 }
  28.                 return null;
  29.         }
  30.  
  31.         public function getOid() {
  32.                 if ($this->ns() == 'oid') {
  33.                         return $this->getDotNotation();
  34.                 } else {
  35.                         $sid = OIDplus::system_id(true);
  36.                         if (empty($sid)) return false;
  37.                         return $sid . '.' . smallhash($this->nodeId());
  38.                 }
  39.         }
  40.  
  41.         public abstract static function objectTypeTitle();
  42.  
  43.         public abstract static function objectTypeTitleShort();
  44.  
  45.         public abstract static function ns();
  46.  
  47.         public abstract static function root();
  48.  
  49.         public abstract function isRoot();
  50.  
  51.         public abstract function nodeId();
  52.  
  53.         public abstract function addString($str);
  54.  
  55.         public abstract function crudShowId(OIDplusObject $parent);
  56.  
  57.         public abstract function crudInsertPrefix();
  58.  
  59.         public abstract function jsTreeNodeName(OIDplusObject $parent = null);
  60.  
  61.         public abstract function defaultTitle();
  62.  
  63.         public abstract function isLeafNode();
  64.  
  65.         public abstract function getContentPage(&$title, &$content, &$icon);
  66.  
  67.         public static function getRaRoots($ra_email=null) {
  68.                 if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
  69.  
  70.                 $out = array();
  71.                 if (is_null($ra_email)) {
  72.                         $res = OIDplus::db()->query("select oChild.id as id, oChild.ra_email as child_mail, oParent.ra_email as parent_mail from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
  73.                                                     "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
  74.                                                     "order by ".OIDplus::db()->natOrder('oChild.id'));
  75.                         while ($row = OIDplus::db()->fetch_array($res)) {
  76.                                 if (!OIDplus::authUtils()::isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()::isRaLoggedIn($row['child_mail'])) {
  77.                                         $x = self::parse($row['id']); // can be FALSE if namespace was disabled
  78.                                         if ($x) $out[] = $x;
  79.                                 }
  80.                         }
  81.                 } else {
  82.                         $res = OIDplus::db()->query("select oChild.id as id from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
  83.                                                     "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
  84.                                                     "where (ifnull(oParent.ra_email,'') <> '".OIDplus::db()->real_escape_string($ra_email)."' and ifnull(oChild.ra_email,'') = '".OIDplus::db()->real_escape_string($ra_email)."') or ".
  85.                                                     "      (oParent.ra_email is null and ifnull(oChild.ra_email,'') = '".OIDplus::db()->real_escape_string($ra_email)."') ".
  86.                                                     "order by ".OIDplus::db()->natOrder('oChild.id'));
  87.                         while ($row = OIDplus::db()->fetch_array($res)) {
  88.                                 $x = self::parse($row['id']); // can be FALSE if namespace was disabled
  89.                                 if ($x) $out[] = self::parse($row['id']);
  90.                         }
  91.                 }
  92.                 return $out;
  93.         }
  94.  
  95.         private static function getAllNonConfidential_rec($parent=null, &$out) {
  96.                 if (is_null($parent)) {
  97.                         $roots = array();
  98.                         foreach (OIDplus::getRegisteredObjectTypes() as $ot) {
  99.                                 $roots[] = "parent = '" . OIDplus::db()->real_escape_string($ot::root()) . "'";
  100.                         }
  101.                         $roots = implode(' or ', $roots);
  102.                 } else {
  103.                         $roots = "parent = '" . OIDplus::db()->real_escape_string($parent) . "'";
  104.                 }
  105.  
  106.                 $res = OIDplus::db()->query("select id, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where $roots order by ".OIDplus::db()->natOrder('id'));
  107.  
  108.                 while ($row = OIDplus::db()->fetch_array($res)) {
  109.                         if ($row['confidential'] == '1') {
  110.                                 // do nothing
  111.                         } else {
  112.                                 $out[] = $row['id'];
  113.                                 self::getAllNonConfidential_rec($row['id'], $out);
  114.                         }
  115.                 }
  116.         }
  117.  
  118.         public static function getAllNonConfidential() {
  119.                 $out = array();
  120.                 self::getAllNonConfidential_rec(null, $out);
  121.                 return $out;
  122.         }
  123.  
  124.         public function isConfidential() {
  125.                 $curid = $this->nodeId();
  126.                 // Recursively search for the confidential flag in the parents
  127.                 while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
  128.                         $row = OIDplus::db()->fetch_array($res);
  129.                         if ($row['confidential']) return true;
  130.                         $curid = $row['parent'];
  131.                 }
  132.  
  133.                 return false;
  134.         }
  135.  
  136.         public function isChildOf(OIDplusObject $obj) {
  137.                 $curid = $this->nodeId();
  138.                 while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
  139.                         $row = OIDplus::db()->fetch_array($res);
  140.                         if ($curid == $obj->nodeId()) return true;
  141.                         $curid = $row['parent'];
  142.                 }
  143.  
  144.                 return false;
  145.         }
  146.  
  147.         public function getRa() {
  148.                 $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  149.                 $row = OIDplus::db()->fetch_array($res);
  150.                 return new OIDplusRA($row['ra_email']);
  151.         }
  152.  
  153.         public function userHasReadRights($ra_email=null) {
  154.                 if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
  155.  
  156.                 // Admin may do everything
  157.                 if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  158.  
  159.                 // If it is not confidential, everybody can read/see it.
  160.                 if (!$this->isConfidential()) return true;
  161.  
  162.                 // If we own the object, we may see it
  163.                 if (is_null($ra_email)) {
  164.                         if ($this->userHasWriteRights()) return true;
  165.                 } else {
  166.                         $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  167.                         $row = OIDplus::db()->fetch_array($res);
  168.                         if ($row['ra_email'] == $ra_email) return true;
  169.                 }
  170.  
  171.                 // If someone has rights to an object below our confidential node,
  172.                 // we let him see the confidential node,
  173.                 // Otherwise he could not browse through to his own node.
  174.                 $roots = $this->getRaRoots($ra_email);
  175.                 foreach ($roots as $root) {
  176.                         if ($root->isChildOf($this)) return true;
  177.                 }
  178.  
  179.                 return false;
  180.         }
  181.  
  182.         public function getIcon($row=null) {
  183.                 $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
  184.  
  185.                 if (is_null($row)) {
  186.                         $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  187.                         $row = OIDplus::db()->fetch_array($res);
  188.                 }
  189.                 // TODO: have different icons for Leaf-Nodes
  190.                 if (OIDplus::authUtils()::isRaLoggedIn($row['ra_email'])) {
  191.                         $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_own.png';
  192.                 } else {
  193.                         $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_general.png';
  194.                 }
  195.                 if (!file_exists($icon)) $icon = null; // default icon (folder)
  196.                 return $icon;
  197.         }
  198.  
  199.         public static function exists($id) {
  200.                 $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($id)."'");
  201.                 return OIDplus::db()->num_rows($res) > 0;
  202.         }
  203.  
  204.         public function getParent() {
  205.                 $res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  206.                 $row = OIDplus::db()->fetch_array($res);
  207.                 $parent = $row['parent'];
  208.                 $obj = OIDplusObject::parse($parent);
  209.                 if ($obj) return $obj;
  210.  
  211.                 // If this OID does not exist, the SQL query "select parent from ..." does not work. So we try to find the next possible parent using one_up()
  212.                 $cur = $this->one_up();
  213.                 if (!$cur) return false;
  214.                 do {
  215.                         if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
  216.  
  217.                         $prev = $cur;
  218.                         $cur = $cur->one_up();
  219.                         if (!$cur) return false;
  220.                 } while ($prev != $cur);
  221.  
  222.                 return false;
  223.         }
  224.  
  225.         public function getRaMail() {
  226.                 $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  227.                 $row = OIDplus::db()->fetch_array($res);
  228.                 return $row['ra_email'];
  229.         }
  230.  
  231.         public function userHasParentalWriteRights($ra_email=null) {
  232.                 if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
  233.  
  234.                 if (is_null($ra_email)) {
  235.                         if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  236.                 }
  237.  
  238.                 $objParent = $this->getParent();
  239.                 if (is_null($objParent)) return false;
  240.                 return $objParent->userHasWriteRights($ra_email);
  241.         }
  242.  
  243.         public function userHasWriteRights($ra_email=null) {
  244.                 if ($ra_email instanceof OIDplusRA) $ra_email = $ra_email->raEmail();
  245.  
  246.                 if (is_null($ra_email)) {
  247.                         if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  248.                         return OIDplus::authUtils()::isRaLoggedIn($this->getRaMail());
  249.                 } else {
  250.                         return $this->getRaMail() == $ra_email;
  251.                 }
  252.         }
  253.  
  254.         public function distance($to) {
  255.                 return null; // not implemented
  256.         }
  257.  
  258.         public function equals($obj) {
  259.                 if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
  260.                 if (!($obj instanceof $this)) return false;
  261.  
  262.                 $distance = $this->distance($obj);
  263.                 if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
  264.  
  265.                 return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
  266.         }
  267.  
  268.         public static function findFitting($id) {
  269.                 $obj = OIDplusObject::parse($id);
  270.                 if (!$obj) throw new Exception("findFitting: Parse failed\n");
  271.  
  272.                 $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id like '".OIDplus::db()->real_escape_string($obj->ns()).":%'");
  273.                 while ($row = OIDplus::db()->fetch_object($res)) {
  274.                         $test = OIDplusObject::parse($row->id);
  275.                         if ($obj->equals($test)) return $test;
  276.                 }
  277.                 return false;
  278.         }
  279.  
  280.         public function one_up() {
  281.                 return null; // not implemented
  282.         }
  283. }
  284.