Subversion Repositories oidplus

Rev

Rev 294 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2020 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. class OIDplusPagePublicResources extends OIDplusPagePluginPublic {
  21.  
  22.         public function init($html=true) {
  23.                 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) {
  24.                         if (!is_numeric($value) || ($value < 0)) {
  25.                                 throw new OIDplusException("Please enter a valid value.");
  26.                         }
  27.                 });
  28.                 OIDplus::config()->prepareConfigKey('resource_plugin_title',          'Resource plugin: Title of the resource section?', 'Documents and resources', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  29.                         if (empty($value)) {
  30.                                 throw new OIDplusException("Please enter a title.");
  31.                         }
  32.                 });
  33.                 OIDplus::config()->deleteConfigKey('resource_plugin_path');
  34.                 OIDplus::config()->prepareConfigKey('resource_plugin_hide_empty_path','Resource plugin: Hide empty paths? 1=on, 0=off', 1, OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  35.                         if (!is_numeric($value) || (($value != 0) && ($value != 1))) {
  36.                                 throw new OIDplusException("Please enter a valid value (0=off, 1=on).");
  37.                         }
  38.                 });
  39.         }
  40.  
  41.         private static function getDocumentTitle($file) {
  42.  
  43.                 $file = OIDplus::basePath().'/'.self::realname($file);
  44.  
  45.                 $cont = file_get_contents($file);
  46.                 if (preg_match('@<title>(.+)</title>@ismU', $cont, $m)) return $m[1];
  47.                 if (preg_match('@<h1>(.+)</h1>@ismU', $cont, $m)) return $m[1];
  48.                 if (preg_match('@<h2>(.+)</h2>@ismU', $cont, $m)) return $m[1];
  49.                 if (preg_match('@<h3>(.+)</h3>@ismU', $cont, $m)) return $m[1];
  50.                 if (preg_match('@<h4>(.+)</h4>@ismU', $cont, $m)) return $m[1];
  51.                 if (preg_match('@<h5>(.+)</h5>@ismU', $cont, $m)) return $m[1];
  52.                 if (preg_match('@<h6>(.+)</h6>@ismU', $cont, $m)) return $m[1];
  53.                 return pathinfo($file, PATHINFO_FILENAME); // filename without extension
  54.         }
  55.        
  56.         private static function myglob($reldir, $onlydir=false) {
  57.                 $out = array();
  58.                
  59.                 $root = OIDplus::basePath().'/userdata/resources/';
  60.                 $res = $onlydir ? glob($root.$reldir, GLOB_ONLYDIR) : glob($root.$reldir);
  61.                 foreach ($res as &$x) {
  62.                         $x = substr($x, strlen($root));
  63.                         $out[] = $x;
  64.                 }
  65.  
  66.                 $root = OIDplus::basePath().'/res/';
  67.                 $res = $onlydir ? glob($root.$reldir, GLOB_ONLYDIR) : glob($root.$reldir);
  68.                 foreach ($res as $x) {
  69.                         $x = substr($x, strlen($root));
  70.                         $out[] = $x;
  71.                 }
  72.  
  73.                 return array_unique($out);
  74.         }
  75.        
  76.         private static function realname($rel) {
  77.                 $candidate1 = OIDplus::basePath().'/userdata/resources/'.$rel;
  78.                 $candidate2 = OIDplus::basePath().'/res/'.$rel;
  79.                 if (file_exists($candidate1) || is_dir($candidate1)) return "userdata/resources/$rel";
  80.                 if (file_exists($candidate2) || is_dir($candidate2)) return "res/$rel";
  81.         }
  82.  
  83.         public function gui($id, &$out, &$handled) {
  84.                 if (explode('$',$id)[0] === 'oidplus:resources') {
  85.                         $handled = true;
  86.  
  87.                         $file = @explode('$',$id)[1];
  88.                         $auth = @explode('$',$id)[2];
  89.  
  90.                         if (!OIDplus::authUtils()::validateAuthKey("resources;$file", $auth)) {
  91.                                 $out['title'] = 'Access denied';
  92.                                 $out['icon'] = 'img/error_big.png';
  93.                                 $out['text'] = '<p>Invalid authentication token</p>';
  94.                                 return;
  95.                         }
  96.  
  97.                         if (strpos($file, '..') !== false) {
  98.                                 $out['title'] = 'Access denied';
  99.                                 $out['icon'] = 'img/error_big.png';
  100.                                 $out['text'] = '<p>Security breach</p>';
  101.                                 return;
  102.                         }
  103.  
  104.                         $out['text'] = '';
  105.  
  106.                         if ($file != '/') {
  107.                                 $dir = dirname($file);
  108.  
  109.                                 if ($dir == '/') {
  110.                                         if (file_exists(__DIR__.'/treeicon.png')) {
  111.                                                 $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  112.                                         } else {
  113.                                                 $tree_icon = null; // default icon (folder)
  114.                                         }
  115.  
  116.                                         $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">';
  117.  
  118.                                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$/$'.OIDplus::authUtils()::makeAuthKey('resources;/')).'><img src="img/arrow_back.png" width="16"> Go back to: '.$ic.' '.htmlentities(OIDplus::config()->getValue('resource_plugin_title', 'Documents and resources')).'</a></p>';
  119.                                 } else {
  120.                                         $realdir = self::realname($dir);
  121.                                        
  122.                                         $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_folder&file='.urlencode($dir);
  123.                                         /*
  124.                                         $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png';
  125.                                         if (file_exists($icon_candidate)) {
  126.                                                 $tree_icon = $icon_candidate;
  127.                                         } else if (file_exists(__DIR__.'/treeicon_folder.png')) {
  128.                                                 $tree_icon = OIDplus::webpath(__DIR__).'treeicon_folder.png';
  129.                                         } else {
  130.                                                 $tree_icon = null; // no icon
  131.                                         }
  132.                                         */
  133.  
  134.                                         $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">';
  135.  
  136.                                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.$dir.'$'.OIDplus::authUtils()::makeAuthKey("resources;$dir")).'><img src="img/arrow_back.png" width="16"> Go back to: '.$ic.' '.htmlentities(basename($dir)).'</a></p><br>';
  137.                                 }
  138.                         }
  139.                        
  140.                         $realfile = self::realname($file);
  141.  
  142.                         if (file_exists($realfile) && (!is_dir($realfile))) {
  143.                                 if (substr($file,-4,4) == '.url') {
  144.                                         $out['title'] = $this->getHyperlinkTitle($realfile);
  145.  
  146.                                         $out['icon'] = OIDplus::webpath(__DIR__).'show_icon.php?mode=icon_leaf_url_big&file='.urlencode($file);
  147.                                         /*
  148.                                         $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png';
  149.                                         if (file_exists($icon_candidate)) {
  150.                                                 $out['icon'] = $icon_candidate;
  151.                                         } else if (file_exists(__DIR__.'/icon_leaf_url_big.png')) {
  152.                                                 $out['icon'] = OIDplus::webpath(__DIR__).'icon_leaf_url_big.png';
  153.                                         } else {
  154.                                                 $out['icon'] = '';
  155.                                         }
  156.                                         */
  157.  
  158.                                         // Should not happen though, due to conditionalselect
  159.                                         $out['text'] .= '<a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">Open in new window</a>';
  160.                                 } else if ((substr($file,-4,4) == '.htm') || (substr($file,-5,5) == '.html')) {
  161.                                         $out['title'] = $this->getDocumentTitle($file);
  162.  
  163.                                         $out['icon'] = OIDplus::webpath(__DIR__).'show_icon.php?mode=icon_leaf_doc_big&file='.urlencode($file);
  164.                                         /*
  165.                                         $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png';
  166.                                         if (file_exists($icon_candidate)) {
  167.                                                 $out['icon'] = $icon_candidate;
  168.                                         } else if (file_exists(__DIR__.'/icon_leaf_doc_big.png')) {
  169.                                                 $out['icon'] = OIDplus::webpath(__DIR__).'icon_leaf_doc_big.png';
  170.                                         } else {
  171.                                                 $out['icon'] = '';
  172.                                         }
  173.                                         */
  174.  
  175.                                         $file = OIDplus::basePath().'/'.self::realname($file);
  176.                                        
  177.                                         $cont = file_get_contents($file);
  178.                                         $cont = preg_replace('@^(.+)<body[^>]*>@isU', '', $cont);
  179.                                         $cont = preg_replace('@</body>.+$@isU', '', $cont);
  180.                                         $cont = preg_replace('@<title>.+</title>@isU', '', $cont);
  181.                                         $cont = preg_replace('@<h1>.+</h1>@isU', '', $cont, 1);
  182.  
  183.                                         $out['text'] .= $cont;
  184.                                 } else {
  185.                                         $out['title'] = 'Unknown file type';
  186.                                         $out['icon'] = 'img/error_big.png';
  187.                                         $out['text'] = '<p>The system does not know how to handle this file type.</p>';
  188.                                         return;
  189.                                 }
  190.                         } else if (is_dir($realfile)) {
  191.                                 $out['title'] = ($file == '/') ? OIDplus::config()->getValue('resource_plugin_title', 'Documents and resources') : basename($file);
  192.  
  193.                                 if ($file == '/') {
  194.                                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  195.                                 } else {
  196.                                         $out['icon'] = OIDplus::webpath(__DIR__).'show_icon.php?mode=icon_folder_big&file='.urlencode($file);
  197.                                         /*
  198.                                         $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_big.png';
  199.                                         if (file_exists($icon_candidate)) {
  200.                                                 $out['icon'] = $icon_candidate;
  201.                                         } else if (file_exists(__DIR__.'/icon_folder_big.png')) {
  202.                                                 $out['icon'] = OIDplus::webpath(__DIR__).'icon_folder_big.png';
  203.                                         } else {
  204.                                                 $out['icon'] = null; // no icon
  205.                                         }
  206.                                         */
  207.                                 }
  208.  
  209.                                 if (file_exists(__DIR__.'/treeicon.png')) {
  210.                                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  211.                                 } else {
  212.                                         $tree_icon = null; // default icon (folder)
  213.                                 }
  214.  
  215.                                 $count = 0;
  216.  
  217.                                 $dirs = self::myglob($file.'*'.'/', true);
  218.                                 natcasesort($dirs);
  219.                                 foreach ($dirs as $dir) {
  220.                                         $realdir = self::realname($dir);
  221.                                         $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_folder&file='.urlencode($dir);
  222.                                         /*
  223.                                         $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png';
  224.                                         if (file_exists($icon_candidate)) {
  225.                                                 $tree_icon = $icon_candidate;
  226.                                         } else if (file_exists(__DIR__.'/treeicon_folder.png')) {
  227.                                                 $tree_icon = OIDplus::webpath(__DIR__).'treeicon_folder.png';
  228.                                         } else {
  229.                                                 $tree_icon = null; // no icon
  230.                                         }
  231.                                         */
  232.  
  233.                                         $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">';
  234.  
  235.                                         $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.$dir.'$'.OIDplus::authUtils()::makeAuthKey("resources;$dir")).'>'.$ic.' '.htmlentities(basename($dir)).'</a></p>';
  236.                                         $count++;
  237.                                 }
  238.  
  239.                                 $files = array_merge(
  240.                                         self::myglob($file.'/'.'*.htm*'), // TODO: also PHP?
  241.                                         self::myglob($file.'/'.'*.url')
  242.                                 );
  243.                                 natcasesort($files);
  244.                                 foreach ($files as $file) {
  245.                                         $realfile = self::realname($file);
  246.                                         if (substr($file,-4,4) == '.url') {
  247.                                                 $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_leaf_url&file='.urlencode($file);
  248.                                                 /*
  249.                                                 $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png';
  250.                                                 if (file_exists($icon_candidate)) {
  251.                                                         $tree_icon = $icon_candidate;
  252.                                                 } else if (file_exists(__DIR__.'/treeicon_leaf_url.png')) {
  253.                                                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon_leaf_url.png';
  254.                                                 } else {
  255.                                                         $tree_icon = null; // default icon (folder)
  256.                                                 }
  257.                                                 */
  258.                                                
  259.                                                 $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">';
  260.  
  261.                                                 $hyperlink_pic = ' <img src="'.OIDplus::webpath(__DIR__).'hyperlink.png" widht="13" height="13" alt="Hyperlink" style="top:-3px;position:relative">';
  262.  
  263.                                                 $out['text'] .= '<p><a href="'.htmlentities(self::getHyperlinkURL($realfile)).'" target="_blank">'.$ic.' '.htmlentities($this->getHyperlinkTitle($realfile)).' '.$hyperlink_pic.'</a></p>';
  264.                                                 $count++;
  265.                                         } else {
  266.                                                 $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_leaf_doc&file='.urlencode($file);
  267.                                                 /*
  268.                                                 $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png';
  269.                                                 if (file_exists($icon_candidate)) {
  270.                                                         $tree_icon = $icon_candidate;
  271.                                                 } else if (file_exists(__DIR__.'/treeicon_leaf_doc.png')) {
  272.                                                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon_leaf_doc.png';
  273.                                                 } else {
  274.                                                         $tree_icon = null; // default icon (folder)
  275.                                                 }
  276.                                                 */
  277.                                                
  278.                                                 $ic = empty($tree_icon) ? '' : '<img src="'.$tree_icon.'" alt="">';
  279.  
  280.                                                 $out['text'] .= '<p><a '.OIDplus::gui()->link('oidplus:resources$'.$file.'$'.OIDplus::authUtils()::makeAuthKey("resources;$file")).'>'.$ic.' '.htmlentities($this->getDocumentTitle($file)).'</a></p>';
  281.                                                 $count++;
  282.                                         }
  283.                                 }
  284.  
  285.                                 if ($count == 0) {
  286.                                         $out['text'] .= '<p>This folder does not contain any elements</p>';
  287.                                 }
  288.                         } else {
  289.                                 $out['title'] = 'Not found';
  290.                                 $out['icon'] = 'img/error_big.png';
  291.                                 $out['text'] = '<p>This resource doesn\'t exist anymore.</p>';
  292.                         }
  293.                 }
  294.         }
  295.  
  296.         private function tree_rec(&$children, $rootdir=null, $depth=0) {
  297.                 if (is_null($rootdir)) $rootdir = '/';
  298.                 if ($depth > 100) return false; // something is wrong!
  299.  
  300.                 $dirs = self::myglob($rootdir.'*'.'/', true);
  301.                 natcasesort($dirs);
  302.                 foreach ($dirs as $dir) {
  303.                         $tmp = array();
  304.                        
  305.                         $this->tree_rec($tmp, $dir, $depth+1);
  306.  
  307.                         $realdir = self::realname($dir);
  308.                        
  309.                         $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_folder&file='.urlencode($dir);
  310.                         /*
  311.                         $icon_candidate = pathinfo($realdir)['dirname'].'/'.pathinfo($realdir)['filename'].'_tree.png';
  312.                         if (file_exists($icon_candidate)) {
  313.                                 $tree_icon = $icon_candidate;
  314.                         } else if (file_exists(__DIR__.'/treeicon_folder.png')) {
  315.                                 $tree_icon = OIDplus::webpath(__DIR__).'treeicon_folder.png';
  316.                         } else {
  317.                                 $tree_icon = null; // default icon (folder)
  318.                         }
  319.                         */
  320.  
  321.                         $children[] = array(
  322.                                 'id' => 'oidplus:resources$'.$dir.'$'.OIDplus::authUtils()::makeAuthKey("resources;$dir"),
  323.                                 'icon' => $tree_icon,
  324.                                 'text' => basename($dir),
  325.                                 'children' => $tmp,
  326.                                 'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1)
  327.                         );
  328.                 }
  329.  
  330.                 $files = array_merge(
  331.                         self::myglob($rootdir.'*.htm*'), // TODO: Also PHP?
  332.                         self::myglob($rootdir.'*.url')
  333.                 );
  334.                 natcasesort($files);
  335.                 foreach ($files as $file) {
  336.                         $realfile = self::realname($file);
  337.                         if (substr($file,-4,4) == '.url') {
  338.                                 $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_leaf_url&file='.urlencode($file);
  339.                                 /*
  340.                                 $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png';
  341.                                 if (file_exists($icon_candidate)) {
  342.                                         $tree_icon = $icon_candidate;
  343.                                 } else if (file_exists(__DIR__.'/treeicon_leaf_url.png')) {
  344.                                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon_leaf_url.png';
  345.                                 } else {
  346.                                         $tree_icon = null; // default icon (folder)
  347.                                 }
  348.                                 */
  349.  
  350.                                 $hyperlink_pic = ' <img src="'.OIDplus::webpath(__DIR__).'hyperlink.png" widht="13" height="13" alt="Hyperlink" style="top:-3px;position:relative">';
  351.  
  352.                                 $children[] = array(
  353.                                         'id' => 'oidplus:resources$'.$file.'$'.OIDplus::authUtils()::makeAuthKey("resources;$file"),
  354.                                         'conditionalselect' => 'window.open('.js_escape(self::getHyperlinkURL($realfile)).'); false;',
  355.                                         'icon' => $tree_icon,
  356.                                         'text' => $this->getHyperlinkTitle($realfile).' '.$hyperlink_pic,
  357.                                         'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1)
  358.                                 );
  359.                         } else {
  360.                                 $tree_icon = OIDplus::webpath(__DIR__).'show_icon.php?mode=treeicon_leaf_doc&file='.urlencode($file);
  361.                                 /*
  362.                                 $icon_candidate = pathinfo($realfile)['dirname'].'/'.pathinfo($realfile)['filename'].'_tree.png';
  363.                                 if (file_exists($icon_candidate)) {
  364.                                         $tree_icon = $icon_candidate;
  365.                                 } else if (file_exists(__DIR__.'/treeicon_leaf_doc.png')) {
  366.                                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon_leaf_doc.png';
  367.                                 } else {
  368.                                         $tree_icon = null; // default icon (folder)
  369.                                 }
  370.                                 */
  371.                                 $children[] = array(
  372.                                         'id' => 'oidplus:resources$'.$file.'$'.OIDplus::authUtils()::makeAuthKey("resources;$file"),
  373.                                         'icon' => $tree_icon,
  374.                                         'text' => $this->getDocumentTitle($file),
  375.                                         'state' => array("opened" => $depth <= OIDplus::config()->getValue('resource_plugin_autoopen_level', 1)-1)
  376.                                 );
  377.                         }
  378.                 }
  379.         }
  380.  
  381.         private function publicSitemap_rec($json, &$out) {
  382.                 foreach ($json as $x) {
  383.                         if (isset($x['id']) && $x['id']) {
  384.                                 $out[] = OIDplus::getSystemUrl().'?goto='.urlencode($x['id']);
  385.                         }
  386.                         if (isset($x['children'])) {
  387.                                 $this->publicSitemap_rec($x['children'], $out);
  388.                         }
  389.                 }
  390.         }
  391.  
  392.         public function publicSitemap(&$out) {
  393.                 $json = array();
  394.                 $this->tree($json, null/*RA EMail*/, false/*HTML tree algorithm*/, true/*display all*/);
  395.                 $this->publicSitemap_rec($json, $out);
  396.         }
  397.  
  398.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  399.                 $children = array();
  400.  
  401.                 $this->tree_rec($children, '/');
  402.  
  403.                 if (!OIDplus::config()->getValue('resource_plugin_hide_empty_path', true) || (count($children) > 0)) {
  404.                         if (file_exists(__DIR__.'/treeicon.png')) {
  405.                                 $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  406.                         } else {
  407.                                 $tree_icon = null; // default icon (folder)
  408.                         }
  409.  
  410.                         $json[] = array(
  411.                                 'id' => 'oidplus:resources$/$'.OIDplus::authUtils()::makeAuthKey('resources;/'),
  412.                                 'icon' => $tree_icon,
  413.                                 'state' => array("opened" => true),
  414.                                 'text' => OIDplus::config()->getValue('resource_plugin_title', 'Documents and resources'),
  415.                                 'children' => $children
  416.                         );
  417.                 }
  418.  
  419.                 return true;
  420.         }
  421.  
  422.         public function tree_search($request) {
  423.                 return false;
  424.         }
  425.  
  426.         private static function getHyperlinkTitle($file) {
  427.                 return preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($file));
  428.         }
  429.  
  430.         private static function getHyperlinkURL($file) {
  431.                 /*
  432.                 [{000214A0-0000-0000-C000-000000000046}]
  433.                 Prop3=19,2
  434.                 [InternetShortcut]
  435.                 URL=http://www.example.com/
  436.                 IDList=
  437.                 */
  438.                 $cont = file_get_contents($file);
  439.                 if (!preg_match('@URL=(.+)\n@ismU', $cont, $m)) return null;
  440.                 return trim($m[1]);
  441.         }
  442. }
  443.