Rev 1130 | Rev 1162 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1130 | Rev 1143 | ||
---|---|---|---|
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | /* |
3 | /* |
4 | * OIDplus 2.0 |
4 | * OIDplus 2.0 |
5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
6 | * |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | * you may not use this file except in compliance with 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 |
9 | * You may obtain a copy of the License at |
10 | * |
10 | * |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | * |
12 | * |
13 | * Unless required by applicable law or agreed to in writing, software |
13 | * Unless required by applicable law or agreed to in writing, software |
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | * See the License for the specific language governing permissions and |
16 | * See the License for the specific language governing permissions and |
17 | * limitations under the License. |
17 | * limitations under the License. |
18 | */ |
18 | */ |
19 | 19 | ||
20 | namespace ViaThinkSoft\OIDplus; |
20 | namespace ViaThinkSoft\OIDplus; |
21 | 21 | ||
22 | // phpcs:disable PSR1.Files.SideEffects |
22 | // phpcs:disable PSR1.Files.SideEffects |
23 | \defined('INSIDE_OIDPLUS') or die; |
23 | \defined('INSIDE_OIDPLUS') or die; |
24 | // phpcs:enable PSR1.Files.SideEffects |
24 | // phpcs:enable PSR1.Files.SideEffects |
25 | 25 | ||
26 | class OIDplusPagePublicResources extends OIDplusPagePluginPublic { |
26 | class OIDplusPagePublicResources extends OIDplusPagePluginPublic { |
27 | 27 | ||
28 | /** |
28 | /** |
29 | * @return array|mixed|string|string[] |
29 | * @return array|mixed|string|string[] |
30 | */ |
30 | */ |
31 | private function getMainTitle() { |
31 | private function getMainTitle() { |
32 | return _L('Documents and Resources'); |
32 | return _L('Documents and Resources'); |
33 | } |
33 | } |
34 | 34 | ||
35 | /** |
35 | /** |
36 | * @param bool $html |
36 | * @param bool $html |
37 | * @return void |
37 | * @return void |
38 | * @throws OIDplusException |
38 | * @throws OIDplusException |
39 | */ |
39 | */ |
40 | public function init(bool $html=true) { |
40 | public function init(bool $html=true) { |
41 | OIDplus::config()->prepareConfigKey('resource_plugin_autoopen_level', 'Resource plugin: How many levels should be open in the treeview when OIDplus is loaded?', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
41 | OIDplus::config()->prepareConfigKey('resource_plugin_autoopen_level', 'Resource plugin: How many levels should be open in the treeview when OIDplus is loaded?', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
42 | if (!is_numeric($value) || ($value < 0)) { |
42 | if (!is_numeric($value) || ($value < 0)) { |
43 | throw new OIDplusException(_L('Please enter a valid value.')); |
43 | throw new OIDplusException(_L('Please enter a valid value.')); |
44 | } |
44 | } |
45 | }); |
45 | }); |
46 | OIDplus::config()->delete('resource_plugin_title'); |
46 | OIDplus::config()->delete('resource_plugin_title'); |
47 | OIDplus::config()->delete('resource_plugin_path'); |
47 | OIDplus::config()->delete('resource_plugin_path'); |
48 | OIDplus::config()->prepareConfigKey('resource_plugin_hide_empty_path','Resource plugin: Hide empty paths? (0=no, 1=yes)', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
48 | OIDplus::config()->prepareConfigKey('resource_plugin_hide_empty_path','Resource plugin: Hide empty paths? (0=no, 1=yes)', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
49 | if (!is_numeric($value) || (($value != 0) && ($value != 1))) { |
49 | if (!is_numeric($value) || (($value != 0) && ($value != 1))) { |
50 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
50 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
51 | } |
51 | } |
52 | }); |
52 | }); |
53 | } |
53 | } |
54 | 54 | ||
55 | /** |
55 | /** |
56 | * @param string $file |
56 | * @param string $file |
57 | * @return string |
57 | * @return string |
58 | * @throws OIDplusConfigInitializationException|OIDplusException |
58 | * @throws OIDplusConfigInitializationException|OIDplusException |
59 | */ |
59 | */ |
60 | private static function getDocumentContent(string $file): string { |
60 | private static function getDocumentContent(string $file): string { |
61 | $file = self::realname($file); |
61 | $file = self::realname($file); |
62 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
62 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
63 | if (file_exists($file2)) $file = $file2; |
63 | if (file_exists($file2)) $file = $file2; |
64 | 64 | ||
65 | $cont = file_get_contents($file); |
65 | $cont = file_get_contents($file); |
- | 66 | if (!$cont) return ''; |
|
66 | 67 | ||
67 | list($html, $js, $css) = extractHtmlContents($cont); |
68 | list($html, $js, $css) = extractHtmlContents($cont); |
68 | $cont = ''; |
69 | $cont = ''; |
69 | if (!empty($js)) $cont .= "<script>\n$js\n</script>"; |
70 | if (!empty($js)) $cont .= "<script>\n$js\n</script>"; |
70 | if (!empty($css)) $cont .= "<style>\n$css\n</style>"; |
71 | if (!empty($css)) $cont .= "<style>\n$css\n</style>"; |
71 | $cont .= stripHtmlComments($html); |
72 | $cont .= stripHtmlComments($html); |
72 | 73 | ||
73 | return $cont; |
74 | return $cont; |
74 | } |
75 | } |
75 | 76 | ||
76 | /** |
77 | /** |
77 | * @param string $file |
78 | * @param string $file |
78 | * @return array|mixed|string |
79 | * @return array|mixed|string |
79 | * @throws OIDplusConfigInitializationException |
80 | * @throws OIDplusConfigInitializationException |
80 | * @throws OIDplusException |
81 | * @throws OIDplusException |
81 | */ |
82 | */ |
82 | private static function getDocumentTitle(string $file) { |
83 | private static function getDocumentTitle(string $file) { |
83 | $file = self::realname($file); |
84 | $file = self::realname($file); |
84 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
85 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
85 | if (file_exists($file2)) $file = $file2; |
86 | if (file_exists($file2)) $file = $file2; |
86 | 87 | ||
87 | $cont = file_get_contents($file); |
88 | $cont = file_get_contents($file); |
88 | 89 | ||
89 | // make sure the program works even if the user provided HTML is not UTF-8 |
90 | // make sure the program works even if the user provided HTML is not UTF-8 |
90 | $cont = convert_to_utf8_no_bom($cont); |
91 | $cont = convert_to_utf8_no_bom($cont); |
91 | 92 | ||
92 | $m = array(); |
93 | $m = array(); |
93 | if (preg_match('@<title>(.+)</title>@ismU', $cont, $m)) return $m[1]; |
94 | if (preg_match('@<title>(.+)</title>@ismU', $cont, $m)) return $m[1]; |
94 | if (preg_match('@<h1>(.+)</h1>@ismU', $cont, $m)) return $m[1]; |
95 | if (preg_match('@<h1>(.+)</h1>@ismU', $cont, $m)) return $m[1]; |
95 | if (preg_match('@<h2>(.+)</h2>@ismU', $cont, $m)) return $m[1]; |
96 | if (preg_match('@<h2>(.+)</h2>@ismU', $cont, $m)) return $m[1]; |
96 | if (preg_match('@<h3>(.+)</h3>@ismU', $cont, $m)) return $m[1]; |
97 | if (preg_match('@<h3>(.+)</h3>@ismU', $cont, $m)) return $m[1]; |
97 | if (preg_match('@<h4>(.+)</h4>@ismU', $cont, $m)) return $m[1]; |
98 | if (preg_match('@<h4>(.+)</h4>@ismU', $cont, $m)) return $m[1]; |
98 | if (preg_match('@<h5>(.+)</h5>@ismU', $cont, $m)) return $m[1]; |
99 | if (preg_match('@<h5>(.+)</h5>@ismU', $cont, $m)) return $m[1]; |
99 | if (preg_match('@<h6>(.+)</h6>@ismU', $cont, $m)) return $m[1]; |
100 | if (preg_match('@<h6>(.+)</h6>@ismU', $cont, $m)) return $m[1]; |
100 | return pathinfo($file, PATHINFO_FILENAME); // filename without extension |
101 | return pathinfo($file, PATHINFO_FILENAME); // filename without extension |
101 | } |
102 | } |
102 | 103 | ||
103 | /** |
104 | /** |
104 | * @param string $source |
105 | * @param string $source |
105 | * @return bool |
106 | * @return bool |
106 | * @throws OIDplusException |
107 | * @throws OIDplusException |
107 | */ |
108 | */ |
108 | protected static function mayAccessResource(string $source): bool { |
109 | protected static function mayAccessResource(string $source): bool { |
109 | if (OIDplus::authUtils()->isAdminLoggedIn()) return true; |
110 | if (OIDplus::authUtils()->isAdminLoggedIn()) return true; |
110 | 111 | ||
111 | $candidates = array( |
112 | $candidates = array( |
112 | OIDplus::localpath().'userdata/resources/security.ini', |
113 | OIDplus::localpath().'userdata/resources/security.ini', |
113 | OIDplus::localpath().'res/security.ini' |
114 | OIDplus::localpath().'res/security.ini' |
114 | ); |
115 | ); |
115 | foreach ($candidates as $ini_file) { |
116 | foreach ($candidates as $ini_file) { |
116 | if (file_exists($ini_file)) { |
117 | if (file_exists($ini_file)) { |
117 | $data = @parse_ini_file($ini_file, true); |
118 | $data = @parse_ini_file($ini_file, true); |
118 | if (isset($data['Security']) && isset($data['Security'][$source])) { |
119 | if (isset($data['Security']) && isset($data['Security'][$source])) { |
119 | $level = $data['Security'][$source]; |
120 | $level = $data['Security'][$source]; |
120 | if ($level == 'PUBLIC') { |
121 | if ($level == 'PUBLIC') { |
121 | return true; |
122 | return true; |
122 | } else if ($level == 'RA') { |
123 | } else if ($level == 'RA') { |
123 | return |
124 | return |
124 | ((OIDplus::authUtils()->raNumLoggedIn() > 0) || |
125 | ((OIDplus::authUtils()->raNumLoggedIn() > 0) || |
125 | (OIDplus::authUtils()->isAdminLoggedIn())); |
126 | (OIDplus::authUtils()->isAdminLoggedIn())); |
126 | } else if ($level == 'ADMIN') { |
127 | } else if ($level == 'ADMIN') { |
127 | return OIDplus::authUtils()->isAdminLoggedIn(); |
128 | return OIDplus::authUtils()->isAdminLoggedIn(); |
128 | } else { |
129 | } else { |
129 | throw new OIDplusException(_L('Unexpected security level in %1 (expect PUBLIC, RA or ADMIN)', $ini_file)); |
130 | throw new OIDplusException(_L('Unexpected security level in %1 (expect PUBLIC, RA or ADMIN)', $ini_file)); |
130 | } |
131 | } |
131 | } |
132 | } |
132 | } |
133 | } |
133 | } |
134 | } |
134 | return true; |
135 | return true; |
135 | } |
136 | } |
136 | 137 | ||
137 | /** |
138 | /** |
138 | * @param string $reldir |
139 | * @param string $reldir |
139 | * @param bool $onlydir |
140 | * @param bool $onlydir |
140 | * @return array |
141 | * @return array |
141 | * @throws OIDplusException |
142 | * @throws OIDplusException |
142 | */ |
143 | */ |
143 | private static function myglob(string $reldir, bool $onlydir=false): array { |
144 | private static function myglob(string $reldir, bool $onlydir=false): array { |
144 | $out = array(); |
145 | $out = array(); |
145 | 146 | ||
146 | $root = OIDplus::localpath().'userdata/resources/'; |
147 | $root = OIDplus::localpath().'userdata/resources/'; |
147 | $res = $onlydir ? @glob($root.ltrim($reldir,'/'), GLOB_ONLYDIR) : @glob($root.ltrim($reldir,'/')); |
148 | $res = $onlydir ? @glob($root.ltrim($reldir,'/'), GLOB_ONLYDIR) : @glob($root.ltrim($reldir,'/')); |
148 | if ($res) foreach ($res as &$x) { |
149 | if ($res) foreach ($res as &$x) { |
149 | $x = substr($x, strlen($root)); |
150 | $x = substr($x, strlen($root)); |
150 | if (strpos($x,'$') !== false) continue; |
151 | if (strpos($x,'$') !== false) continue; |
151 | $out[] = $x; |
152 | $out[] = $x; |
152 | } |
153 | } |
153 | 154 | ||
154 | $root = OIDplus::localpath().'res/'; |
155 | $root = OIDplus::localpath().'res/'; |
155 | $res = $onlydir ? @glob($root.ltrim($reldir,'/'), GLOB_ONLYDIR) : @glob($root.ltrim($reldir,'/')); |
156 | $res = $onlydir ? @glob($root.ltrim($reldir,'/'), GLOB_ONLYDIR) : @glob($root.ltrim($reldir,'/')); |
156 | if ($res) foreach ($res as $x) { |
157 | if ($res) foreach ($res as $x) { |
157 | $x = substr($x, strlen($root)); |
158 | $x = substr($x, strlen($root)); |
158 | if (strpos($x,'$') !== false) continue; |
159 | if (strpos($x,'$') !== false) continue; |
159 | $out[] = $x; |
160 | $out[] = $x; |
160 | } |
161 | } |
161 | 162 | ||
162 | $out = array_unique($out); |
163 | $out = array_unique($out); |
163 | 164 | ||
164 | return array_filter($out, function($v, $k) { |
165 | return array_filter($out, function($v, $k) { |
165 | return self::mayAccessResource($v); |
166 | return self::mayAccessResource($v); |
166 | }, ARRAY_FILTER_USE_BOTH); |
167 | }, ARRAY_FILTER_USE_BOTH); |
167 | } |
168 | } |
168 | 169 | ||
169 | /** |
170 | /** |
170 | * @param string $rel |
171 | * @param string $rel |
171 | * @return string|null |
172 | * @return string|null |
172 | */ |
173 | */ |
173 | private static function realname(string $rel) { |
174 | private static function realname(string $rel) { |
174 | $candidate1 = OIDplus::localpath().'userdata/resources/'.$rel; |
175 | $candidate1 = OIDplus::localpath().'userdata/resources/'.$rel; |
175 | $candidate2 = OIDplus::localpath().'res/'.$rel; |
176 | $candidate2 = OIDplus::localpath().'res/'.$rel; |
176 | if (file_exists($candidate1) || is_dir($candidate1)) return $candidate1; |
177 | if (file_exists($candidate1) || is_dir($candidate1)) return $candidate1; |
177 | if (file_exists($candidate2) || is_dir($candidate2)) return $candidate2; |
178 | if (file_exists($candidate2) || is_dir($candidate2)) return $candidate2; |
178 | return null; |
179 | return null; |
179 | } |
180 | } |
180 | 181 | ||
181 | /** |
182 | /** |
182 | * @param string $source |
183 | * @param string $source |
183 | * @param string $target |
184 | * @param string $target |
184 | * @return bool |
185 | * @return bool |
185 | */ |
186 | */ |
186 | protected static function checkRedirect(string $source, string &$target): bool { |
187 | protected static function checkRedirect(string $source, string &$target): bool { |
187 | $candidates = array( |
188 | $candidates = array( |
188 | OIDplus::localpath().'userdata/resources/redirect.ini', |
189 | OIDplus::localpath().'userdata/resources/redirect.ini', |
189 | OIDplus::localpath().'res/redirect.ini' |
190 | OIDplus::localpath().'res/redirect.ini' |
190 | ); |
191 | ); |
191 | foreach ($candidates as $ini_file) { |
192 | foreach ($candidates as $ini_file) { |
192 | if (file_exists($ini_file)) { |
193 | if (file_exists($ini_file)) { |
193 | $data = @parse_ini_file($ini_file, true); |
194 | $data = @parse_ini_file($ini_file, true); |
194 | if (isset($data['Redirects']) && isset($data['Redirects'][$source])) { |
195 | if (isset($data['Redirects']) && isset($data['Redirects'][$source])) { |
195 | $target = $data['Redirects'][$source]; |
196 | $target = $data['Redirects'][$source]; |
196 | return true; |
197 | return true; |
197 | } |
198 | } |
198 | } |
199 | } |
199 | } |
200 | } |
200 | return false; |
201 | return false; |
201 | } |
202 | } |
202 | 203 | ||
203 | /** |
204 | /** |
204 | * @param string $id |
205 | * @param string $id |
205 | * @param array $out |
206 | * @param array $out |
206 | * @param bool $handled |
207 | * @param bool $handled |
207 | * @return void |
208 | * @return void |
208 | * @throws OIDplusConfigInitializationException |
209 | * @throws OIDplusConfigInitializationException |
209 | * @throws OIDplusException |
210 | * @throws OIDplusException |
210 | */ |
211 | */ |
211 | public function gui(string $id, array &$out, bool &$handled) { |
212 | public function gui(string $id, array &$out, bool &$handled) { |
212 | if (explode('$',$id,2)[0] === 'oidplus:resources') { |
213 | if (explode('$',$id,2)[0] === 'oidplus:resources') { |
213 | $handled = true; |
214 | $handled = true; |
214 | 215 | ||
215 | $tmp = explode('$',$id); |
216 | $tmp = explode('$',$id); |
216 | $file = $tmp[1] ?? ''; |
217 | $file = $tmp[1] ?? ''; |
217 | unset($tmp); |
218 | unset($tmp); |
218 | 219 | ||
219 | // Security checks |
220 | // Security checks |
220 | 221 | ||
221 | if ( |
222 | if ( |
222 | ($file != '') && ( |
223 | ($file != '') && ( |
223 | (strpos($file, chr(0)) !== false) || // Directory traversal (LFI,RFI) helper |
224 | (strpos($file, chr(0)) !== false) || // Directory traversal (LFI,RFI) helper |
224 | (strpos($file, '../') !== false) || ($file[0] == '/') || ($file[0] == '~') || // <-- Local File Injection (LFI) |
225 | (strpos($file, '../') !== false) || ($file[0] == '/') || ($file[0] == '~') || // <-- Local File Injection (LFI) |
225 | ($file[0] == '.') || (strpos($file, '/.') !== false) || // <-- Calling hidden files e.g. ".htpasswd" |
226 | ($file[0] == '.') || (strpos($file, '/.') !== false) || // <-- Calling hidden files e.g. ".htpasswd" |
226 | (strpos($file, '://') !== false) // <-- Remote File Injection (RFI) |
227 | (strpos($file, '://') !== false) // <-- Remote File Injection (RFI) |
227 | )) { |
228 | )) { |
228 | if (strpos($file, chr(0)) !== false) { |
229 | if (strpos($file, chr(0)) !== false) { |
229 | $file = str_replace(chr(0), '[NUL]', $file); |
230 | $file = str_replace(chr(0), '[NUL]', $file); |
230 | } |
231 | } |
231 | // This will not be logged anymore, because people could spam the log files otherwise |
232 | // This will not be logged anymore, because people could spam the log files otherwise |
232 | //OIDplus::logger()->log("[WARN]A!", "LFI/RFI attack blocked (requested file '$file')"); |
233 | //OIDplus::logger()->log("[WARN]A!", "LFI/RFI attack blocked (requested file '$file')"); |
233 | $out['title'] = _L('Access denied'); |
234 | $out['title'] = _L('Access denied'); |
234 | $out['icon'] = 'img/error.png'; |
235 | $out['icon'] = 'img/error.png'; |
235 | $out['text'] = '<p>'._L('This request is invalid').'</p>'; |
236 | $out['text'] = '<p>'._L('This request is invalid').'</p>'; |
236 | return; |
237 | return; |
237 | } |
238 | } |
238 | 239 | ||
239 | $out['text'] = ''; |
240 | $out['text'] = ''; |
240 | 241 | ||
241 | // Check for permission |
242 | // Check for permission |
242 | 243 | ||
243 | if ($file != '') { |
244 | if ($file != '') { |
244 | if (!self::mayAccessResource($file)) { |
245 | if (!self::mayAccessResource($file)) { |
245 | $out['title'] = _L('Access denied'); |
246 | $out['title'] = _L('Access denied'); |
246 | $out['icon'] = 'img/error.png'; |
247 | $out['icon'] = 'img/error.png'; |
247 | $out['text'] = '<p>'._L('Authentication error. Please log in.').'</p>'; |
248 | $out['text'] = '<p>'._L('Authentication error. Please log in.').'</p>'; |
248 | return; |
249 | return; |
249 | } |
250 | } |
250 | } |
251 | } |
251 | 252 | ||
252 | // Redirections |
253 | // Redirections |
253 | 254 | ||
254 | if ($file != '') { |
255 | if ($file != '') { |
255 | $target = ''; |
256 | $target = ''; |
256 | if (self::checkRedirect($file, $target)) { |
257 | if (self::checkRedirect($file, $target)) { |
257 | $out['title'] = _L('Please wait...'); |
258 | $out['title'] = _L('Please wait...'); |
258 | $out['text'] = '<p>'._L('You are being redirected...').'</p><script>window.location.href = '.js_escape($target).';</script>'; |
259 | $out['text'] = '<p>'._L('You are being redirected...').'</p><script>window.location.href = '.js_escape($target).';</script>'; |
259 | return; |
260 | return; |
260 | } |
261 | } |
261 | } |
262 | } |
262 | 263 | ||
263 | // First, "Go back to" line |
264 | // First, "Go back to" line |
264 | 265 | ||
265 | if ($file != '') { |
266 | if ($file != '') { |
266 | $dir = dirname($file); |
267 | $dir = dirname($file); |
267 | 268 | ||
268 | if ($dir == '.') { |
269 | if ($dir == '.') { |
269 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
270 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
270 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
271 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
271 | } else { |
272 | } else { |
272 | $tree_icon = null; // default icon (folder) |
273 | $tree_icon = null; // default icon (folder) |
273 | } |
274 | } |
274 | 275 | ||
275 | $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">'; |
276 | $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">'; |
276 | 277 | ||
277 | $lng_gobackto = _L('Go back to').':'; |
278 | $lng_gobackto = _L('Go back to').':'; |
278 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '.$lng_gobackto.' '.$ic.' '.htmlentities($this->getMainTitle()).'</a></p>'; |
279 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '.$lng_gobackto.' '.$ic.' '.htmlentities($this->getMainTitle()).'</a></p>'; |
279 | } else { |
280 | } else { |
280 | $realdir = self::realname($dir); |
281 | $realdir = self::realname($dir); |
281 | 282 | ||
282 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
283 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
283 | /* |
284 | /* |
284 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
285 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
285 | if (file_exists($icon_candidate)) { |
286 | if (file_exists($icon_candidate)) { |
286 | $tree_icon = $icon_candidate; |
287 | $tree_icon = $icon_candidate; |
287 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
288 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
288 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
289 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
289 | } else { |
290 | } else { |
290 | $tree_icon = null; // no icon |
291 | $tree_icon = null; // no icon |
291 | } |
292 | } |
292 | */ |
293 | */ |
293 | 294 | ||
294 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
295 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
295 | 296 | ||
296 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.rtrim($dir,'/').'/').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to').': '.$ic.' '.htmlentities(self::getFolderTitle($realdir)).'</a></p><br>'; |
297 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.rtrim($dir,'/').'/').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to').': '.$ic.' '.htmlentities(self::getFolderTitle($realdir)).'</a></p><br>'; |
297 | } |
298 | } |
298 | } |
299 | } |
299 | 300 | ||
300 | // Then the content |
301 | // Then the content |
301 | 302 | ||
302 | $realfile = self::realname($file); |
303 | $realfile = self::realname($file); |
303 | // $realfile2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $realfile); |
304 | // $realfile2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $realfile); |
304 | // if (file_exists($realfile2)) $realfile = $realfile2; |
305 | // if (file_exists($realfile2)) $realfile = $realfile2; |
305 | 306 | ||
306 | if (file_exists($realfile) && (!is_dir($realfile))) { |
307 | if (file_exists($realfile) && (!is_dir($realfile))) { |
307 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
308 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
308 | $out['title'] = $this->getHyperlinkTitle($realfile); |
309 | $out['title'] = $this->getHyperlinkTitle($realfile); |
309 | 310 | ||
310 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
311 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
311 | /* |
312 | /* |
312 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
313 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
313 | if (file_exists($icon_candidate)) { |
314 | if (file_exists($icon_candidate)) { |
314 | $out['icon'] = $icon_candidate; |
315 | $out['icon'] = $icon_candidate; |
315 | } else if (file_exists(__DIR__.'/img/leaf_url_icon.png')) { |
316 | } else if (file_exists(__DIR__.'/img/leaf_url_icon.png')) { |
316 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon.png'; |
317 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon.png'; |
317 | } else { |
318 | } else { |
318 | $out['icon'] = ''; |
319 | $out['icon'] = ''; |
319 | } |
320 | } |
320 | */ |
321 | */ |
321 | 322 | ||
322 | // Should not happen though, due to conditionalselect |
323 | // Should not happen though, due to conditionalselect |
323 | $out['text'] .= '<a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">'._L('Open in new window').'</a>'; |
324 | $out['text'] .= '<a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">'._L('Open in new window').'</a>'; |
324 | } else if ((substr($file,-4,4) == '.htm') || (substr($file,-5,5) == '.html')) { |
325 | } else if ((substr($file,-4,4) == '.htm') || (substr($file,-5,5) == '.html')) { |
325 | $out['title'] = $this->getDocumentTitle($file); |
326 | $out['title'] = $this->getDocumentTitle($file); |
326 | 327 | ||
327 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
328 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
328 | /* |
329 | /* |
329 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
330 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
330 | if (file_exists($icon_candidate)) { |
331 | if (file_exists($icon_candidate)) { |
331 | $out['icon'] = $icon_candidate; |
332 | $out['icon'] = $icon_candidate; |
332 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon.png')) { |
333 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon.png')) { |
333 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon.png'; |
334 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon.png'; |
334 | } else { |
335 | } else { |
335 | $out['icon'] = ''; |
336 | $out['icon'] = ''; |
336 | } |
337 | } |
337 | */ |
338 | */ |
338 | 339 | ||
339 | $out['text'] .= self::getDocumentContent($file); |
340 | $out['text'] .= self::getDocumentContent($file); |
340 | } else { |
341 | } else { |
341 | $out['title'] = _L('Unknown file type'); |
342 | $out['title'] = _L('Unknown file type'); |
342 | $out['icon'] = 'img/error.png'; |
343 | $out['icon'] = 'img/error.png'; |
343 | $out['text'] = '<p>'._L('The system does not know how to handle this file type.').'</p>'; |
344 | $out['text'] = '<p>'._L('The system does not know how to handle this file type.').'</p>'; |
344 | } |
345 | } |
345 | } else if (is_dir($realfile)) { |
346 | } else if (is_dir($realfile)) { |
346 | $out['title'] = ($file == '') ? $this->getMainTitle() : self::getFolderTitle($realfile); |
347 | $out['title'] = ($file == '') ? $this->getMainTitle() : self::getFolderTitle($realfile); |
347 | 348 | ||
348 | if ($file == '') { |
349 | if ($file == '') { |
349 | $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
350 | $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
350 | } else { |
351 | } else { |
351 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
352 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
352 | /* |
353 | /* |
353 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
354 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png'; |
354 | if (file_exists($icon_candidate)) { |
355 | if (file_exists($icon_candidate)) { |
355 | $out['icon'] = $icon_candidate; |
356 | $out['icon'] = $icon_candidate; |
356 | } else if (file_exists(__DIR__.'/img/folder_icon.png')) { |
357 | } else if (file_exists(__DIR__.'/img/folder_icon.png')) { |
357 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon.png'; |
358 | $out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon.png'; |
358 | } else { |
359 | } else { |
359 | $out['icon'] = null; // no icon |
360 | $out['icon'] = null; // no icon |
360 | } |
361 | } |
361 | */ |
362 | */ |
362 | } |
363 | } |
363 | 364 | ||
364 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
365 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
365 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
366 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
366 | } else { |
367 | } else { |
367 | $tree_icon = null; // default icon (folder) |
368 | $tree_icon = null; // default icon (folder) |
368 | } |
369 | } |
369 | 370 | ||
370 | $count = 0; |
371 | $count = 0; |
371 | 372 | ||
372 | $dirs = self::myglob(rtrim($file,'/').'/'.'*', true); |
373 | $dirs = self::myglob(rtrim($file,'/').'/'.'*', true); |
373 | natcasesort($dirs); |
374 | natcasesort($dirs); |
374 | foreach ($dirs as $dir) { |
375 | foreach ($dirs as $dir) { |
375 | $realdir = self::realname($dir); |
376 | $realdir = self::realname($dir); |
376 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
377 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
377 | /* |
378 | /* |
378 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
379 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
379 | if (file_exists($icon_candidate)) { |
380 | if (file_exists($icon_candidate)) { |
380 | $tree_icon = $icon_candidate; |
381 | $tree_icon = $icon_candidate; |
381 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
382 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
382 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
383 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
383 | } else { |
384 | } else { |
384 | $tree_icon = null; // no icon |
385 | $tree_icon = null; // no icon |
385 | } |
386 | } |
386 | */ |
387 | */ |
387 | 388 | ||
388 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
389 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
389 | 390 | ||
390 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.rtrim($dir,'/').'/').'>'.$ic.' '.htmlentities(self::getFolderTitle($realdir)).'</a></p>'; |
391 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.rtrim($dir,'/').'/').'>'.$ic.' '.htmlentities(self::getFolderTitle($realdir)).'</a></p>'; |
391 | $count++; |
392 | $count++; |
392 | } |
393 | } |
393 | 394 | ||
394 | $files = array_merge( |
395 | $files = array_merge( |
395 | self::myglob(rtrim($file,'/').'/'.'*.htm'), // TODO: also PHP? |
396 | self::myglob(rtrim($file,'/').'/'.'*.htm'), // TODO: also PHP? |
396 | self::myglob(rtrim($file,'/').'/'.'*.html'), |
397 | self::myglob(rtrim($file,'/').'/'.'*.html'), |
397 | self::myglob(rtrim($file,'/').'/'.'*.url'), |
398 | self::myglob(rtrim($file,'/').'/'.'*.url'), |
398 | self::myglob(rtrim($file,'/').'/'.'*.link') |
399 | self::myglob(rtrim($file,'/').'/'.'*.link') |
399 | ); |
400 | ); |
400 | natcasesort($files); |
401 | natcasesort($files); |
401 | foreach ($files as $file) { |
402 | foreach ($files as $file) { |
402 | $realfile = self::realname($file); |
403 | $realfile = self::realname($file); |
403 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
404 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
404 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
405 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
405 | /* |
406 | /* |
406 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
407 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
407 | if (file_exists($icon_candidate)) { |
408 | if (file_exists($icon_candidate)) { |
408 | $tree_icon = $icon_candidate; |
409 | $tree_icon = $icon_candidate; |
409 | } else if (file_exists(__DIR__.'/img/leaf_url_icon16.png')) { |
410 | } else if (file_exists(__DIR__.'/img/leaf_url_icon16.png')) { |
410 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon16.png'; |
411 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon16.png'; |
411 | } else { |
412 | } else { |
412 | $tree_icon = null; // default icon (folder) |
413 | $tree_icon = null; // default icon (folder) |
413 | } |
414 | } |
414 | */ |
415 | */ |
415 | 416 | ||
416 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
417 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
417 | 418 | ||
418 | $out['text'] .= '<p><a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">'.$ic.' '.htmlentities($this->getHyperlinkTitle($realfile)).'</a></p>'; |
419 | $out['text'] .= '<p><a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">'.$ic.' '.htmlentities($this->getHyperlinkTitle($realfile)).'</a></p>'; |
419 | $count++; |
420 | $count++; |
420 | } else { |
421 | } else { |
421 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
422 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
422 | /* |
423 | /* |
423 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
424 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
424 | if (file_exists($icon_candidate)) { |
425 | if (file_exists($icon_candidate)) { |
425 | $tree_icon = $icon_candidate; |
426 | $tree_icon = $icon_candidate; |
426 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon16.png')) { |
427 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon16.png')) { |
427 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon16.png'; |
428 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon16.png'; |
428 | } else { |
429 | } else { |
429 | $tree_icon = null; // default icon (folder) |
430 | $tree_icon = null; // default icon (folder) |
430 | } |
431 | } |
431 | */ |
432 | */ |
432 | 433 | ||
433 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
434 | $ic = /*empty($tree_icon) ? '' : */'<img src="'.$tree_icon.'" alt="">'; |
434 | 435 | ||
435 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.$file).'>'.$ic.' '.htmlentities($this->getDocumentTitle($file)).'</a></p>'; |
436 | $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.$file).'>'.$ic.' '.htmlentities($this->getDocumentTitle($file)).'</a></p>'; |
436 | $count++; |
437 | $count++; |
437 | } |
438 | } |
438 | } |
439 | } |
439 | 440 | ||
440 | if ($count == 0) { |
441 | if ($count == 0) { |
441 | $out['text'] .= '<p>'._L('This folder does not contain any elements').'</p>'; |
442 | $out['text'] .= '<p>'._L('This folder does not contain any elements').'</p>'; |
442 | } |
443 | } |
443 | } else { |
444 | } else { |
444 | $out['title'] = _L('Not found'); |
445 | $out['title'] = _L('Not found'); |
445 | $out['icon'] = 'img/error.png'; |
446 | $out['icon'] = 'img/error.png'; |
446 | $out['text'] = '<p>'._L('This resource doesn\'t exist anymore.').'</p>'; |
447 | $out['text'] = '<p>'._L('This resource doesn\'t exist anymore.').'</p>'; |
447 | } |
448 | } |
448 | } |
449 | } |
449 | } |
450 | } |
450 | 451 | ||
451 | /** |
452 | /** |
452 | * @param array $children |
453 | * @param array $children |
453 | * @param string|null $rootdir |
454 | * @param string|null $rootdir |
454 | * @param int $depth |
455 | * @param int $depth |
455 | * @return void |
456 | * @return void |
456 | * @throws OIDplusConfigInitializationException |
457 | * @throws OIDplusConfigInitializationException |
457 | * @throws OIDplusException |
458 | * @throws OIDplusException |
458 | */ |
459 | */ |
459 | private function tree_rec(array &$children, string $rootdir=null, int $depth=0)/*: void*/ { |
460 | private function tree_rec(array &$children, string $rootdir=null, int $depth=0)/*: void*/ { |
460 | if (is_null($rootdir)) $rootdir = ''; |
461 | if (is_null($rootdir)) $rootdir = ''; |
461 | if ($depth > 100) return; // something is wrong! |
462 | if ($depth > 100) return; // something is wrong! |
462 | 463 | ||
463 | $dirs = self::myglob($rootdir.'*'.'/', true); |
464 | $dirs = self::myglob($rootdir.'*'.'/', true); |
464 | natcasesort($dirs); |
465 | natcasesort($dirs); |
465 | foreach ($dirs as $dir) { |
466 | foreach ($dirs as $dir) { |
466 | $tmp = array(); |
467 | $tmp = array(); |
467 | 468 | ||
468 | $this->tree_rec($tmp, $dir, $depth+1); |
469 | $this->tree_rec($tmp, $dir, $depth+1); |
469 | 470 | ||
470 | $realdir = self::realname($dir); |
471 | $realdir = self::realname($dir); |
471 | 472 | ||
472 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
473 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=folder_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($dir); |
473 | /* |
474 | /* |
474 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
475 | $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png'; |
475 | if (file_exists($icon_candidate)) { |
476 | if (file_exists($icon_candidate)) { |
476 | $tree_icon = $icon_candidate; |
477 | $tree_icon = $icon_candidate; |
477 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
478 | } else if (file_exists(__DIR__.'/img/folder_icon16.png')) { |
478 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
479 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/folder_icon16.png'; |
479 | } else { |
480 | } else { |
480 | $tree_icon = null; // default icon (folder) |
481 | $tree_icon = null; // default icon (folder) |
481 | } |
482 | } |
482 | */ |
483 | */ |
483 | 484 | ||
484 | $children[] = array( |
485 | $children[] = array( |
485 | 'id' => 'oidplus:resources$'.$dir, |
486 | 'id' => 'oidplus:resources$'.$dir, |
486 | 'icon' => $tree_icon, |
487 | 'icon' => $tree_icon, |
487 | 'text' => self::getFolderTitle($realdir), |
488 | 'text' => self::getFolderTitle($realdir), |
488 | 'children' => $tmp, |
489 | 'children' => $tmp, |
489 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1) |
490 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1) |
490 | ); |
491 | ); |
491 | } |
492 | } |
492 | 493 | ||
493 | $files = array_merge( |
494 | $files = array_merge( |
494 | self::myglob($rootdir.'*.htm'), // TODO: Also PHP? |
495 | self::myglob($rootdir.'*.htm'), // TODO: Also PHP? |
495 | self::myglob($rootdir.'*.html'), |
496 | self::myglob($rootdir.'*.html'), |
496 | self::myglob($rootdir.'*.url'), |
497 | self::myglob($rootdir.'*.url'), |
497 | self::myglob($rootdir.'*.link') |
498 | self::myglob($rootdir.'*.link') |
498 | ); |
499 | ); |
499 | natcasesort($files); |
500 | natcasesort($files); |
500 | foreach ($files as $file) { |
501 | foreach ($files as $file) { |
501 | $realfile = self::realname($file); |
502 | $realfile = self::realname($file); |
502 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
503 | if ((substr($file,-4,4) == '.url') || (substr($file,-5,5) == '.link')) { |
503 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
504 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_url_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
504 | /* |
505 | /* |
505 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
506 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
506 | if (file_exists($icon_candidate)) { |
507 | if (file_exists($icon_candidate)) { |
507 | $tree_icon = $icon_candidate; |
508 | $tree_icon = $icon_candidate; |
508 | } else if (file_exists(__DIR__.'/img/leaf_url_icon16.png')) { |
509 | } else if (file_exists(__DIR__.'/img/leaf_url_icon16.png')) { |
509 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon16.png'; |
510 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_url_icon16.png'; |
510 | } else { |
511 | } else { |
511 | $tree_icon = null; // default icon (folder) |
512 | $tree_icon = null; // default icon (folder) |
512 | } |
513 | } |
513 | */ |
514 | */ |
514 | 515 | ||
515 | $children[] = array( |
516 | $children[] = array( |
516 | 'id' => 'oidplus:resources$'.$file, |
517 | 'id' => 'oidplus:resources$'.$file, |
517 | 'conditionalselect' => 'window.open('.js_escape(self::getHyperlinkURL($realfile)).'); false;', |
518 | 'conditionalselect' => 'window.open('.js_escape(self::getHyperlinkURL($realfile)).'); false;', |
518 | 'icon' => $tree_icon, |
519 | 'icon' => $tree_icon, |
519 | 'text' => $this->getHyperlinkTitle($realfile), |
520 | 'text' => $this->getHyperlinkTitle($realfile), |
520 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1), |
521 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1), |
521 | 'a_attr' => array( |
522 | 'a_attr' => array( |
522 | 'href' => self::getHyperlinkURL($realfile), |
523 | 'href' => self::getHyperlinkURL($realfile), |
523 | 'target' => '_blank' |
524 | 'target' => '_blank' |
524 | ) |
525 | ) |
525 | ); |
526 | ); |
526 | } else { |
527 | } else { |
527 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
528 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'show_icon.php?mode=leaf_doc_icon16&lang='.OIDplus::getCurrentLang().'&file='.urlencode($file); |
528 | /* |
529 | /* |
529 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
530 | $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png'; |
530 | if (file_exists($icon_candidate)) { |
531 | if (file_exists($icon_candidate)) { |
531 | $tree_icon = $icon_candidate; |
532 | $tree_icon = $icon_candidate; |
532 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon16.png')) { |
533 | } else if (file_exists(__DIR__.'/img/leaf_doc_icon16.png')) { |
533 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon16.png'; |
534 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/leaf_doc_icon16.png'; |
534 | } else { |
535 | } else { |
535 | $tree_icon = null; // default icon (folder) |
536 | $tree_icon = null; // default icon (folder) |
536 | } |
537 | } |
537 | */ |
538 | */ |
538 | $children[] = array( |
539 | $children[] = array( |
539 | 'id' => 'oidplus:resources$'.$file, |
540 | 'id' => 'oidplus:resources$'.$file, |
540 | 'icon' => $tree_icon, |
541 | 'icon' => $tree_icon, |
541 | 'text' => $this->getDocumentTitle($file), |
542 | 'text' => $this->getDocumentTitle($file), |
542 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1) |
543 | 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1) |
543 | ); |
544 | ); |
544 | } |
545 | } |
545 | } |
546 | } |
546 | } |
547 | } |
547 | 548 | ||
548 | /** |
549 | /** |
549 | * @param array $json |
550 | * @param array $json |
550 | * @param array $out |
551 | * @param array $out |
551 | * @return void |
552 | * @return void |
552 | */ |
553 | */ |
553 | private function publicSitemap_rec(array $json, array &$out) { |
554 | private function publicSitemap_rec(array $json, array &$out) { |
554 | foreach ($json as $x) { |
555 | foreach ($json as $x) { |
555 | if (isset($x['id']) && $x['id']) { |
556 | if (isset($x['id']) && $x['id']) { |
556 | $out[] = $x['id']; |
557 | $out[] = $x['id']; |
557 | } |
558 | } |
558 | if (isset($x['children'])) { |
559 | if (isset($x['children'])) { |
559 | $this->publicSitemap_rec($x['children'], $out); |
560 | $this->publicSitemap_rec($x['children'], $out); |
560 | } |
561 | } |
561 | } |
562 | } |
562 | } |
563 | } |
563 | 564 | ||
564 | /** |
565 | /** |
565 | * @param array $out |
566 | * @param array $out |
566 | * @return void |
567 | * @return void |
567 | */ |
568 | */ |
568 | public function publicSitemap(array &$out) { |
569 | public function publicSitemap(array &$out) { |
569 | $json = array(); |
570 | $json = array(); |
570 | $this->tree($json, null/*RA EMail*/, false/*HTML tree algorithm*/, "*"/*display all*/); |
571 | $this->tree($json, null/*RA EMail*/, false/*HTML tree algorithm*/, "*"/*display all*/); |
571 | $this->publicSitemap_rec($json, $out); |
572 | $this->publicSitemap_rec($json, $out); |
572 | } |
573 | } |
573 | 574 | ||
574 | /** |
575 | /** |
575 | * @param array $json |
576 | * @param array $json |
576 | * @param string|null $ra_email |
577 | * @param string|null $ra_email |
577 | * @param bool $nonjs |
578 | * @param bool $nonjs |
578 | * @param string $req_goto |
579 | * @param string $req_goto |
579 | * @return bool |
580 | * @return bool |
580 | * @throws OIDplusConfigInitializationException |
581 | * @throws OIDplusConfigInitializationException |
581 | * @throws OIDplusException |
582 | * @throws OIDplusException |
582 | */ |
583 | */ |
583 | public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool { |
584 | public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool { |
584 | $children = array(); |
585 | $children = array(); |
585 | 586 | ||
586 | $this->tree_rec($children, '/'); |
587 | $this->tree_rec($children, '/'); |
587 | 588 | ||
588 | if (!OIDplus::config()->getValue('resource_plugin_hide_empty_path', true) || (count($children) > 0)) { |
589 | if (!OIDplus::config()->getValue('resource_plugin_hide_empty_path', true) || (count($children) > 0)) { |
589 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
590 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
590 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
591 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
591 | } else { |
592 | } else { |
592 | $tree_icon = null; // default icon (folder) |
593 | $tree_icon = null; // default icon (folder) |
593 | } |
594 | } |
594 | 595 | ||
595 | $json[] = array( |
596 | $json[] = array( |
596 | 'id' => 'oidplus:resources', |
597 | 'id' => 'oidplus:resources', |
597 | 'icon' => $tree_icon, |
598 | 'icon' => $tree_icon, |
598 | 'state' => array("opened" => true), |
599 | 'state' => array("opened" => true), |
599 | 'text' => $this->getMainTitle(), |
600 | 'text' => $this->getMainTitle(), |
600 | 'children' => $children |
601 | 'children' => $children |
601 | ); |
602 | ); |
602 | } |
603 | } |
603 | 604 | ||
604 | return true; |
605 | return true; |
605 | } |
606 | } |
606 | 607 | ||
607 | /** |
608 | /** |
608 | * @param string $request |
609 | * @param string $request |
609 | * @return array|false |
610 | * @return array|false |
610 | */ |
611 | */ |
611 | public function tree_search(string $request) { |
612 | public function tree_search(string $request) { |
612 | return false; |
613 | return false; |
613 | } |
614 | } |
614 | 615 | ||
615 | /** |
616 | /** |
616 | * @param string $file |
617 | * @param string $file |
617 | * @return array|mixed|string|string[]|null |
618 | * @return array|mixed|string|string[]|null |
618 | * @throws OIDplusConfigInitializationException |
619 | * @throws OIDplusConfigInitializationException |
619 | * @throws OIDplusException |
620 | * @throws OIDplusException |
620 | */ |
621 | */ |
621 | private static function getHyperlinkTitle(string $file) { |
622 | private static function getHyperlinkTitle(string $file) { |
622 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
623 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
623 | if (file_exists($file2)) $file = $file2; |
624 | if (file_exists($file2)) $file = $file2; |
624 | 625 | ||
625 | if (substr($file,-4,4) == '.url') { |
626 | if (substr($file,-4,4) == '.url') { |
626 | return preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($file)); |
627 | return preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($file)); |
627 | } else if (substr($file,-5,5) == '.link') { |
628 | } else if (substr($file,-5,5) == '.link') { |
628 | /* |
629 | /* |
629 | [Link] |
630 | [Link] |
630 | Title=Report a bug |
631 | Title=Report a bug |
631 | URL=https://github.com/danielmarschall/oidplus/issues |
632 | URL=https://github.com/danielmarschall/oidplus/issues |
632 | */ |
633 | */ |
633 | 634 | ||
634 | $data = @parse_ini_file($file, true); |
635 | $data = @parse_ini_file($file, true); |
635 | if (!$data) { |
636 | if (!$data) { |
636 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
637 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
637 | } |
638 | } |
638 | if (!isset($data['Link'])) { |
639 | if (!isset($data['Link'])) { |
639 | throw new OIDplusException(_L('Could not find "%1" section at %2','Link',$file)); |
640 | throw new OIDplusException(_L('Could not find "%1" section at %2','Link',$file)); |
640 | } |
641 | } |
641 | if (!isset($data['Link']['Title'])) { |
642 | if (!isset($data['Link']['Title'])) { |
642 | throw new OIDplusException(_L('"%1" is missing in %2','Title',$file)); |
643 | throw new OIDplusException(_L('"%1" is missing in %2','Title',$file)); |
643 | } |
644 | } |
644 | return $data['Link']['Title']; |
645 | return $data['Link']['Title']; |
645 | } else { |
646 | } else { |
646 | throw new OIDplusException(_L('Unexpected file extension for file %1',$file)); |
647 | throw new OIDplusException(_L('Unexpected file extension for file %1',$file)); |
647 | } |
648 | } |
648 | } |
649 | } |
649 | 650 | ||
650 | /** |
651 | /** |
651 | * @param string $file |
652 | * @param string $file |
652 | * @return mixed |
653 | * @return mixed |
653 | * @throws OIDplusConfigInitializationException |
654 | * @throws OIDplusConfigInitializationException |
654 | * @throws OIDplusException |
655 | * @throws OIDplusException |
655 | */ |
656 | */ |
656 | private static function getHyperlinkURL(string $file) { |
657 | private static function getHyperlinkURL(string $file) { |
657 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
658 | $file2 = preg_replace('/\.([^.]+)$/', '$'.OIDplus::getCurrentLang().'.\1', $file); |
658 | if (file_exists($file2)) $file = $file2; |
659 | if (file_exists($file2)) $file = $file2; |
659 | 660 | ||
660 | if (substr($file,-4,4) == '.url') { |
661 | if (substr($file,-4,4) == '.url') { |
661 | /* |
662 | /* |
662 | [InternetShortcut] |
663 | [InternetShortcut] |
663 | URL=http://www.example.com/ |
664 | URL=http://www.example.com/ |
664 | */ |
665 | */ |
665 | 666 | ||
666 | $data = @parse_ini_file($file, true); |
667 | $data = @parse_ini_file($file, true); |
667 | if (!$data) { |
668 | if (!$data) { |
668 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
669 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
669 | } |
670 | } |
670 | if (!isset($data['InternetShortcut'])) { |
671 | if (!isset($data['InternetShortcut'])) { |
671 | throw new OIDplusException(_L('Could not find "%1" section at %2','InternetShortcut',$file)); |
672 | throw new OIDplusException(_L('Could not find "%1" section at %2','InternetShortcut',$file)); |
672 | } |
673 | } |
673 | if (!isset($data['InternetShortcut']['URL'])) { |
674 | if (!isset($data['InternetShortcut']['URL'])) { |
674 | throw new OIDplusException(_L('"%1" is missing in %2','URL',$file)); |
675 | throw new OIDplusException(_L('"%1" is missing in %2','URL',$file)); |
675 | } |
676 | } |
676 | return $data['InternetShortcut']['URL']; |
677 | return $data['InternetShortcut']['URL']; |
677 | } else if (substr($file,-5,5) == '.link') { |
678 | } else if (substr($file,-5,5) == '.link') { |
678 | /* |
679 | /* |
679 | [Link] |
680 | [Link] |
680 | Title=Report a bug |
681 | Title=Report a bug |
681 | URL=https://github.com/danielmarschall/oidplus/issues |
682 | URL=https://github.com/danielmarschall/oidplus/issues |
682 | */ |
683 | */ |
683 | 684 | ||
684 | $data = @parse_ini_file($file, true); |
685 | $data = @parse_ini_file($file, true); |
685 | if (!$data) { |
686 | if (!$data) { |
686 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
687 | throw new OIDplusException(_L('File %1 has an invalid INI format!',$file)); |
687 | } |
688 | } |
688 | if (!isset($data['Link'])) { |
689 | if (!isset($data['Link'])) { |
689 | throw new OIDplusException(_L('Could not find "%1" section at %2','Link',$file)); |
690 | throw new OIDplusException(_L('Could not find "%1" section at %2','Link',$file)); |
690 | } |
691 | } |
691 | if (!isset($data['Link']['URL'])) { |
692 | if (!isset($data['Link']['URL'])) { |
692 | throw new OIDplusException(_L('"%1" is missing in %2','URL',$file)); |
693 | throw new OIDplusException(_L('"%1" is missing in %2','URL',$file)); |
693 | } |
694 | } |
694 | return $data['Link']['URL']; |
695 | return $data['Link']['URL']; |
695 | } else { |
696 | } else { |
696 | throw new OIDplusException(_L('Unexpected file extension for file %1',$file)); |
697 | throw new OIDplusException(_L('Unexpected file extension for file %1',$file)); |
697 | } |
698 | } |
698 | 699 | ||
699 | } |
700 | } |
700 | 701 | ||
701 | /** |
702 | /** |
702 | * @param string $dir |
703 | * @param string $dir |
703 | * @return mixed|string |
704 | * @return mixed|string |
704 | * @throws OIDplusConfigInitializationException |
705 | * @throws OIDplusConfigInitializationException |
705 | * @throws OIDplusException |
706 | * @throws OIDplusException |
706 | */ |
707 | */ |
707 | private static function getFolderTitle(string $dir) { |
708 | private static function getFolderTitle(string $dir) { |
708 | $data = @parse_ini_file("$dir/folder\$".OIDplus::getCurrentLang().".ini", true); |
709 | $data = @parse_ini_file("$dir/folder\$".OIDplus::getCurrentLang().".ini", true); |
709 | if ($data && isset($data['Folder']) && isset($data['Folder']['Title'])) { |
710 | if ($data && isset($data['Folder']) && isset($data['Folder']['Title'])) { |
710 | return $data['Folder']['Title']; |
711 | return $data['Folder']['Title']; |
711 | } |
712 | } |
712 | 713 | ||
713 | $data = @parse_ini_file("$dir/folder.ini", true); |
714 | $data = @parse_ini_file("$dir/folder.ini", true); |
714 | if ($data && isset($data['Folder']) && isset($data['Folder']['Title'])) { |
715 | if ($data && isset($data['Folder']) && isset($data['Folder']['Title'])) { |
715 | return $data['Folder']['Title']; |
716 | return $data['Folder']['Title']; |
716 | } |
717 | } |
717 | 718 | ||
718 | return basename($dir); |
719 | return basename($dir); |
719 | } |
720 | } |
720 | } |
721 | } |
721 | 722 |