1<?php 2/** 3 @file nobadbrowser/action.php 4 @brief Warn users of bad browsers. 5 @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 @author Luis Machuca Bezzaza <lambalicious [at] tuta [dot] io> 7**/ 8// must be run within Dokuwiki 9if(!defined('DOKU_INC')) die(); 10if(!defined('DW_LF')) define('DW_LF',"\n"); 11 12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 13define('THIS_PLUGIN', DOKU_PLUGIN.'nobadbrowser/'); 14require_once(DOKU_PLUGIN.'action.php'); 15require_once(DOKU_INC.'inc/confutils.php'); 16require_once(DOKU_INC.'inc/infoutils.php'); // for notify facilities 17 18/** 19 * All DokuWiki plugins to extend the admin function 20 * need to inherit from this class 21 */ 22class action_plugin_nobadbrowser extends DokuWiki_Action_Plugin { 23 24 // detected browser info 25 var $binfo = array(); 26 // the plugin's data object 27 var $cnf= array(); 28 29 function action_plugin_nobadbrowser () { 30 //global $ID; 31 //global $ACT; 32 global $bid; 33 $this->cnf= array(); 34 $this->binfo= []; 35 if (!extension_loaded('browscap')) { 36 $this->binfo= $this->get_browser_local($_SERVER['HTTP_USER_AGENT']); 37 $this->binfo['browscap']= false; 38 msg(<<<EOF 39nobadbrowser notice: This PHP installation seems to lack ''browscap'' support. Results may be inconclusive. 40EOF 41, 2); 42 } else { 43 $this->binfo= get_browser(null, true); 44 $this->binfo['browscap']= true; 45 } 46 $this->binfo['_UA']= $_SERVER['HTTP_USER_AGENT']; 47 //msg(print_r($this->binfo, true), 1); // FOR DEBUG 48 } 49 50 /*** 51 * Register its handlers with the DokuWiki's event controller 52 */ 53 function register (Doku_Event_Handler $controller) { 54 global $ACT; 55 if ($ACT != 'show') return; 56 $controller->register_hook('TPL_CONTENT_DISPLAY','BEFORE', $this, 'warning',array()); 57 } 58 59 60/* 61 rendering options (from getConf) 62 notify -> use the DokuWiki notification message area 63 splash -> use a JS+CSS splash screen (not available in this release) 64*/ 65 function warning (Doku_Event $event, $param) { 66 global $ACT; 67 static $done= false; 68 69 if ($ACT!='show') { 70 return; 71 } 72 if ($this->getConf['debug']) { 73 $this->render_debug($event, $param); 74 } 75 76 if ($this->whybadbrowser()) { 77 $parameter= $this->cnf['parameter']; 78 $reason= $this->cnf['reason']; 79 $see= $this->cnf['see']; 80 $mens = <<<EOF 81You seem to be using a bad browser. \\\\ 82You are at risk because __${parameter}__ is: __${reason}__. 83Visit [[${see}|nobadbrowser @ DokuWiki]] for more details. 84EOF; 85 $outp= p_render('xhtml', p_get_instructions($mens), $info); 86 msg(($outp), -1); 87 } 88 // end function 89 } 90 91 92/** 93 ******************************************************************* 94 * Helper Functions 95 */ 96 97 98 function whybadbrowser () { 99 // Match Internet Explorer 100 if (preg_match('/\bIE/', $this->binfo['browser']) && intval($this->binfo['version'])< 10 ) { 101 $this->cnf= array( 102 'parameter' => 'Browser old age', 103 'reason' => $this->binfo['browser'] . " " . $this->binfo['version'] , 104 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#internet_explorer' 105 ); 106 return true; 107 } 108 // ... or browsers made by Microsoft (incl. Edge) 109 if (preg_match('/^Microsoft.*/', $this->binfo['browser_maker'])) { 110 $this->cnf= array( 111 'reason' => $this->binfo['browser_maker'] , 112 'parameter' => 'Browser Ecosystem', 113 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#internet_explorer' 114 ); 115 return true; 116 } 117 // Match Opera post-Presto 118 if (preg_match('/^Opera/', $this->binfo['browser']) && intval($this->binfo['version'])>12 ) { 119 $this->cnf= [ 120 'reason' => $this->binfo['browser'] . " " . $this->binfo['version'], 121 'parameter' => 'Browser is a Chrome reskin', 122 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#opera' 123 ]; 124 return true; 125 } 126 // Match Google Chrome 127 if (preg_match('/\bChrome/', $this->binfo['browser'])) { 128 $this->cnf= array( 129 'reason' => $this->binfo['browser'] , 130 'parameter' => 'Browser', 131 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#google_chrome' 132 ); 133 return true; 134 } 135 // ... or browsers made by Google (incl. Android WebView) 136 if (preg_match('/^Google.*/', $this->binfo['browser_maker'])) { 137 $this->cnf= array( 138 'reason' => $this->binfo['browser_maker'] , 139 'parameter' => 'Browser Ecosystem', 140 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#google_chrome' 141 ); 142 return true; 143 } 144 // ...or Chrome reskins 145 if (preg_match('/\bChrome/', $this->binfo['parent']) ) { 146 $this->cnf= array( 147 'reason' => $this->binfo['parent'] , 148 'parameter' => 'Browser type', 149 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#google_chrome' 150 ); 151 return true; 152 } 153 // ...or Chrome reskins "trying to pass" 154 if (preg_match('/.*Google Inc.*/', $this->binfo['renderingengine_maker']) ) { 155 $this->cnf= array( 156 'reason' => 'Chrome reskin' , 157 'parameter' => 'Browser type', 158 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#google_chrome' 159 ); 160 return true; 161 } 162 // match browsers made by Apple 163 if (preg_match('/^Safari/', $this->binfo['browser']) 164 || preg_match('/^Apple/', $this->binfo['browser_maker']) ) { 165 $this->cnf= [ 166 'reason' => $this->binfo['browser_maker'] , 167 'parameter' => 'Browser Ecosystem', 168 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#apple' 169 ]; 170 return true; 171 } 172 // match browsers made by Facebook, for GAFAM completeness 173 if (preg_match('/^Facebook/', $this->binfo['browser_maker']) ) { 174 $this->cnf= [ 175 'reason' => $this->binfo['browser_maker'] , 176 'parameter' => 'Browser Ecosystem', 177 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#facebook' 178 ]; 179 return true; 180 } 181 // match browsers made by Amazon, for GAFAM completeness 182 if (preg_match('/^Amazon/', $this->binfo['browser_maker']) ) { 183 $this->cnf= [ 184 'reason' => $this->binfo['browser_maker'] , 185 'parameter' => 'Browser Ecosystem', 186 'see' => 'https://www.dokuwiki.org/plugin:nobadbrowser#amazon' 187 ]; 188 return true; 189 } 190 return false; 191 } 192 193 /** 194 * This function is an alternative to get_browser when not available. 195 * It does some parsing of the user agent string to provide acceptable, not necessarily accurate results, focused on returning five primary keys about the browser which are to concern for nobadbrowser : 196 * * browser 197 * * version 198 * * browser_maker 199 * * renderingengine_name 200 * * renderingengine_maker 201 * 202 * Other keys that can also be of interest: 203 * 204 * * renderingengine_version 205 * * parent 206 * 207 * */ 208 function get_browser_local ($user_agent, $return_array=true) { 209 $ret= []; 210 // Internet Explorer 211 if (strpos($user_agent, 'MSIE') !== false) { 212 $ret['browser']= 'IE'; 213 $ret['browser_maker']= 'Microsoft Corporation'; 214 if (preg_match ('#MSIE ([0-9\.]+);#', $user_agent, $browserversion) ) { 215 $ret['version']= $browserversion[1]; 216 $ver= explode('.', $browserversion[1], 3); 217 list($ret['majorver'], $ret['minorver'])= $ver; 218 $ret['parent']= $ret['browser']. ' ' . $ret['majorver']; 219 } 220 $ret['renderingengine_name']= 'Trident'; 221 $ret['renderingengine_maker']= 'Microsoft Corporation'; 222 if (preg_match ('#Trident/([0-9\.]+)#', $user_agent, $rendererversion) ) { 223 $ret['renderingengine_version']= $rendererversion[1]; 224 } 225 } 226 // Google Chrome and its various derivations 227 if (preg_match_all( 228 '#AppleWebKit/[0-9\.]+.*\(.*KHTML.*like.*Gecko.*\) Chrome/([0-9]+\.[0-9]+).+Safari/[0-9\.]+\b(.*)$#' 229 , $user_agent, $chrome_info) ) { 230 $ret['browser']= 'Chrome'; 231 $ret['browser_maker']= 'Google Inc'; 232 $ret['version']= $chrome_info[1][0]; 233 $ret['parent']= 'Chrome'; 234 $ret['variants']= $chrome_info[2]; 235 $variants= trim($chrome_info[2]); 236 $variants= explode(' ', $variants); 237 //$ret['variant_match']= $chrome_info[2][0]; 238 if (count($variants) > 0 && (isset($variants[0]) ) && ($variants[0] != '') ) { 239 //$ret['variant']= 1; 240 $variant= explode('/', $variants[0]); 241 $variantname= trim($variant[0]); 242 $variantmaker= $ret['browser_maker']; 243 if ($variantname=='Edg') { $variantname= 'Edge'; } 244 else if ($variantname=='OPR') { $variantname= 'Opera'; $variantmaker= 'Opera Software ASA'; } 245 $variantversion= explode('.', $variant[1],3); 246 $variantversion= $variantversion[0].'.'.$variantversion[1]; 247 $ret['variant_found']= [ $variantname, $variantversion]; 248 $ret['browser']= $variantname; 249 $ret['version']= $variantversion; 250 $ret['browser_maker']= $variantmaker; 251 } 252 //list($ret['majorver'], $ret['minorver'])= explode('.', $chrome_info[1],3); 253 $ret['renderingengine_name']= 'Blink'; 254 $ret['renderingengine_maker']= 'Google Inc'; 255 $ret['renderingengine_version']= ''; 256 } 257 // Safari 258 if (preg_match_all( 259 '#AppleWebKit/[0-9\.]+.*\(.*KHTML.*like.*Gecko.*\) Version/([0-9]+\.[0-9]+).*Safari/([0-9]+\.[0-9]+).*#' 260 , $user_agent, $safari_info) ) { 261 $ret['browser']= 'Safari'; 262 $ret['browser_maker']= 'Apple Inc'; 263 $ret['version']= $safari_info[1][0]; 264 $ret['renderingengine_name']= 'WebKit'; 265 $ret['renderingengine_maker']= 'Apple Inc'; 266 $ret['renderingengine_version']= ''; 267 } 268 // TODO: Facebook Browser 269 if (preg_match_all( 270 '#AppleWebKit/[0-9\.]+.*\(.*KHTML.*like.*Gecko.*\) Version/([0-9]+\.[0-9]+).*Safari/([0-9]+\.[0-9]+).*(FBAV|FBIOS).*#' 271 , $user_agent, $facebook_info) ) { 272 $ret['browser']= 'Facebook'; 273 $ret['browser_maker']= 'Facebook'; 274 $ret['version']= $facebook_info[1][0]; 275 $ret['renderingengine_name']= 'WebKit'; 276 $ret['renderingengine_maker']= 'Apple Inc'; 277 $ret['renderingengine_version']= ''; 278 } 279 // Firefox and its variants 280 if (preg_match_all( 281 '#^Mozilla/[0-9\.]+.*Gecko/[0-9]+.+Firefox/([0-9]+\.[0-9]+).*$#' 282 , $user_agent, $firefox_info) ) { 283 $ret['browser']= 'Firefox'; 284 $ret['browser_maker']= 'Mozilla Foundation'; 285 $ret['version']= $firefox_info[1][0]; 286 $rendererversion= $ret['version']; 287 $ret['renderingengine_name']= 'Gecko'; 288 $ret['renderingengine_maker']= 'Mozilla Foundation'; 289 $ret['renderingengine_version']= $rendererversion; 290 } 291 return $ret; 292 } 293 294 function render_debug (Doku_Event $event, $param) { 295 $arr= array( 296 'browser' => $this->binfo['browser'] , 297 'browser_maker' => $this->binfo['browser_maker'] , 298 ); 299 $x = print_r($this->binfo, true); 300 $out= '<pre>'. htmlspecialchars($x). '</pre>'; 301 msg($out,-1); 302 } 303 304} 305