action.php 11 KB

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