Rev 899 | Rev 1086 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 899 | Rev 1050 | ||
---|---|---|---|
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | /* |
3 | /* |
4 | * OIDplus 2.0 |
4 | * OIDplus 2.0 |
5 | * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft |
5 | * Copyright 2019 - 2021 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 | if (!defined('INSIDE_OIDPLUS')) die(); |
20 | namespace ViaThinkSoft\OIDplus; |
21 | 21 | ||
22 | class OIDplusPagePublicAttachments extends OIDplusPagePluginPublic { |
22 | class OIDplusPagePublicAttachments extends OIDplusPagePluginPublic { |
23 | 23 | ||
24 | const DIR_UNLOCK_FILE = 'oidplus_upload.dir'; |
24 | const DIR_UNLOCK_FILE = 'oidplus_upload.dir'; |
25 | 25 | ||
26 | private static function checkUploadDir($dir) { |
26 | private static function checkUploadDir($dir) { |
27 | if (!is_dir($dir)) { |
27 | if (!is_dir($dir)) { |
28 | throw new OIDplusException(_L('The attachment directory "%1" is not existing.', $dir)); |
28 | throw new OIDplusException(_L('The attachment directory "%1" is not existing.', $dir)); |
29 | } |
29 | } |
30 | 30 | ||
31 | $realdir = realpath($dir); |
31 | $realdir = realpath($dir); |
32 | if ($realdir === false) { |
32 | if ($realdir === false) { |
33 | throw new OIDplusException(_L('The attachment directory "%1" cannot be resolved (realpath).', $dir)); |
33 | throw new OIDplusException(_L('The attachment directory "%1" cannot be resolved (realpath).', $dir)); |
34 | } |
34 | } |
35 | 35 | ||
36 | $unlock_file = $realdir . DIRECTORY_SEPARATOR . self::DIR_UNLOCK_FILE; |
36 | $unlock_file = $realdir . DIRECTORY_SEPARATOR . self::DIR_UNLOCK_FILE; |
37 | if (!file_exists($unlock_file)) { |
37 | if (!file_exists($unlock_file)) { |
38 | throw new OIDplusException(_L('Unlock file "%1" is not existing in attachment directory "%2".', self::DIR_UNLOCK_FILE, $dir)); |
38 | throw new OIDplusException(_L('Unlock file "%1" is not existing in attachment directory "%2".', self::DIR_UNLOCK_FILE, $dir)); |
39 | } |
39 | } |
40 | 40 | ||
41 | if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { |
41 | if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { |
42 | // Linux check 1: Check for critical directories |
42 | // Linux check 1: Check for critical directories |
43 | if (self::isCriticalLinuxDirectory($realdir)) { |
43 | if (self::isCriticalLinuxDirectory($realdir)) { |
44 | throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!')); |
44 | throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!')); |
45 | } |
45 | } |
46 | 46 | ||
47 | // Linux check 2: Check file owner |
47 | // Linux check 2: Check file owner |
48 | $file_owner_a = fileowner(OIDplus::localpath().'index.php'); |
48 | $file_owner_a = fileowner(OIDplus::localpath().'index.php'); |
49 | if ($file_owner_a === false) { |
49 | if ($file_owner_a === false) { |
50 | $file_owner_a = -1; |
50 | $file_owner_a = -1; |
51 | $file_owner_a_name = '???'; |
51 | $file_owner_a_name = '???'; |
52 | } else { |
52 | } else { |
53 | $tmp = function_exists('posix_getpwuid') ? posix_getpwuid($file_owner_a) : false; |
53 | $tmp = function_exists('posix_getpwuid') ? posix_getpwuid($file_owner_a) : false; |
54 | $file_owner_a_name = $tmp !== false ? $tmp['name'] : 'UID '.$file_owner_a; |
54 | $file_owner_a_name = $tmp !== false ? $tmp['name'] : 'UID '.$file_owner_a; |
55 | } |
55 | } |
56 | 56 | ||
57 | $file_owner_b = fileowner($unlock_file); |
57 | $file_owner_b = fileowner($unlock_file); |
58 | if ($file_owner_b === false) { |
58 | if ($file_owner_b === false) { |
59 | $file_owner_b = -1; |
59 | $file_owner_b = -1; |
60 | $file_owner_b_name = '???'; |
60 | $file_owner_b_name = '???'; |
61 | } else { |
61 | } else { |
62 | $tmp = function_exists('posix_getpwuid') ? posix_getpwuid($file_owner_b) : false; |
62 | $tmp = function_exists('posix_getpwuid') ? posix_getpwuid($file_owner_b) : false; |
63 | $file_owner_b_name = $tmp !== false ? $tmp['name'] : 'UID '.$file_owner_b; |
63 | $file_owner_b_name = $tmp !== false ? $tmp['name'] : 'UID '.$file_owner_b; |
64 | } |
64 | } |
65 | 65 | ||
66 | if ($file_owner_a != $file_owner_b) { |
66 | if ($file_owner_a != $file_owner_b) { |
67 | throw new OIDplusException(_L('Owner of unlock file "%1" is wrong. It is "%2", but it should be "%3".', $unlock_file, $file_owner_b_name, $file_owner_a_name)); |
67 | throw new OIDplusException(_L('Owner of unlock file "%1" is wrong. It is "%2", but it should be "%3".', $unlock_file, $file_owner_b_name, $file_owner_a_name)); |
68 | } |
68 | } |
69 | } else { |
69 | } else { |
70 | // Windows check 1: Check for critical directories |
70 | // Windows check 1: Check for critical directories |
71 | if (self::isCriticalWindowsDirectory($realdir)) { |
71 | if (self::isCriticalWindowsDirectory($realdir)) { |
72 | throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!')); |
72 | throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!')); |
73 | } |
73 | } |
74 | 74 | ||
75 | // Note: We will not query the file owner in Windows systems. |
75 | // Note: We will not query the file owner in Windows systems. |
76 | // It would be possible, however, on Windows systems, the file |
76 | // It would be possible, however, on Windows systems, the file |
77 | // ownership is rather hidden to the user and the user needs |
77 | // ownership is rather hidden to the user and the user needs |
78 | // to go into several menus and windows in order to see/change |
78 | // to go into several menus and windows in order to see/change |
79 | // the owner. We don't want to over-complicate it to the Windows admin. |
79 | // the owner. We don't want to over-complicate it to the Windows admin. |
80 | } |
80 | } |
81 | } |
81 | } |
82 | 82 | ||
83 | private static function isCriticalWindowsDirectory($dir) { |
83 | private static function isCriticalWindowsDirectory($dir) { |
84 | $dir .= '\\'; |
84 | $dir .= '\\'; |
85 | $windir = isset($_SERVER['SystemRoot']) ? $_SERVER['SystemRoot'].'\\' : 'C:\\Windows\\'; |
85 | $windir = isset($_SERVER['SystemRoot']) ? $_SERVER['SystemRoot'].'\\' : 'C:\\Windows\\'; |
86 | if (stripos($dir,$windir) === 0) return true; |
86 | if (stripos($dir,$windir) === 0) return true; |
87 | return false; |
87 | return false; |
88 | } |
88 | } |
89 | 89 | ||
90 | private static function isCriticalLinuxDirectory($dir) { |
90 | private static function isCriticalLinuxDirectory($dir) { |
91 | if ($dir == '/') return true; |
91 | if ($dir == '/') return true; |
92 | $dir .= '/'; |
92 | $dir .= '/'; |
93 | if (strpos($dir,'/bin/') === 0) return true; |
93 | if (strpos($dir,'/bin/') === 0) return true; |
94 | if (strpos($dir,'/boot/') === 0) return true; |
94 | if (strpos($dir,'/boot/') === 0) return true; |
95 | if (strpos($dir,'/dev/') === 0) return true; |
95 | if (strpos($dir,'/dev/') === 0) return true; |
96 | if (strpos($dir,'/etc/') === 0) return true; |
96 | if (strpos($dir,'/etc/') === 0) return true; |
97 | if (strpos($dir,'/lib') === 0) return true; |
97 | if (strpos($dir,'/lib') === 0) return true; |
98 | if (strpos($dir,'/opt/') === 0) return true; |
98 | if (strpos($dir,'/opt/') === 0) return true; |
99 | if (strpos($dir,'/proc/') === 0) return true; |
99 | if (strpos($dir,'/proc/') === 0) return true; |
100 | if (strpos($dir,'/root/') === 0) return true; |
100 | if (strpos($dir,'/root/') === 0) return true; |
101 | if (strpos($dir,'/run/') === 0) return true; |
101 | if (strpos($dir,'/run/') === 0) return true; |
102 | if (strpos($dir,'/sbin/') === 0) return true; |
102 | if (strpos($dir,'/sbin/') === 0) return true; |
103 | if (strpos($dir,'/sys/') === 0) return true; |
103 | if (strpos($dir,'/sys/') === 0) return true; |
104 | if (strpos($dir,'/tmp/') === 0) return true; |
104 | if (strpos($dir,'/tmp/') === 0) return true; |
105 | if (strpos($dir,'/usr/bin/') === 0) return true; |
105 | if (strpos($dir,'/usr/bin/') === 0) return true; |
106 | if (strpos($dir,'/usr/include/') === 0) return true; |
106 | if (strpos($dir,'/usr/include/') === 0) return true; |
107 | if (strpos($dir,'/usr/lib') === 0) return true; |
107 | if (strpos($dir,'/usr/lib') === 0) return true; |
108 | if (strpos($dir,'/usr/sbin/') === 0) return true; |
108 | if (strpos($dir,'/usr/sbin/') === 0) return true; |
109 | if (strpos($dir,'/usr/src/') === 0) return true; |
109 | if (strpos($dir,'/usr/src/') === 0) return true; |
110 | if (strpos($dir,'/var/cache/') === 0) return true; |
110 | if (strpos($dir,'/var/cache/') === 0) return true; |
111 | if (strpos($dir,'/var/lib') === 0) return true; |
111 | if (strpos($dir,'/var/lib') === 0) return true; |
112 | if (strpos($dir,'/var/lock/') === 0) return true; |
112 | if (strpos($dir,'/var/lock/') === 0) return true; |
113 | if (strpos($dir,'/var/log/') === 0) return true; |
113 | if (strpos($dir,'/var/log/') === 0) return true; |
114 | if (strpos($dir,'/var/mail/') === 0) return true; |
114 | if (strpos($dir,'/var/mail/') === 0) return true; |
115 | if (strpos($dir,'/var/opt/') === 0) return true; |
115 | if (strpos($dir,'/var/opt/') === 0) return true; |
116 | if (strpos($dir,'/var/run/') === 0) return true; |
116 | if (strpos($dir,'/var/run/') === 0) return true; |
117 | if (strpos($dir,'/var/spool/') === 0) return true; |
117 | if (strpos($dir,'/var/spool/') === 0) return true; |
118 | if (strpos($dir,'/var/tmp/') === 0) return true; |
118 | if (strpos($dir,'/var/tmp/') === 0) return true; |
119 | return false; |
119 | return false; |
120 | } |
120 | } |
121 | 121 | ||
122 | public static function getUploadDir($id=null) { |
122 | public static function getUploadDir($id=null) { |
123 | // Get base path |
123 | // Get base path |
124 | $cfg = OIDplus::config()->getValue('attachment_upload_dir', ''); |
124 | $cfg = OIDplus::config()->getValue('attachment_upload_dir', ''); |
125 | $cfg = trim($cfg); |
125 | $cfg = trim($cfg); |
126 | if ($cfg === '') { |
126 | if ($cfg === '') { |
127 | $basepath = OIDplus::localpath() . 'userdata' . DIRECTORY_SEPARATOR . 'attachments'; |
127 | $basepath = OIDplus::localpath() . 'userdata' . DIRECTORY_SEPARATOR . 'attachments'; |
128 | } else { |
128 | } else { |
129 | $basepath = $cfg; |
129 | $basepath = $cfg; |
130 | } |
130 | } |
131 | 131 | ||
132 | try { |
132 | try { |
133 | self::checkUploadDir($basepath); |
133 | self::checkUploadDir($basepath); |
134 | } catch (Exception $e) { |
134 | } catch (\Exception $e) { |
135 | $error = _L('This functionality is not available due to a misconfiguration'); |
135 | $error = _L('This functionality is not available due to a misconfiguration'); |
136 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
136 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
137 | $error .= ': '.$e->getMessage(); |
137 | $error .= ': '.$e->getMessage(); |
138 | } else { |
138 | } else { |
139 | $error .= '. '._L('Please notify the system administrator. After they log-in, they can see the reason at this place.'); |
139 | $error .= '. '._L('Please notify the system administrator. After they log-in, they can see the reason at this place.'); |
140 | } |
140 | } |
141 | throw new OIDplusException($error); |
141 | throw new OIDplusException($error); |
142 | } |
142 | } |
143 | 143 | ||
144 | // Get object-specific path |
144 | // Get object-specific path |
145 | if (!is_null($id)) { |
145 | if (!is_null($id)) { |
146 | $obj = OIDplusObject::parse($id); |
146 | $obj = OIDplusObject::parse($id); |
147 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
147 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
148 | 148 | ||
149 | $path_v1 = $basepath . DIRECTORY_SEPARATOR . $obj->getLegacyDirectoryName(); |
149 | $path_v1 = $basepath . DIRECTORY_SEPARATOR . $obj->getLegacyDirectoryName(); |
150 | $path_v1_bug = $basepath . $obj->getLegacyDirectoryName(); |
150 | $path_v1_bug = $basepath . $obj->getLegacyDirectoryName(); |
151 | $path_v2 = $basepath . DIRECTORY_SEPARATOR . $obj->getDirectoryName(); |
151 | $path_v2 = $basepath . DIRECTORY_SEPARATOR . $obj->getDirectoryName(); |
152 | 152 | ||
153 | if (is_dir($path_v1)) return $path_v1; // backwards compatibility |
153 | if (is_dir($path_v1)) return $path_v1; // backwards compatibility |
154 | if (is_dir($path_v1_bug)) return $path_v1_bug; // backwards compatibility |
154 | if (is_dir($path_v1_bug)) return $path_v1_bug; // backwards compatibility |
155 | return $path_v2; |
155 | return $path_v2; |
156 | } else { |
156 | } else { |
157 | return $basepath; |
157 | return $basepath; |
158 | } |
158 | } |
159 | } |
159 | } |
160 | 160 | ||
161 | private function raMayDelete() { |
161 | private function raMayDelete() { |
162 | return OIDplus::config()->getValue('attachments_allow_ra_delete', 0); |
162 | return OIDplus::config()->getValue('attachments_allow_ra_delete', 0); |
163 | } |
163 | } |
164 | 164 | ||
165 | private function raMayUpload() { |
165 | private function raMayUpload() { |
166 | return OIDplus::config()->getValue('attachments_allow_ra_upload', 0); |
166 | return OIDplus::config()->getValue('attachments_allow_ra_upload', 0); |
167 | } |
167 | } |
168 | 168 | ||
169 | public function action($actionID, $params) { |
169 | public function action($actionID, $params) { |
170 | 170 | ||
171 | if ($actionID == 'deleteAttachment') { |
171 | if ($actionID == 'deleteAttachment') { |
172 | _CheckParamExists($params, 'id'); |
172 | _CheckParamExists($params, 'id'); |
173 | $id = $params['id']; |
173 | $id = $params['id']; |
174 | $obj = OIDplusObject::parse($id); |
174 | $obj = OIDplusObject::parse($id); |
175 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
175 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
176 | if (!$obj->userHasWriteRights()) throw new OIDplusException(_L('Authentication error. Please log in as admin, or as the RA of "%1" to upload an attachment.',$id)); |
176 | if (!$obj->userHasWriteRights()) throw new OIDplusException(_L('Authentication error. Please log in as admin, or as the RA of "%1" to upload an attachment.',$id)); |
177 | 177 | ||
178 | if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayDelete()) { |
178 | if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayDelete()) { |
179 | throw new OIDplusException(_L('The administrator has disabled deleting attachments by RAs.')); |
179 | throw new OIDplusException(_L('The administrator has disabled deleting attachments by RAs.')); |
180 | } |
180 | } |
181 | 181 | ||
182 | _CheckParamExists($params, 'filename'); |
182 | _CheckParamExists($params, 'filename'); |
183 | $req_filename = $params['filename']; |
183 | $req_filename = $params['filename']; |
184 | if (strpos($req_filename, '/') !== false) throw new OIDplusException(_L('Illegal file name')); |
184 | if (strpos($req_filename, '/') !== false) throw new OIDplusException(_L('Illegal file name')); |
185 | if (strpos($req_filename, '\\') !== false) throw new OIDplusException(_L('Illegal file name')); |
185 | if (strpos($req_filename, '\\') !== false) throw new OIDplusException(_L('Illegal file name')); |
186 | if (strpos($req_filename, '..') !== false) throw new OIDplusException(_L('Illegal file name')); |
186 | if (strpos($req_filename, '..') !== false) throw new OIDplusException(_L('Illegal file name')); |
187 | if (strpos($req_filename, chr(0)) !== false) throw new OIDplusException(_L('Illegal file name')); |
187 | if (strpos($req_filename, chr(0)) !== false) throw new OIDplusException(_L('Illegal file name')); |
188 | 188 | ||
189 | $uploaddir = self::getUploadDir($id); |
189 | $uploaddir = self::getUploadDir($id); |
190 | $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename); |
190 | $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename); |
191 | 191 | ||
192 | if (!file_exists($uploadfile)) throw new OIDplusException(_L('File does not exist')); |
192 | if (!file_exists($uploadfile)) throw new OIDplusException(_L('File does not exist')); |
193 | @unlink($uploadfile); |
193 | @unlink($uploadfile); |
194 | if (file_exists($uploadfile)) { |
194 | if (file_exists($uploadfile)) { |
195 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Attachment file '".basename($uploadfile)."' could not be deleted from object '$id' (problem with permissions?)"); |
195 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Attachment file '".basename($uploadfile)."' could not be deleted from object '$id' (problem with permissions?)"); |
196 | $msg = _L('Attachment file "%1" could not be deleted from object "%2" (problem with permissions?)',basename($uploadfile),$id); |
196 | $msg = _L('Attachment file "%1" could not be deleted from object "%2" (problem with permissions?)',basename($uploadfile),$id); |
197 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
197 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
198 | throw new OIDplusException($msg); |
198 | throw new OIDplusException($msg); |
199 | } else { |
199 | } else { |
200 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
200 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
201 | } |
201 | } |
202 | } else { |
202 | } else { |
203 | // If it was the last file, delete the empty directory |
203 | // If it was the last file, delete the empty directory |
204 | $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*'); |
204 | $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*'); |
205 | if (is_array($ary) && (count($ary) == 0)) @rmdir($uploaddir); |
205 | if (is_array($ary) && (count($ary) == 0)) @rmdir($uploaddir); |
206 | } |
206 | } |
207 | 207 | ||
208 | OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Deleted attachment '".basename($uploadfile)."' from object '$id'"); |
208 | OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Deleted attachment '".basename($uploadfile)."' from object '$id'"); |
209 | 209 | ||
210 | return array("status" => 0); |
210 | return array("status" => 0); |
211 | 211 | ||
212 | } else if ($actionID == 'uploadAttachment') { |
212 | } else if ($actionID == 'uploadAttachment') { |
213 | _CheckParamExists($params, 'id'); |
213 | _CheckParamExists($params, 'id'); |
214 | $id = $params['id']; |
214 | $id = $params['id']; |
215 | $obj = OIDplusObject::parse($id); |
215 | $obj = OIDplusObject::parse($id); |
216 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
216 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
217 | if (!$obj->userHasWriteRights()) throw new OIDplusException(_L('Authentication error. Please log in as admin, or as the RA of "%1" to upload an attachment.',$id)); |
217 | if (!$obj->userHasWriteRights()) throw new OIDplusException(_L('Authentication error. Please log in as admin, or as the RA of "%1" to upload an attachment.',$id)); |
218 | 218 | ||
219 | if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayUpload()) { |
219 | if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayUpload()) { |
220 | throw new OIDplusException(_L('The administrator has disabled uploading attachments by RAs.')); |
220 | throw new OIDplusException(_L('The administrator has disabled uploading attachments by RAs.')); |
221 | } |
221 | } |
222 | 222 | ||
223 | if (!isset($_FILES['userfile'])) { |
223 | if (!isset($_FILES['userfile'])) { |
224 | throw new OIDplusException(_L('Please choose a file.')); |
224 | throw new OIDplusException(_L('Please choose a file.')); |
225 | } |
225 | } |
226 | 226 | ||
227 | if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
227 | if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
228 | $fname = basename($_FILES['userfile']['name']); |
228 | $fname = basename($_FILES['userfile']['name']); |
229 | 229 | ||
230 | // 1. If something is on the blacklist, we always block it, even if it is on the whitelist, too |
230 | // 1. If something is on the blacklist, we always block it, even if it is on the whitelist, too |
231 | $banned = explode(',', OIDplus::config()->getValue('attachments_block_extensions', '')); |
231 | $banned = explode(',', OIDplus::config()->getValue('attachments_block_extensions', '')); |
232 | foreach ($banned as $ext) { |
232 | foreach ($banned as $ext) { |
233 | $ext = trim($ext); |
233 | $ext = trim($ext); |
234 | if ($ext == '') continue; |
234 | if ($ext == '') continue; |
235 | if (strtolower(substr($fname, -strlen($ext)-1)) == strtolower('.'.$ext)) { |
235 | if (strtolower(substr($fname, -strlen($ext)-1)) == strtolower('.'.$ext)) { |
236 | throw new OIDplusException(_L('The file extension "%1" is banned by the administrator (it can be uploaded by the administrator though)',$ext)); |
236 | throw new OIDplusException(_L('The file extension "%1" is banned by the administrator (it can be uploaded by the administrator though)',$ext)); |
237 | } |
237 | } |
238 | } |
238 | } |
239 | 239 | ||
240 | // 2. Something on the whitelist is always OK |
240 | // 2. Something on the whitelist is always OK |
241 | $allowed = explode(',', OIDplus::config()->getValue('attachments_allow_extensions', '')); |
241 | $allowed = explode(',', OIDplus::config()->getValue('attachments_allow_extensions', '')); |
242 | $is_whitelisted = false; |
242 | $is_whitelisted = false; |
243 | foreach ($allowed as $ext) { |
243 | foreach ($allowed as $ext) { |
244 | $ext = trim($ext); |
244 | $ext = trim($ext); |
245 | if ($ext == '') continue; |
245 | if ($ext == '') continue; |
246 | if (strtolower(substr($fname, -strlen($ext)-1)) == strtolower('.'.$ext)) { |
246 | if (strtolower(substr($fname, -strlen($ext)-1)) == strtolower('.'.$ext)) { |
247 | $is_whitelisted = true; |
247 | $is_whitelisted = true; |
248 | break; |
248 | break; |
249 | } |
249 | } |
250 | } |
250 | } |
251 | 251 | ||
252 | // 3. For everything that is neither whitelisted, nor blacklisted, the admin can decide if these grey zone is allowed or blocked |
252 | // 3. For everything that is neither whitelisted, nor blacklisted, the admin can decide if these grey zone is allowed or blocked |
253 | if (!$is_whitelisted) { |
253 | if (!$is_whitelisted) { |
254 | if (!OIDplus::config()->getValue('attachments_allow_grey_extensions', '1')) { |
254 | if (!OIDplus::config()->getValue('attachments_allow_grey_extensions', '1')) { |
255 | $tmp = explode('.', $fname); |
255 | $tmp = explode('.', $fname); |
256 | $ext = array_pop($tmp); |
256 | $ext = array_pop($tmp); |
257 | throw new OIDplusException(_L('The file extension "%1" is not on the whitelist (it can be uploaded by the administrator though)',$ext)); |
257 | throw new OIDplusException(_L('The file extension "%1" is not on the whitelist (it can be uploaded by the administrator though)',$ext)); |
258 | } |
258 | } |
259 | } |
259 | } |
260 | } |
260 | } |
261 | 261 | ||
262 | $req_filename = $_FILES['userfile']['name']; |
262 | $req_filename = $_FILES['userfile']['name']; |
263 | if (strpos($req_filename, '/') !== false) throw new OIDplusException(_L('Illegal file name')); |
263 | if (strpos($req_filename, '/') !== false) throw new OIDplusException(_L('Illegal file name')); |
264 | if (strpos($req_filename, '\\') !== false) throw new OIDplusException(_L('Illegal file name')); |
264 | if (strpos($req_filename, '\\') !== false) throw new OIDplusException(_L('Illegal file name')); |
265 | if (strpos($req_filename, '..') !== false) throw new OIDplusException(_L('Illegal file name')); |
265 | if (strpos($req_filename, '..') !== false) throw new OIDplusException(_L('Illegal file name')); |
266 | if (strpos($req_filename, chr(0)) !== false) throw new OIDplusException(_L('Illegal file name')); |
266 | if (strpos($req_filename, chr(0)) !== false) throw new OIDplusException(_L('Illegal file name')); |
267 | 267 | ||
268 | $uploaddir = self::getUploadDir($id); |
268 | $uploaddir = self::getUploadDir($id); |
269 | $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename); |
269 | $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename); |
270 | 270 | ||
271 | if (!is_dir($uploaddir)) { |
271 | if (!is_dir($uploaddir)) { |
272 | @mkdir($uploaddir, 0777, true); |
272 | @mkdir($uploaddir, 0777, true); |
273 | if (!is_dir($uploaddir)) { |
273 | if (!is_dir($uploaddir)) { |
274 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Upload attachment '".basename($uploadfile)."' to object '$id' failed: Cannot create directory '".basename($uploaddir)."' (problem with permissions?)"); |
274 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Upload attachment '".basename($uploadfile)."' to object '$id' failed: Cannot create directory '".basename($uploaddir)."' (problem with permissions?)"); |
275 | $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot create directory "%1" (problem with permissions?)',basename($uploaddir)); |
275 | $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot create directory "%1" (problem with permissions?)',basename($uploaddir)); |
276 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
276 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
277 | throw new OIDplusException($msg); |
277 | throw new OIDplusException($msg); |
278 | } else { |
278 | } else { |
279 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
279 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
280 | } |
280 | } |
281 | } |
281 | } |
282 | } |
282 | } |
283 | 283 | ||
284 | if (!@move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { |
284 | if (!@move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { |
285 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Upload attachment '".basename($uploadfile)."' to object '$id' failed: Cannot move uploaded file into directory (problem with permissions?)"); |
285 | OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Upload attachment '".basename($uploadfile)."' to object '$id' failed: Cannot move uploaded file into directory (problem with permissions?)"); |
286 | $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot move uploaded file into directory (problem with permissions?)'); |
286 | $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot move uploaded file into directory (problem with permissions?)'); |
287 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
287 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
288 | throw new OIDplusException($msg); |
288 | throw new OIDplusException($msg); |
289 | } else { |
289 | } else { |
290 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
290 | throw new OIDplusException($msg.'. '._L('Please contact the system administrator.')); |
291 | } |
291 | } |
292 | } |
292 | } |
293 | 293 | ||
294 | OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Uploaded attachment '".basename($uploadfile)."' to object '$id'"); |
294 | OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Uploaded attachment '".basename($uploadfile)."' to object '$id'"); |
295 | 295 | ||
296 | return array("status" => 0); |
296 | return array("status" => 0); |
297 | } else { |
297 | } else { |
298 | throw new OIDplusException(_L('Unknown action ID')); |
298 | throw new OIDplusException(_L('Unknown action ID')); |
299 | } |
299 | } |
300 | } |
300 | } |
301 | 301 | ||
302 | public function init($html=true) { |
302 | public function init($html=true) { |
303 | OIDplus::config()->prepareConfigKey('attachments_block_extensions', 'Block file name extensions being used in file attachments (comma separated)', 'exe,scr,pif,bat,com,vbs,cmd', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
303 | OIDplus::config()->prepareConfigKey('attachments_block_extensions', 'Block file name extensions being used in file attachments (comma separated)', 'exe,scr,pif,bat,com,vbs,cmd', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
304 | // TODO: check if a blacklist entry is also on the whitelist (which is not allowed) |
304 | // TODO: check if a blacklist entry is also on the whitelist (which is not allowed) |
305 | }); |
305 | }); |
306 | OIDplus::config()->prepareConfigKey('attachments_allow_extensions', 'Allow (whitelist) file name extensions being used in file attachments (comma separated)', '', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
306 | OIDplus::config()->prepareConfigKey('attachments_allow_extensions', 'Allow (whitelist) file name extensions being used in file attachments (comma separated)', '', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
307 | // TODO: check if a whitelist entry is also on the blacklist (which is not allowed) |
307 | // TODO: check if a whitelist entry is also on the blacklist (which is not allowed) |
308 | }); |
308 | }); |
309 | OIDplus::config()->prepareConfigKey('attachments_allow_grey_extensions', 'Should file-extensions which are neither be on the whitelist, nor be at the blacklist, be allowed? (1=Yes, 0=No)', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
309 | OIDplus::config()->prepareConfigKey('attachments_allow_grey_extensions', 'Should file-extensions which are neither be on the whitelist, nor be at the blacklist, be allowed? (1=Yes, 0=No)', '1', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
310 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
310 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
311 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
311 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
312 | } |
312 | } |
313 | }); |
313 | }); |
314 | OIDplus::config()->prepareConfigKey('attachments_allow_ra_delete', 'Allow that RAs delete file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
314 | OIDplus::config()->prepareConfigKey('attachments_allow_ra_delete', 'Allow that RAs delete file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
315 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
315 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
316 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
316 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
317 | } |
317 | } |
318 | }); |
318 | }); |
319 | OIDplus::config()->prepareConfigKey('attachments_allow_ra_upload', 'Allow that RAs upload file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
319 | OIDplus::config()->prepareConfigKey('attachments_allow_ra_upload', 'Allow that RAs upload file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
320 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
320 | if (!is_numeric($value) || ($value < 0) || ($value > 1)) { |
321 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
321 | throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).')); |
322 | } |
322 | } |
323 | }); |
323 | }); |
324 | 324 | ||
325 | $info_txt = 'Alternative directory for attachments. It must contain a file named "'; |
325 | $info_txt = 'Alternative directory for attachments. It must contain a file named "'; |
326 | $info_txt .= self::DIR_UNLOCK_FILE; |
326 | $info_txt .= self::DIR_UNLOCK_FILE; |
327 | $info_txt .= '"'; |
327 | $info_txt .= '"'; |
328 | if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { |
328 | if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { |
329 | $info_txt .= ' with the same owner as index.php'; |
329 | $info_txt .= ' with the same owner as index.php'; |
330 | } |
330 | } |
331 | $info_txt .= '. If this setting is empty, then the userdata directory is used.'; |
331 | $info_txt .= '. If this setting is empty, then the userdata directory is used.'; |
332 | OIDplus::config()->prepareConfigKey('attachment_upload_dir', $info_txt, '', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
332 | OIDplus::config()->prepareConfigKey('attachment_upload_dir', $info_txt, '', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
333 | if (trim($value) !== '') { |
333 | if (trim($value) !== '') { |
334 | self::checkUploadDir($value); |
334 | self::checkUploadDir($value); |
335 | } |
335 | } |
336 | }); |
336 | }); |
337 | } |
337 | } |
338 | 338 | ||
339 | public function gui($id, &$out, &$handled) { |
339 | public function gui($id, &$out, &$handled) { |
340 | // Nothing |
340 | // Nothing |
341 | } |
341 | } |
342 | 342 | ||
343 | public function publicSitemap(&$out) { |
343 | public function publicSitemap(&$out) { |
344 | // Nothing |
344 | // Nothing |
345 | } |
345 | } |
346 | 346 | ||
347 | public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') { |
347 | public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') { |
348 | return false; |
348 | return false; |
349 | } |
349 | } |
350 | 350 | ||
351 | private static function convert_filesize($bytes, $decimals = 2){ |
351 | private static function convert_filesize($bytes, $decimals = 2){ |
352 | $size = array(_L('Bytes'),_L('KiB'),_L('MiB'),_L('GiB'),_L('TiB'),_L('PiB'),_L('EiB'),_L('ZiB'),_L('YiB')); |
352 | $size = array(_L('Bytes'),_L('KiB'),_L('MiB'),_L('GiB'),_L('TiB'),_L('PiB'),_L('EiB'),_L('ZiB'),_L('YiB')); |
353 | $factor = floor((strlen($bytes) - 1) / 3); |
353 | $factor = floor((strlen($bytes) - 1) / 3); |
354 | return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor]; |
354 | return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor]; |
355 | } |
355 | } |
356 | 356 | ||
357 | public function implementsFeature($id) { |
357 | public function implementsFeature($id) { |
358 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.2') return true; // modifyContent |
358 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.2') return true; // modifyContent |
359 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.3') return true; // beforeObject*, afterObject* |
359 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.3') return true; // beforeObject*, afterObject* |
360 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.4') return true; // whois*Attributes |
360 | if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.4') return true; // whois*Attributes |
361 | return false; |
361 | return false; |
362 | } |
362 | } |
363 | 363 | ||
364 | public function modifyContent($id, &$title, &$icon, &$text) { |
364 | public function modifyContent($id, &$title, &$icon, &$text) { |
365 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.2 |
365 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.2 |
366 | 366 | ||
367 | $output = ''; |
367 | $output = ''; |
368 | $doshow = false; |
368 | $doshow = false; |
369 | 369 | ||
370 | try { |
370 | try { |
371 | $upload_dir = self::getUploadDir($id); |
371 | $upload_dir = self::getUploadDir($id); |
372 | $files = @glob($upload_dir . DIRECTORY_SEPARATOR . '*'); |
372 | $files = @glob($upload_dir . DIRECTORY_SEPARATOR . '*'); |
373 | $found_files = false; |
373 | $found_files = false; |
374 | 374 | ||
375 | $obj = OIDplusObject::parse($id); |
375 | $obj = OIDplusObject::parse($id); |
376 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
376 | if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id)); |
377 | $can_upload = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayUpload() && $obj->userHasWriteRights()); |
377 | $can_upload = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayUpload() && $obj->userHasWriteRights()); |
378 | $can_delete = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayDelete() && $obj->userHasWriteRights()); |
378 | $can_delete = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayDelete() && $obj->userHasWriteRights()); |
379 | 379 | ||
380 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
380 | if (OIDplus::authUtils()->isAdminLoggedIn()) { |
381 | $output .= '<p>'._L('Admin info: The directory is %1','<b>'.htmlentities($upload_dir).'</b>').'</p>'; |
381 | $output .= '<p>'._L('Admin info: The directory is %1','<b>'.htmlentities($upload_dir).'</b>').'</p>'; |
382 | $doshow = true; |
382 | $doshow = true; |
383 | } |
383 | } |
384 | 384 | ||
385 | $output .= '<div id="fileattachments_table" class="table-responsive">'; |
385 | $output .= '<div id="fileattachments_table" class="table-responsive">'; |
386 | $output .= '<table class="table table-bordered table-striped">'; |
386 | $output .= '<table class="table table-bordered table-striped">'; |
387 | $output .= '<tr>'; |
387 | $output .= '<tr>'; |
388 | $output .= '<th>'._L('Filename').'</th>'; |
388 | $output .= '<th>'._L('Filename').'</th>'; |
389 | $output .= '<th>'._L('Size').'</th>'; |
389 | $output .= '<th>'._L('Size').'</th>'; |
390 | $output .= '<th>'._L('File type').'</th>'; |
390 | $output .= '<th>'._L('File type').'</th>'; |
391 | $output .= '<th>'._L('Download').'</th>'; |
391 | $output .= '<th>'._L('Download').'</th>'; |
392 | if ($can_delete) $output .= '<th>'._L('Delete').'</th>'; |
392 | if ($can_delete) $output .= '<th>'._L('Delete').'</th>'; |
393 | $output .= '</tr>'; |
393 | $output .= '</tr>'; |
394 | if ($files) foreach ($files as $file) { |
394 | if ($files) foreach ($files as $file) { |
395 | if (is_dir($file)) continue; |
395 | if (is_dir($file)) continue; |
396 | 396 | ||
397 | $output .= '<tr>'; |
397 | $output .= '<tr>'; |
398 | $output .= '<td>'.htmlentities(basename($file)).'</td>'; |
398 | $output .= '<td>'.htmlentities(basename($file)).'</td>'; |
399 | $output .= '<td>'.htmlentities(self::convert_filesize(filesize($file), 0)).'</td>'; |
399 | $output .= '<td>'.htmlentities(self::convert_filesize(filesize($file), 0)).'</td>'; |
400 | $lookup_files = array( |
400 | $lookup_files = array( |
401 | OIDplus::localpath().'userdata/attachments/filetypes$'.OIDplus::getCurrentLang().'.conf', |
401 | OIDplus::localpath().'userdata/attachments/filetypes$'.OIDplus::getCurrentLang().'.conf', |
402 | OIDplus::localpath().'userdata/attachments/filetypes.conf', |
402 | OIDplus::localpath().'userdata/attachments/filetypes.conf', |
403 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.local', // not recommended |
403 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.local', // not recommended |
404 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.local', // not recommended |
404 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.local', // not recommended |
405 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.conf', |
405 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.conf', |
406 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.conf' |
406 | OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.conf' |
407 | ); |
407 | ); |
408 | $output .= '<td>'.htmlentities(VtsFileTypeDetect::getDescription($file, $lookup_files)).'</td>'; |
408 | $output .= '<td>'.htmlentities(\VtsFileTypeDetect::getDescription($file, $lookup_files)).'</td>'; |
409 | 409 | ||
410 | $output .= ' <td><button type="button" name="download_'.md5($file).'" id="download_'.md5($file).'" class="btn btn-success btn-xs download" onclick="OIDplusPagePublicAttachments.downloadAttachment('.js_escape(OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE)).', current_node,'.js_escape(basename($file)).')">'._L('Download').'</button></td>'; |
410 | $output .= ' <td><button type="button" name="download_'.md5($file).'" id="download_'.md5($file).'" class="btn btn-success btn-xs download" onclick="OIDplusPagePublicAttachments.downloadAttachment('.js_escape(OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE)).', current_node,'.js_escape(basename($file)).')">'._L('Download').'</button></td>'; |
411 | if ($can_delete) { |
411 | if ($can_delete) { |
412 | $output .= ' <td><button type="button" name="delete_'.md5($file).'" id="delete_'.md5($file).'" class="btn btn-danger btn-xs delete" onclick="OIDplusPagePublicAttachments.deleteAttachment(current_node,'.js_escape(basename($file)).')">'._L('Delete').'</button></td>'; |
412 | $output .= ' <td><button type="button" name="delete_'.md5($file).'" id="delete_'.md5($file).'" class="btn btn-danger btn-xs delete" onclick="OIDplusPagePublicAttachments.deleteAttachment(current_node,'.js_escape(basename($file)).')">'._L('Delete').'</button></td>'; |
413 | } |
413 | } |
414 | 414 | ||
415 | $output .= '</tr>'; |
415 | $output .= '</tr>'; |
416 | $doshow = true; |
416 | $doshow = true; |
417 | $found_files = true; |
417 | $found_files = true; |
418 | } |
418 | } |
419 | 419 | ||
420 | if (!$found_files) $output .= '<tr><td colspan="'.($can_delete ? 5 : 4).'"><i>'._L('No attachments').'</i></td></tr>'; |
420 | if (!$found_files) $output .= '<tr><td colspan="'.($can_delete ? 5 : 4).'"><i>'._L('No attachments').'</i></td></tr>'; |
421 | 421 | ||
422 | $output .= '</table></div>'; |
422 | $output .= '</table></div>'; |
423 | 423 | ||
424 | if ($can_upload) { |
424 | if ($can_upload) { |
425 | $output .= '<form action="javascript:void(0);" onsubmit="return OIDplusPagePublicAttachments.uploadAttachmentOnSubmit(this);" enctype="multipart/form-data" id="uploadAttachmentForm">'; |
425 | $output .= '<form action="javascript:void(0);" onsubmit="return OIDplusPagePublicAttachments.uploadAttachmentOnSubmit(this);" enctype="multipart/form-data" id="uploadAttachmentForm">'; |
426 | $output .= '<input type="hidden" name="id" value="'.htmlentities($id).'">'; |
426 | $output .= '<input type="hidden" name="id" value="'.htmlentities($id).'">'; |
427 | $output .= '<div>'._L('Add a file attachment').':<input type="file" name="userfile" value="" id="fileAttachment">'; |
427 | $output .= '<div>'._L('Add a file attachment').':<input type="file" name="userfile" value="" id="fileAttachment">'; |
428 | $output .= '<br><input type="submit" value="'._L('Upload').'"></div>'; |
428 | $output .= '<br><input type="submit" value="'._L('Upload').'"></div>'; |
429 | $output .= '</form>'; |
429 | $output .= '</form>'; |
430 | $doshow = true; |
430 | $doshow = true; |
431 | } |
431 | } |
432 | } catch (Exception $e) { |
432 | } catch (\Exception $e) { |
433 | $doshow = true; |
433 | $doshow = true; |
434 | $output = '<p>'.$e->getMessage().'</p>'; |
434 | $output = '<p>'.$e->getMessage().'</p>'; |
435 | } |
435 | } |
436 | 436 | ||
437 | $output = '<h2>'._L('File attachments').'</h2>' . |
437 | $output = '<h2>'._L('File attachments').'</h2>' . |
438 | '<div class="container box">' . |
438 | '<div class="container box">' . |
439 | $output . |
439 | $output . |
440 | '</div>'; |
440 | '</div>'; |
441 | if ($doshow) $text .= $output; |
441 | if ($doshow) $text .= $output; |
442 | } |
442 | } |
443 | 443 | ||
444 | public function beforeObjectDelete($id) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
444 | public function beforeObjectDelete($id) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
445 | public function afterObjectDelete($id) { |
445 | public function afterObjectDelete($id) { |
446 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
446 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
447 | // Delete the attachment folder including all files in it (note: Subfolders are not possible) |
447 | // Delete the attachment folder including all files in it (note: Subfolders are not possible) |
448 | $uploaddir = self::getUploadDir($id); |
448 | $uploaddir = self::getUploadDir($id); |
449 | if ($uploaddir != '') { |
449 | if ($uploaddir != '') { |
450 | $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*'); |
450 | $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*'); |
451 | if ($ary) foreach ($ary as $a) @unlink($a); |
451 | if ($ary) foreach ($ary as $a) @unlink($a); |
452 | @rmdir($uploaddir); |
452 | @rmdir($uploaddir); |
453 | if (is_dir($uploaddir)) { |
453 | if (is_dir($uploaddir)) { |
454 | OIDplus::logger()->log("[WARN]OID($id)+[WARN]A!", "Attachment directory '$uploaddir' could not be deleted during the deletion of the OID"); |
454 | OIDplus::logger()->log("[WARN]OID($id)+[WARN]A!", "Attachment directory '$uploaddir' could not be deleted during the deletion of the OID"); |
455 | } |
455 | } |
456 | } |
456 | } |
457 | } |
457 | } |
458 | public function beforeObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
458 | public function beforeObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
459 | public function afterObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
459 | public function afterObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
460 | public function beforeObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
460 | public function beforeObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
461 | public function afterObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
461 | public function afterObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
462 | public function beforeObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
462 | public function beforeObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
463 | public function afterObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
463 | public function afterObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3 |
464 | 464 | ||
465 | public function tree_search($request) { |
465 | public function tree_search($request) { |
466 | return false; |
466 | return false; |
467 | } |
467 | } |
468 | 468 | ||
469 | public function whoisObjectAttributes($id, &$out) { |
469 | public function whoisObjectAttributes($id, &$out) { |
470 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.4 |
470 | // Interface 1.3.6.1.4.1.37476.2.5.2.3.4 |
471 | 471 | ||
472 | $xmlns = 'oidplus-attachment-plugin'; |
472 | $xmlns = 'oidplus-attachment-plugin'; |
473 | $xmlschema = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.4.1.95.1'; |
473 | $xmlschema = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.4.1.95.1'; |
474 | $xmlschemauri = OIDplus::webpath(__DIR__.'/attachments.xsd',OIDplus::PATH_ABSOLUTE); |
474 | $xmlschemauri = OIDplus::webpath(__DIR__.'/attachments.xsd',OIDplus::PATH_ABSOLUTE); |
475 | 475 | ||
476 | $files = @glob(self::getUploadDir($id) . DIRECTORY_SEPARATOR . '*'); |
476 | $files = @glob(self::getUploadDir($id) . DIRECTORY_SEPARATOR . '*'); |
477 | if ($files) foreach ($files as $file) { |
477 | if ($files) foreach ($files as $file) { |
478 | $url = OIDplus::webpath(__DIR__,OIDplus::PATH_ABSOLUTE).'download.php?id='.urlencode($id).'&filename='.urlencode(basename($file)); |
478 | $url = OIDplus::webpath(__DIR__,OIDplus::PATH_ABSOLUTE).'download.php?id='.urlencode($id).'&filename='.urlencode(basename($file)); |
479 | 479 | ||
480 | $out[] = array( |
480 | $out[] = array( |
481 | 'xmlns' => $xmlns, |
481 | 'xmlns' => $xmlns, |
482 | 'xmlschema' => $xmlschema, |
482 | 'xmlschema' => $xmlschema, |
483 | 'xmlschemauri' => $xmlschemauri, |
483 | 'xmlschemauri' => $xmlschemauri, |
484 | 'name' => 'attachment-name', |
484 | 'name' => 'attachment-name', |
485 | 'value' => basename($file) |
485 | 'value' => basename($file) |
486 | ); |
486 | ); |
487 | 487 | ||
488 | $out[] = array( |
488 | $out[] = array( |
489 | 'xmlns' => $xmlns, |
489 | 'xmlns' => $xmlns, |
490 | 'xmlschema' => $xmlschema, |
490 | 'xmlschema' => $xmlschema, |
491 | 'xmlschemauri' => $xmlschemauri, |
491 | 'xmlschemauri' => $xmlschemauri, |
492 | 'name' => 'attachment-url', |
492 | 'name' => 'attachment-url', |
493 | 'value' => $url |
493 | 'value' => $url |
494 | ); |
494 | ); |
495 | } |
495 | } |
496 | 496 | ||
497 | } |
497 | } |
498 | public function whoisRaAttributes($email, &$out) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.4 |
498 | public function whoisRaAttributes($email, &$out) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.4 |
499 | } |
499 | } |
500 | 500 |