Subversion Repositories oidplus

Rev

Rev 1054 | Rev 1116 | 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 - 2023 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. namespace ViaThinkSoft\OIDplus;
  21.  
  22. // phpcs:disable PSR1.Files.SideEffects
  23. \defined('INSIDE_OIDPLUS') or die;
  24. // phpcs:enable PSR1.Files.SideEffects
  25.  
  26. class OIDplusFourCC extends OIDplusObject {
  27.         private $fourcc;
  28.  
  29.         // FourCC Syntax examples:
  30.         // fourcc_transform('8BIM')       === array(56,66,73,77);   // Adobe Photoshop
  31.         // fourcc_transform('AVI')        === array(65,86,73,32);   // AVI File (padded with whitespace)
  32.         // fourcc_transform('Y3[10][10]') === array(89,51,10,10);   // 10bit Y'CbCr 4:2:2 video
  33.         // Non-FourCC:  fourcc_transform returns false.
  34.         private function fourcc_transform($fourcc) {
  35.                 $out = array();
  36.                 if ($fourcc === '') return false;
  37.                 for ($i=0; $i<4; $i++) {
  38.                         if (strlen($fourcc) === 0) {
  39.                                 $out[] = 0x20; // fill with whitespace
  40.                         } else {
  41.                                 if ($fourcc[0] !== '[') {
  42.                                         $out[] = ord($fourcc[0]);
  43.                                         $fourcc = substr($fourcc,1);
  44.                                 } else {
  45.                                         $p = strpos($fourcc,']');
  46.                                         $out[] = (int)substr($fourcc,1,$p-1);
  47.                                         $fourcc = substr($fourcc,$p+1);
  48.                                 }
  49.                         }
  50.                 }
  51.                 if ($fourcc !== '') return false;
  52.                 return $out;
  53.         }
  54.  
  55.         public function __construct($fourcc) {
  56.                 if (self::fourcc_transform($fourcc) !== false) {
  57.                         $this->fourcc = $fourcc; // leaf node
  58.                 } else {
  59.                         $this->fourcc = $fourcc; // It is a category name
  60.                 }
  61.         }
  62.  
  63.         public static function parse($node_id) {
  64.                 @list($namespace, $fourcc) = explode(':', $node_id, 2);
  65.                 if ($namespace !== self::ns()) return false;
  66.                 return new self($fourcc);
  67.         }
  68.  
  69.         public static function objectTypeTitle() {
  70.                 return _L('Four-Character-Code (FourCC)');
  71.         }
  72.  
  73.         public static function objectTypeTitleShort() {
  74.                 return _L('FourCC');
  75.         }
  76.  
  77.         public static function ns() {
  78.                 return 'fourcc';
  79.         }
  80.  
  81.         public static function root() {
  82.                 return self::ns().':';
  83.         }
  84.  
  85.         public function isRoot() {
  86.                 return $this->fourcc == '';
  87.         }
  88.  
  89.         public function nodeId($with_ns=true) {
  90.                 return $with_ns ? self::root().$this->fourcc : $this->fourcc;
  91.         }
  92.  
  93.         public function addString($str) {
  94.  
  95.                 // Y3[10] [10] --> Y3[10][10]
  96.                 $test_str = trim($str);
  97.                 do {
  98.                         $test_str2 = $test_str;
  99.                         $test_str = str_replace(' [', '[', $test_str);
  100.                         $test_str = str_replace('] ', ']', $test_str);
  101.                 } while ($test_str2 != $test_str);
  102.  
  103.                 if (self::fourcc_transform($test_str) !== false) {
  104.                         // real FourCC
  105.                         return self::root() . $test_str;
  106.                 } else {
  107.                         // just a category
  108.                         if ($this->isRoot()) {
  109.                                 return self::root() . $str;
  110.                         } else {
  111.                                 return $this->nodeId() . '/' . $str;
  112.                         }
  113.                 }
  114.         }
  115.  
  116.         public function crudShowId(OIDplusObject $parent) {
  117.                 if ($this->isLeafNode()) {
  118.                         // We don't parse '/' in a valid FourCC code (i.e. Leaf node)
  119.                         return $this->nodeId(false);
  120.                 } else {
  121.                         if ($parent->isRoot()) {
  122.                                 return substr($this->nodeId(), strlen($parent->nodeId()));
  123.                         } else {
  124.                                 return substr($this->nodeId(), strlen($parent->nodeId())+1);
  125.                         }
  126.                 }
  127.         }
  128.  
  129.         public function jsTreeNodeName(OIDplusObject $parent = null) {
  130.                 if ($parent == null) return $this->objectTypeTitle();
  131.                 return $this->crudShowId($parent);
  132.         }
  133.  
  134.         public function defaultTitle() {
  135.                 return $this->fourcc;
  136.         }
  137.  
  138.         public function isLeafNode() {
  139.                 return self::fourcc_transform($this->fourcc) !== false;
  140.         }
  141.  
  142.         private function getTechInfo() {
  143.                 $tech_info = array();
  144.                 $tech_info[_L('FourCC code')]   = $this->fourcc;
  145.                 $tech_info[_L('C/C++ Literal')] = $this->getMultiCharLiteral();
  146.                 $tech_info[_L('Hex Dump')]      = strtoupper(implode(' ', str_split($this->getHex(true),2)));
  147.                 $tech_info[_L('Big Endian')]    = '0x'.$this->getHex(true).' ('.$this->getInt(true).')';
  148.                 $tech_info[_L('Little Endian')] = '0x'.$this->getHex(false).' ('.$this->getInt(false).')';
  149.                 return $tech_info;
  150.         }
  151.  
  152.         public function getContentPage(&$title, &$content, &$icon) {
  153.                 $icon = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
  154.  
  155.                 if ($this->isRoot()) {
  156.                         $title = OIDplusFourCC::objectTypeTitle();
  157.  
  158.                         $res = OIDplus::db()->query("select * from ###objects where parent = ?", array(self::root()));
  159.                         if ($res->any()) {
  160.                                 $content  = '<p>'._L('Please select a FourCC in the tree view at the left to show its contents.').'</p>';
  161.                         } else {
  162.                                 $content  = '<p>'._L('Currently, no FourCC is registered in the system.').'</p>';
  163.                         }
  164.  
  165.                         if (!$this->isLeafNode()) {
  166.                                 if (OIDplus::authUtils()->isAdminLoggedIn()) {
  167.                                         $content .= '<h2>'._L('Manage root objects / categories').'</h2>';
  168.                                 } else {
  169.                                         $content .= '<h2>'._L('Available objects / categories').'</h2>';
  170.                                 }
  171.                                 $content .= '%%CRUD%%';
  172.                         }
  173.                 } else {
  174.                         $title = $this->getTitle();
  175.  
  176.                         if ($this->isLeafNode()) {
  177.                                 $tech_info = $this->getTechInfo();
  178.                                 $tech_info_html = '';
  179.                                 if (count($tech_info) > 0) {
  180.                                         $tech_info_html .= '<h2>'._L('Technical information').'</h2>';
  181.                                         $tech_info_html .= '<table border="0">';
  182.                                         foreach ($tech_info as $key => $value) {
  183.                                                 $tech_info_html .= '<tr><td>'.$key.': </td><td><code>'.str_replace(' ','&nbsp;',$value).'</code></td></tr>';
  184.                                         }
  185.                                         $tech_info_html .= '</table>';
  186.                                 }
  187.  
  188.                                 $content = $tech_info_html;
  189.                         } else {
  190.                                 $content = '';
  191.                         }
  192.  
  193.                         $content .= '<h2>'._L('Description').'</h2>%%DESC%%';
  194.  
  195.                         if (!$this->isLeafNode()) {
  196.                                 if ($this->userHasWriteRights()) {
  197.                                         $content .= '<h2>'._L('Create or change subordinate objects / categories').'</h2>';
  198.                                 } else {
  199.                                         $content .= '<h2>'._L('Subordinate objects / categories').'</h2>';
  200.                                 }
  201.                                 $content .= '%%CRUD%%';
  202.                         }
  203.                 }
  204.         }
  205.  
  206.         public function getIcon($row=null) {
  207.                 $in_login_treenode = false;
  208.                 foreach (debug_backtrace() as $trace) {
  209.                         // If we are inside the "Login" area (i.e. "Root object links"), we want the
  210.                         // correct icon, not a folder icon!
  211.                         if ($trace['class'] === OIDplusPagePublicLogin::class) $in_login_treenode = true;
  212.                 }
  213.  
  214.                 if (!$in_login_treenode && !$this->isLeafNode()) return null; // foldericon
  215.  
  216.                 return parent::getIcon($row);
  217.         }
  218.  
  219.         public function one_up() {
  220.                 // A FourCC is a FourCC, there is no hierarchy
  221.                 return false;
  222.         }
  223.  
  224.         public function distance($to) {
  225.                 // Distance between FourCCs is not possible
  226.                 return null;
  227.         }
  228.  
  229.         public function getAltIds() {
  230.                 if ($this->isRoot()) return array();
  231.                 if (!$this->isLeafNode()) return array();
  232.                 $ids = parent::getAltIds();
  233.                 return $ids;
  234.         }
  235.  
  236.         private function getInt($big_endian) {
  237.                 $type = self::fourcc_transform($this->fourcc);
  238.                 if ($type === false) return false;
  239.                 $dec = 0;
  240.                 if (!$big_endian) $type = array_reverse($type);
  241.                 for ($i=0;$i<4;$i++) $dec = ($dec<<8) + $type[$i];
  242.                 return $dec;
  243.         }
  244.  
  245.         private function getHex($big_endian) {
  246.                 $dec = $this->getInt($big_endian);
  247.                 $hex = str_pad(dechex($dec), 8, "0", STR_PAD_LEFT);
  248.                 return $hex;
  249.         }
  250.  
  251.         private function getMultiCharLiteral() {
  252.                 $type = self::fourcc_transform($this->fourcc);
  253.                 if ($type === false) return false;
  254.                 return c_literal($type);
  255.         }
  256.  
  257.         public function getDirectoryName() {
  258.                 if ($this->isLeafNode()) {
  259.                         // Leaf (FourCC)
  260.                         // Example output: "fourcc_23496d52" for 'fourcc:#ImR'
  261.                         return $this->ns().'_'.$this->getHex(true);
  262.                 } else {
  263.                         // Category
  264.                         return parent::getDirectoryName();
  265.                 }
  266.         }
  267.  
  268.         public static function treeIconFilename($mode) {
  269.                 return 'img/'.$mode.'_icon16.png';
  270.         }
  271. }
  272.