Subversion Repositories oidplus

Rev

Rev 1054 | Rev 1116 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
844 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
844 daniel-mar 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
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
844 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
844 daniel-mar 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,']');
926 daniel-mar 46
                                        $out[] = (int)substr($fourcc,1,$p-1);
844 daniel-mar 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);
860 daniel-mar 65
                if ($namespace !== self::ns()) return false;
844 daniel-mar 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() {
860 daniel-mar 82
                return self::ns().':';
844 daniel-mar 83
        }
84
 
85
        public function isRoot() {
86
                return $this->fourcc == '';
87
        }
88
 
89
        public function nodeId($with_ns=true) {
859 daniel-mar 90
                return $with_ns ? self::root().$this->fourcc : $this->fourcc;
844 daniel-mar 91
        }
92
 
93
        public function addString($str) {
845 daniel-mar 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) {
844 daniel-mar 104
                        // real FourCC
858 daniel-mar 105
                        return self::root() . $test_str;
844 daniel-mar 106
                } else {
107
                        // just a category
858 daniel-mar 108
                        if ($this->isRoot()) {
109
                                return self::root() . $str;
110
                        } else {
111
                                return $this->nodeId() . '/' . $str;
112
                        }
844 daniel-mar 113
                }
114
        }
115
 
116
        public function crudShowId(OIDplusObject $parent) {
850 daniel-mar 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
                }
844 daniel-mar 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();
845 daniel-mar 144
                $tech_info[_L('FourCC code')]   = $this->fourcc;
145
                $tech_info[_L('C/C++ Literal')] = $this->getMultiCharLiteral();
844 daniel-mar 146
                $tech_info[_L('Hex Dump')]      = strtoupper(implode(' ', str_split($this->getHex(true),2)));
1054 daniel-mar 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).')';
844 daniel-mar 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()) {
962 daniel-mar 160
                                $content  = '<p>'._L('Please select a FourCC in the tree view at the left to show its contents.').'</p>';
844 daniel-mar 161
                        } else {
962 daniel-mar 162
                                $content  = '<p>'._L('Currently, no FourCC is registered in the system.').'</p>';
844 daniel-mar 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()) {
928 daniel-mar 197
                                        $content .= '<h2>'._L('Create or change subordinate objects / categories').'</h2>';
844 daniel-mar 198
                                } else {
928 daniel-mar 199
                                        $content .= '<h2>'._L('Subordinate objects / categories').'</h2>';
844 daniel-mar 200
                                }
201
                                $content .= '%%CRUD%%';
202
                        }
203
                }
204
        }
205
 
1035 daniel-mar 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!
1050 daniel-mar 211
                        if ($trace['class'] === OIDplusPagePublicLogin::class) $in_login_treenode = true;
1035 daniel-mar 212
                }
213
 
214
                if (!$in_login_treenode && !$this->isLeafNode()) return null; // foldericon
215
 
844 daniel-mar 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
 
1054 daniel-mar 236
        private function getInt($big_endian) {
844 daniel-mar 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];
1054 daniel-mar 242
                return $dec;
243
        }
244
 
245
        private function getHex($big_endian) {
246
                $dec = $this->getInt($big_endian);
844 daniel-mar 247
                $hex = str_pad(dechex($dec), 8, "0", STR_PAD_LEFT);
248
                return $hex;
249
        }
250
 
845 daniel-mar 251
        private function getMultiCharLiteral() {
844 daniel-mar 252
                $type = self::fourcc_transform($this->fourcc);
253
                if ($type === false) return false;
926 daniel-mar 254
                return c_literal($type);
844 daniel-mar 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
        }
850 daniel-mar 271
}