1<?php 2/** 3 @file noiewarning/action.php 4 @brief Warn users of Internet Explorer browser. 5 @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 @author Luis Machuca Bezzaza <luis [dot] machuca [at] gulix [dot] cl> 7 @version 2018-08-21 8**/ 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11if(!defined('DW_LF')) define('DW_LF',"\n"); 12 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14define('THIS_PLUGIN', DOKU_PLUGIN.'noiewarning/'); 15require_once(DOKU_PLUGIN.'action.php'); 16require_once(DOKU_INC.'inc/confutils.php'); 17require_once(DOKU_INC.'inc/infoutils.php'); // for notify facilities 18 19/** 20 * All DokuWiki plugins to extend the admin function 21 * need to inherit from this class 22 */ 23class action_plugin_noiewarning extends DokuWiki_Action_Plugin { 24 25 // the plugin's data object 26 var $cnf= array(); 27 // the browser recommendation 28 var $betterbrowser= null; 29 30 function action_plugin_noiewarning () { 31 global $ID; 32 global $ACT; 33 // load options from configuration 34 $this->cnf= array ( 35 'id' => $ID, 36 'is_IE' => $this->_is_IE(), 37 'browser' => $_SERVER['HTTP_USER_AGENT'], 38 'message' => null, 39 'file' => null, 40 'showhack' => false 41 ); 42 43 $this->betterbrowser= $this->get_better_browser(); 44 if ($this->cnf['showhack'] !== false) { 45 $hackwarn = 'ERROR: the loaded hash "'. $this->cnf['file']; 46 $hackwarn.= '" seems to recommend Internet Explorer.<br/>'; 47 $hackwarn.= '<strong>This wiki installation may have been hacked!</strong>'; 48 msg($hackwarn, -1); 49 return; // nothing more to do 50 } 51 // if not IE, nothing more to do 52 if (!$this->cnf['is_IE'] ) return; // nothing more to be done 53 54 $this->cnf['method'] = $this->getConf('method'); 55 $this->cnf['datasrc']= $this->getConf('source'); 56 $this->cnf['banner'] = $this->getLang('wedetect'); 57 // set up information 58 59 } 60 61 function getInfo () { 62 $parts = explode('_',get_class($this)); 63 $file = DOKU_PLUGIN.'/'.$parts[2].'/plugin.info.txt'; 64 $info = array(); 65 if(!@file_exists($file)) { 66 trigger_error('getInfo() not implemented in '.get_class($this).' and '.$info.' not found', E_USER_WARNING); 67 } 68 else { 69 $info= confToHash($file); 70 $lang= explode(',', $info['lang']); 71 if (in_array('desc', $lang) && ''!==$this->getLang('plugininfo_desc')) $info['desc']= $this->getLang('plugininfo_desc'); 72 } 73 return $info; 74 } 75 76 /*** 77 * Register its handlers with the DokuWiki's event controller 78 */ 79 function register(Doku_Event_Handler $controller) { 80 global $ACT; 81 if ($ACT != 'show' || $this->cnf['showhack']===true) return; 82 $controller->register_hook( 83 'TPL_CONTENT_DISPLAY','BEFORE', $this, 'warning',array()); 84 85 // debug handler (should be disabled by default) 86 //$controller->register_hook( 87 //'TPL_CONTENT_DISPLAY','BEFORE', $this, '_debug'); 88 } 89 90 91/* 92 rendering options (from getConf) 93 subsection -> write the message as first content of wikipage 94 notify -> use the DokuWiki notification message area 95 load_note -> use the note plugin if available 96 splash -> use a JS+CSS splash screen (not available in this release) 97*/ 98 function warning (Doku_Event $event, $param) { 99 global $ID; 100 global $INFO; 101 global $ACT; 102 static $done= false; 103 104 // we do work only when IE is detected 105 if (!$this->_is_IE() // if user is not using IE 106 || $ACT!='show' // or we are not actually displaying a page 107 ) { 108 $done= true; 109 return; 110 } 111 else { 112 $emessage= $this->cnf['banner']; 113 114 switch ($this->cnf['method']) { 115 case 'notify': { 116 $this->render_notify_($event, $param); 117 break; 118 } 119 case 'note': { 120 $this->render_note_($event, $param); 121 break; 122 } 123 /* case not yet implemented 124 case 'splash': { 125 $this->render_splash_($event, $param); 126 break; 127 } 128 */ 129 default: { 130 // prepends the warning to the page output data 131 //$event->data= $emessage. DW_LF. $event->data; 132 $this->render_text_($event, $param); 133 break; 134 } 135 136 } // end switch 137 $done= true; 138 } // end else (working against IE) 139 140 // end function 141 } 142 143 144/** 145 ******************************************************************* 146 * Helper Functions 147 */ 148 149 /** 150 * @fn _is_IE 151 * @brief Attempts to detect Internet Explorer 152 * @return <tt>true</tt> if IE is detected, <tt>false</tt> otherwise 153 */ 154 private function _is_IE () { 155 $useragent= $_SERVER['HTTP_USER_AGENT']; 156 if (strpos($useragent, 'MSIE') !== false) 157 return true; 158 else if (strpos($useragent, 'Trident/') !== false) 159 return true; 160 else if (strpos($useragent, 'Edge/') !== false) 161 return true; 162 else 163 return false; // end function 164 } 165 166 function render_text_ (Doku_Event $event, $param) { 167 global $conf; 168 $warn= p_render('xhtml', p_get_instructions($this->getLang('wedetect')), $info); 169 $warn= '<div id="noiewarning"> '. $warn; 170 171 if ($this->betterbrowser !== null && !empty($this->betterbrowser)) { // can't do a thing 172 173 $url= $this->betterbrowser['url']; 174 $favicon= htmlspecialchars( $this->betterbrowser['icon'] ? 'background-image: url('.$this->betterbrowser['icon'].') ;' : '' ); 175 $color= $this->betterbrowser['color'] ? 'border-bottom: 2px solid '. str_replace('%','#', $this->betterbrowser['color']). ';' : ''; 176 $werecommend= htmlspecialchars($this->getLang('werecommend')); 177 $name= htmlspecialchars($this->betterbrowser['browser']); 178 $warn= <<<EOF 179$warn 180<p>$werecommend <a href="$url" class="urlextern" style="$favicon $color">$name</a>.</p> 181EOF; 182 183 } 184 $warn= $warn. DW_LF. '</div>'. DW_LF; 185 $event->data = $warn.$event->data; 186 } 187 188 189 function render_notify_ (Doku_Event $event, $param) { 190 global $conf; 191 $warn= p_render('xhtml', p_get_instructions($this->getLang('wedetect')), $info); 192 $warn= substr($warn, 4, -5); 193 msg($warn, -1); 194 195 if ($this->betterbrowser !== null && !empty($this->betterbrowser)) { 196 197 $url= $this->betterbrowser['url']; 198 $favicon= $this->betterbrowser['icon'] ? 'background-image: url('.$this->betterbrowser['icon'].') ;' : ''; 199 $name= htmlspecialchars($this->betterbrowser['browser']); 200 $title= htmlspecialchars("Switch to ". $name); 201 $werecommend= htmlspecialchars($this->getLang('werecommend')); 202 $more= 'line-height: 1.6em; text-decoration: none; text-shadow: -1px -1px '. $this->betterbrowser['color']. ';'. $favicon; 203 $reclink= <<<EOF 204$werecommend <a href="$url" class="urlextern" rel="follow" title="$title" style="$more" >$name</a> 205EOF; 206 207 msg($reclink, 0); 208 } // end if 209 } 210 211 function render_note_ (Doku_Event $event, $param) { 212 $notehelper= &plugin_load('syntax', 'note'); 213 if (!$notehelper) { 214 msg("noiewarning: the plugin (note) was selected as an assist, but not found.", -1); 215 } 216 global $conf; 217 $warn = '<note warning>'.DW_LF. DW_LF; 218 $warn.= $this->getLang('wedetect'). DW_LF; 219 if ($this->betterbrowser !== null && !empty($this->betterbrowser)) { // can't do a thing 220 $wrecc.= DW_LF. $this->getLang('werecommend'); 221 $url= $this->betterbrowser['url']; 222 $name= $this->betterbrowser['browser']; 223 224 $wrecc.= "[[${url}|${name}]] .". DW_LF; 225 $warn.= $wrecc; 226 } 227 $warn.= '</note>'. DW_LF; 228 229 $outp= p_render('xhtml', p_get_instructions($warn), $info); 230 $event->data = $outp.$event->data; 231 } 232 233 function render_splash_ (Doku_Event $event, $param) { 234 } 235 236 237 function _debug (Doku_Event $event, $param) { 238 global $ACT; 239 $d .= '<pre> ACT: '. $ACT. DW_LF; 240 if (!$this->betterbrowser) $d .= ' --- BADARRAY ---'; 241 else $d .= print_r ($this->betterbrowser, true); 242 $d .= '</pre><br/>'; 243 $event->data = $d. $event->data; 244 } 245 246 247 /** 248 * @fn _getraw 249 * @brief Loads the wikitext from a file, given its wikipage 250 * 251 * Technically just a wrapper on io_readfile, but as it is intended 252 * to grow and do specific parsing, will be separated here. 253 */ 254 private function _getraw ($wikipage) { 255 if (page_exists($page) ) { 256 // start a renderer and pass it the warning wikipage 257 $file = wikiFN($page); 258 $text = io_readfile($file); 259 } 260 return $text; 261 // end function 262 } 263 264 265 266 /** 267 This function looks for a hash file called 268 DOKU_CONF/better-browser.txt, which contains info about a 269 recommended browser. 270 **/ 271 private function get_better_browser ($id = '') { 272 $hash= null; 273 if ($id === '') $id= $this->getConf('better'); 274 // search recommend at $DOKU_CONF or browserlist path 275 if ($id === 'custom') { 276 $betterfile= DOKU_CONF. '/better-browser.txt'; 277 if (file_exists($betterfile)) { 278 $hash= confToHash($betterfile); 279 $this->cnf['file']= $id; 280 } 281 else $id= 'firefox'; 282 } 283 if ($hash === null) { 284 $betterfile= THIS_PLUGIN.'recommend/'.$id.'.txt'; 285 if (file_exists($betterfile)) { 286 $hash= confToHash($betterfile); 287 $this->cnf['file']= $id; 288 } 289 } 290 //sanitize the hash, checking that there are no mentions of IE 291 if ($hash === null) return $hash; // nothing more can be done 292 if (in_array('IE', $hash)!==false 293 || in_array('Internet Explorer', $hash)!==false 294 || in_array('Microsoft', $hash)!==false 295 || in_array('Edge/', $hash)!==false 296 ) { 297 $this->cnf['file']= $id. '(?)'; 298 // should NOT be recommending! 299 $hash= null; 300 //$hackwarn= htmlspecialchars($hackwarn); 301 if ($this->cnf['showhack'] === false) { 302 $this->cnf['showhack']= true; 303 } 304 } 305 return $hash; 306 } 307 308} 309