Subversion Repositories oidplus

Rev

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

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('INSIDE_OIDPLUS')) die();
  21.  
  22. class OIDplusPagePublicAttachments extends OIDplusPagePluginPublic {
  23.  
  24.         const DIR_UNLOCK_FILE = 'oidplus_upload.dir';
  25.  
  26.         private static function checkUploadDir($dir) {
  27.                 if (!is_dir($dir)) {
  28.                         throw new OIDplusException(_L('The attachment directory "%1" is not existing.', $dir));
  29.                 }
  30.  
  31.                 $realdir = realpath($dir);
  32.                 if ($realdir === false) {
  33.                         throw new OIDplusException(_L('The attachment directory "%1" cannot be resolved (realpath).', $dir));
  34.                 }
  35.  
  36.                 $unlock_file = $realdir . DIRECTORY_SEPARATOR . self::DIR_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));
  39.                 }
  40.  
  41.                 if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
  42.                         // Linux check 1: Check for critical directories
  43.                         if (self::isCriticalLinuxDirectory($realdir)) {
  44.                                 throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!'));
  45.                         }
  46.  
  47.                         // Linux check 2: Check file owner
  48.                         $file_owner_a = fileowner(OIDplus::localpath().'index.php');
  49.                         if ($file_owner_a === false) {
  50.                                 $file_owner_a = -1;
  51.                                 $file_owner_a_name = '???';
  52.                         } else {
  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;
  55.                         }
  56.  
  57.                         $file_owner_b = fileowner($unlock_file);
  58.                         if ($file_owner_b === false) {
  59.                                 $file_owner_b = -1;
  60.                                 $file_owner_b_name = '???';
  61.                         } else {
  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;
  64.                         }
  65.  
  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));
  68.                         }
  69.                 } else {
  70.                         // Windows check 1: Check for critical directories
  71.                         if (self::isCriticalWindowsDirectory($realdir)) {
  72.                                 throw new OIDplusException(_L('The attachment directory must not be inside a critical system directory!'));
  73.                         }
  74.  
  75.                         // Note: We will not query the file owner in Windows systems.
  76.                         // It would be possible, however, on Windows systems, the file
  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
  79.                         // the owner. We don't want to over-complicate it to the Windows admin.
  80.                 }
  81.         }
  82.  
  83.         private static function isCriticalWindowsDirectory($dir) {
  84.                 $dir .= '\\';
  85.                 $windir = isset($_SERVER['SystemRoot']) ? $_SERVER['SystemRoot'].'\\' : 'C:\\Windows\\';
  86.                 if (stripos($dir,$windir) === 0) return true;
  87.                 return false;
  88.         }
  89.  
  90.         private static function isCriticalLinuxDirectory($dir) {
  91.                 if ($dir == '/') return true;
  92.                 $dir .= '/';
  93.                 if (strpos($dir,'/bin/') === 0) return true;
  94.                 if (strpos($dir,'/boot/') === 0) return true;
  95.                 if (strpos($dir,'/dev/') === 0) return true;
  96.                 if (strpos($dir,'/etc/') === 0) return true;
  97.                 if (strpos($dir,'/lib') === 0) return true;
  98.                 if (strpos($dir,'/opt/') === 0) return true;
  99.                 if (strpos($dir,'/proc/') === 0) return true;
  100.                 if (strpos($dir,'/root/') === 0) return true;
  101.                 if (strpos($dir,'/run/') === 0) return true;
  102.                 if (strpos($dir,'/sbin/') === 0) return true;
  103.                 if (strpos($dir,'/sys/') === 0) return true;
  104.                 if (strpos($dir,'/tmp/') === 0) return true;
  105.                 if (strpos($dir,'/usr/bin/') === 0) return true;
  106.                 if (strpos($dir,'/usr/include/') === 0) return true;
  107.                 if (strpos($dir,'/usr/lib') === 0) return true;
  108.                 if (strpos($dir,'/usr/sbin/') === 0) return true;
  109.                 if (strpos($dir,'/usr/src/') === 0) return true;
  110.                 if (strpos($dir,'/var/cache/') === 0) return true;
  111.                 if (strpos($dir,'/var/lib') === 0) return true;
  112.                 if (strpos($dir,'/var/lock/') === 0) return true;
  113.                 if (strpos($dir,'/var/log/') === 0) return true;
  114.                 if (strpos($dir,'/var/mail/') === 0) return true;
  115.                 if (strpos($dir,'/var/opt/') === 0) return true;
  116.                 if (strpos($dir,'/var/run/') === 0) return true;
  117.                 if (strpos($dir,'/var/spool/') === 0) return true;
  118.                 if (strpos($dir,'/var/tmp/') === 0) return true;
  119.                 return false;
  120.         }
  121.  
  122.         public static function getUploadDir($id=null) {
  123.                 // Get base path
  124.                 $cfg = OIDplus::config()->getValue('attachment_upload_dir', '');
  125.                 $cfg = trim($cfg);
  126.                 if ($cfg === '') {
  127.                         $basepath = OIDplus::localpath() . 'userdata' . DIRECTORY_SEPARATOR . 'attachments';
  128.                 } else {
  129.                         $basepath = $cfg;
  130.                 }
  131.  
  132.                 try {
  133.                         self::checkUploadDir($basepath);
  134.                 } catch (Exception $e) {
  135.                         $error = _L('This functionality is not available due to a misconfiguration');
  136.                         if (OIDplus::authUtils()->isAdminLoggedIn()) {
  137.                                 $error .= ': '.$e->getMessage();
  138.                         } else {
  139.                                 $error .= '. '._L('Please notify the system administrator. After they log-in, they can see the reason at this place.');
  140.                         }
  141.                         throw new OIDplusException($error);
  142.                 }
  143.  
  144.                 // Get object-specific path
  145.                 if (!is_null($id)) {
  146.                         $obj = OIDplusObject::parse($id);
  147.                         if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id));
  148.  
  149.                         $path_v1 = $basepath . DIRECTORY_SEPARATOR . $obj->getLegacyDirectoryName();
  150.                         $path_v1_bug = $basepath . $obj->getLegacyDirectoryName();
  151.                         $path_v2 = $basepath . DIRECTORY_SEPARATOR . $obj->getDirectoryName();
  152.  
  153.                         if (is_dir($path_v1)) return $path_v1; // backwards compatibility
  154.                         if (is_dir($path_v1_bug)) return $path_v1_bug; // backwards compatibility
  155.                         return $path_v2;
  156.                 } else {
  157.                         return $basepath;
  158.                 }
  159.         }
  160.  
  161.         private function raMayDelete() {
  162.                 return OIDplus::config()->getValue('attachments_allow_ra_delete', 0);
  163.         }
  164.  
  165.         private function raMayUpload() {
  166.                 return OIDplus::config()->getValue('attachments_allow_ra_upload', 0);
  167.         }
  168.  
  169.         public function action($actionID, $params) {
  170.  
  171.                 if ($actionID == 'deleteAttachment') {
  172.                         _CheckParamExists($params, 'id');
  173.                         $id = $params['id'];
  174.                         $obj = OIDplusObject::parse($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));
  177.  
  178.                         if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayDelete()) {
  179.                                 throw new OIDplusException(_L('The administrator has disabled deleting attachments by RAs.'));
  180.                         }
  181.  
  182.                         _CheckParamExists($params, 'filename');
  183.                         $req_filename = $params['filename'];
  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'));
  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'));
  188.  
  189.                         $uploaddir = self::getUploadDir($id);
  190.                         $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename);
  191.  
  192.                         if (!file_exists($uploadfile)) throw new OIDplusException(_L('File does not exist'));
  193.                         @unlink($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?)");
  196.                                 $msg = _L('Attachment file "%1" could not be deleted from object "%2" (problem with permissions?)',basename($uploadfile),$id);
  197.                                 if (OIDplus::authUtils()->isAdminLoggedIn()) {
  198.                                         throw new OIDplusException($msg);
  199.                                 } else {
  200.                                         throw new OIDplusException($msg.'. '._L('Please contact the system administrator.'));
  201.                                 }
  202.                         } else {
  203.                                 // If it was the last file, delete the empty directory
  204.                                 $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*');
  205.                                 if (is_array($ary) && (count($ary) == 0)) @rmdir($uploaddir);
  206.                         }
  207.  
  208.                         OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Deleted attachment '".basename($uploadfile)."' from object '$id'");
  209.  
  210.                         return array("status" => 0);
  211.  
  212.                 } else if ($actionID == 'uploadAttachment') {
  213.                         _CheckParamExists($params, 'id');
  214.                         $id = $params['id'];
  215.                         $obj = OIDplusObject::parse($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));
  218.  
  219.                         if (!OIDplus::authUtils()->isAdminLoggedIn() && !$this->raMayUpload()) {
  220.                                 throw new OIDplusException(_L('The administrator has disabled uploading attachments by RAs.'));
  221.                         }
  222.  
  223.                         if (!isset($_FILES['userfile'])) {
  224.                                 throw new OIDplusException(_L('Please choose a file.'));
  225.                         }
  226.  
  227.                         if (!OIDplus::authUtils()->isAdminLoggedIn()) {
  228.                                 $banned = explode(',', OIDplus::config()->getValue('attachments_block_extensions', ''));
  229.                                 foreach ($banned as $ext) {
  230.                                         $ext = trim($ext);
  231.                                         if ($ext == '') continue;
  232.                                         if (strtolower(substr(basename($_FILES['userfile']['name']), -strlen($ext)-1)) == strtolower('.'.$ext)) {
  233.                                                 throw new OIDplusException(_L('The file extension "%1" is banned by the administrator (it can be uploaded by the administrator though)',$ext));
  234.                                         }
  235.                                 }
  236.                         }
  237.  
  238.                         $req_filename = $_FILES['userfile']['name'];
  239.                         if (strpos($req_filename, '/') !== false) throw new OIDplusException(_L('Illegal file name'));
  240.                         if (strpos($req_filename, '\\') !== false) throw new OIDplusException(_L('Illegal file name'));
  241.                         if (strpos($req_filename, '..') !== false) throw new OIDplusException(_L('Illegal file name'));
  242.                         if (strpos($req_filename, chr(0)) !== false) throw new OIDplusException(_L('Illegal file name'));
  243.  
  244.                         $uploaddir = self::getUploadDir($id);
  245.                         $uploadfile = $uploaddir . DIRECTORY_SEPARATOR . basename($req_filename);
  246.  
  247.                         if (!is_dir($uploaddir)) {
  248.                                 @mkdir($uploaddir, 0777, true);
  249.                                 if (!is_dir($uploaddir)) {
  250.                                         OIDplus::logger()->log("[ERR]OID($id)+[ERR]A!", "Upload attachment '".basename($uploadfile)."' to object '$id' failed: Cannot create directory '".basename($uploaddir)."' (problem with permissions?)");
  251.                                         $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot create directory "%1" (problem with permissions?)',basename($uploaddir));
  252.                                         if (OIDplus::authUtils()->isAdminLoggedIn()) {
  253.                                                 throw new OIDplusException($msg);
  254.                                         } else {
  255.                                                 throw new OIDplusException($msg.'. '._L('Please contact the system administrator.'));
  256.                                         }
  257.                                 }
  258.                         }
  259.  
  260.                         if (!@move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
  261.                                 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?)");
  262.                                 $msg = _L('Upload attachment "%1" to object "%2" failed',basename($uploadfile),$id).': '._L('Cannot move uploaded file into directory (problem with permissions?)');
  263.                                 if (OIDplus::authUtils()->isAdminLoggedIn()) {
  264.                                         throw new OIDplusException($msg);
  265.                                 } else {
  266.                                         throw new OIDplusException($msg.'. '._L('Please contact the system administrator.'));
  267.                                 }
  268.                         }
  269.  
  270.                         OIDplus::logger()->log("[OK]OID($id)+[?INFO/!OK]OIDRA($id)?/[?INFO/!OK]A?", "Uploaded attachment '".basename($uploadfile)."' to object '$id'");
  271.  
  272.                         return array("status" => 0);
  273.                 } else {
  274.                         throw new OIDplusException(_L('Unknown action ID'));
  275.                 }
  276.         }
  277.  
  278.         public function init($html=true) {
  279.                 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) {
  280.                 });
  281.                 OIDplus::config()->prepareConfigKey('attachments_allow_ra_delete', 'Allow that RAs delete file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  282.                         if (!is_numeric($value) || ($value < 0) || ($value > 1)) {
  283.                                 throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).'));
  284.                         }
  285.                 });
  286.                 OIDplus::config()->prepareConfigKey('attachments_allow_ra_upload', 'Allow that RAs upload file attachments? (0=no, 1=yes)', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  287.                         if (!is_numeric($value) || ($value < 0) || ($value > 1)) {
  288.                                 throw new OIDplusException(_L('Please enter a valid value (0=no, 1=yes).'));
  289.                         }
  290.                 });
  291.  
  292.                 $info_txt  = 'Alternative directory for attachments. It must contain a file named "';
  293.                 $info_txt .= self::DIR_UNLOCK_FILE;
  294.                 $info_txt .= '"';
  295.                 if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
  296.                         $info_txt .= ' with the same owner as index.php';
  297.                 }
  298.                 $info_txt .= '. If this setting is empty, then the userdata directory is used.';
  299.                 OIDplus::config()->prepareConfigKey('attachment_upload_dir', $info_txt, '', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  300.                         if (trim($value) !== '') {
  301.                                 self::checkUploadDir($value);
  302.                         }
  303.                 });
  304.         }
  305.  
  306.         public function gui($id, &$out, &$handled) {
  307.                 // Nothing
  308.         }
  309.  
  310.         public function publicSitemap(&$out) {
  311.                 // Nothing
  312.         }
  313.  
  314.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  315.                 return false;
  316.         }
  317.  
  318.         private static function convert_filesize($bytes, $decimals = 2){
  319.                 $size = array(_L('Bytes'),_L('KiB'),_L('MiB'),_L('GiB'),_L('TiB'),_L('PiB'),_L('EiB'),_L('ZiB'),_L('YiB'));
  320.                 $factor = floor((strlen($bytes) - 1) / 3);
  321.                 return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor];
  322.         }
  323.  
  324.         public function implementsFeature($id) {
  325.                 if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.2') return true; // modifyContent
  326.                 if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.3') return true; // beforeObject*, afterObject*
  327.                 if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.4') return true; // whois*Attributes
  328.                 return false;
  329.         }
  330.  
  331.         public function modifyContent($id, &$title, &$icon, &$text) {
  332.                 // Interface 1.3.6.1.4.1.37476.2.5.2.3.2
  333.  
  334.                 $output = '';
  335.                 $doshow = false;
  336.  
  337.                 try {
  338.                         $upload_dir = self::getUploadDir($id);
  339.                         $files = @glob($upload_dir . DIRECTORY_SEPARATOR . '*');
  340.                         $found_files = false;
  341.  
  342.                         $obj = OIDplusObject::parse($id);
  343.                         if ($obj === null) throw new OIDplusException(_L('Invalid object "%1"',$id));
  344.                         $can_upload = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayUpload() && $obj->userHasWriteRights());
  345.                         $can_delete = OIDplus::authUtils()->isAdminLoggedIn() || ($this->raMayDelete() && $obj->userHasWriteRights());
  346.  
  347.                         if (OIDplus::authUtils()->isAdminLoggedIn()) {
  348.                                 $output .= '<p>'._L('Admin info: The directory is %1','<b>'.htmlentities($upload_dir).'</b>').'</p>';
  349.                                 $doshow = true;
  350.                         }
  351.  
  352.                         $output .= '<div id="fileattachments_table" class="table-responsive">';
  353.                         $output .= '<table class="table table-bordered table-striped">';
  354.                         $output .= '<tr>';
  355.                         $output .= '<th>'._L('Filename').'</th>';
  356.                         $output .= '<th>'._L('Size').'</th>';
  357.                         $output .= '<th>'._L('File type').'</th>';
  358.                         $output .= '<th>'._L('Download').'</th>';
  359.                         if ($can_delete) $output .= '<th>'._L('Delete').'</th>';
  360.                         $output .= '</tr>';
  361.                         if ($files) foreach ($files as $file) {
  362.                                 if (is_dir($file)) continue;
  363.  
  364.                                 $output .= '<tr>';
  365.                                 $output .= '<td>'.htmlentities(basename($file)).'</td>';
  366.                                 $output .= '<td>'.htmlentities(self::convert_filesize(filesize($file), 0)).'</td>';
  367.                                 $lookup_files = array(
  368.                                         OIDplus::localpath().'userdata/attachments/filetypes$'.OIDplus::getCurrentLang().'.conf',
  369.                                         OIDplus::localpath().'userdata/attachments/filetypes.conf',
  370.                                         OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.local', // not recommended
  371.                                         OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.local', // not recommended
  372.                                         OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes$'.OIDplus::getCurrentLang().'.conf',
  373.                                         OIDplus::localpath().'vendor/danielmarschall/fileformats/filetypes.conf'
  374.                                 );
  375.                                 $output .= '<td>'.htmlentities(VtsFileTypeDetect::getDescription($file, $lookup_files)).'</td>';
  376.  
  377.                                 $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__,true)).', current_node,'.js_escape(basename($file)).')">'._L('Download').'</button></td>';
  378.                                 if ($can_delete) {
  379.                                         $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>';
  380.                                 }
  381.  
  382.                                 $output .= '</tr>';
  383.                                 $doshow = true;
  384.                                 $found_files = true;
  385.                         }
  386.  
  387.                         if (!$found_files) $output .= '<tr><td colspan="'.($can_delete ? 5 : 4).'"><i>'._L('No attachments').'</i></td></tr>';
  388.  
  389.                         $output .= '</table></div>';
  390.  
  391.                         if ($can_upload) {
  392.                                 $output .= '<form action="javascript:void(0);" onsubmit="return OIDplusPagePublicAttachments.uploadAttachmentOnSubmit(this);" enctype="multipart/form-data" id="uploadAttachmentForm">';
  393.                                 $output .= '<input type="hidden" name="id" value="'.htmlentities($id).'">';
  394.                                 $output .= '<div>'._L('Add a file attachment').':<input type="file" name="userfile" value="" id="fileAttachment">';
  395.                                 $output .= '<br><input type="submit" value="'._L('Upload').'"></div>';
  396.                                 $output .= '</form>';
  397.                                 $doshow = true;
  398.                         }
  399.                 } catch (Exception $e) {
  400.                         $doshow = true;
  401.                         $output = '<p>'.$e->getMessage().'</p>';
  402.                 }
  403.  
  404.                 $output = '<h2>'._L('File attachments').'</h2>' .
  405.                           '<div class="container box">' .
  406.                           $output .
  407.                           '</div>';
  408.                 if ($doshow) $text .= $output;
  409.         }
  410.  
  411.         public function beforeObjectDelete($id) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  412.         public function afterObjectDelete($id) {
  413.                 // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  414.                 // Delete the attachment folder including all files in it (note: Subfolders are not possible)
  415.                 $uploaddir = self::getUploadDir($id);
  416.                 if ($uploaddir != '') {
  417.                         $ary = @glob($uploaddir . DIRECTORY_SEPARATOR . '*');
  418.                         if ($ary) foreach ($ary as $a) @unlink($a);
  419.                         @rmdir($uploaddir);
  420.                         if (is_dir($uploaddir)) {
  421.                                 OIDplus::logger()->log("[WARN]OID($id)+[WARN]A!", "Attachment directory '$uploaddir' could not be deleted during the deletion of the OID");
  422.                         }
  423.                 }
  424.         }
  425.         public function beforeObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  426.         public function afterObjectUpdateSuperior($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  427.         public function beforeObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  428.         public function afterObjectUpdateSelf($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  429.         public function beforeObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  430.         public function afterObjectInsert($id, &$params) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.3
  431.  
  432.         public function tree_search($request) {
  433.                 return false;
  434.         }
  435.  
  436.         public function whoisObjectAttributes($id, &$out) {
  437.                 // Interface 1.3.6.1.4.1.37476.2.5.2.3.4
  438.  
  439.                 $files = @glob(self::getUploadDir($id) . DIRECTORY_SEPARATOR . '*');
  440.                 if ($files) foreach ($files as $file) {
  441.                         $out[] = 'attachment-name: '.basename($file);
  442.                         $out[] = 'attachment-url: '.OIDplus::webpath(__DIR__,true).'download.php?id='.urlencode($id).'&filename='.urlencode(basename($file));
  443.                 }
  444.  
  445.         }
  446.         public function whoisRaAttributes($email, &$out) {} // Interface 1.3.6.1.4.1.37476.2.5.2.3.4
  447. }
  448.