update.npm.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //(c)2019, MIT Style License <browser-update.org/LICENSE.txt>
  2. //it is recommended to directly link to this file because we update the detection code
  3. "use strict";
  4. var $bu_= new function() {
  5. var s=this;
  6. this.version="3.3.26";
  7. this.vsakt = {c:"87.0.4280",f:83,s:"13.1.2",e:86,i:12,ios:"13.3",samsung:12.0,o:71,e_a:45.09,o_a:59.1,y:"20.9.1",v:3.3,uc:"13.3"};
  8. //severely insecure below(!) this version, insecure means remote code execution that is actively being exploited
  9. this.vsinsecure_below = {c:"86.0.4240.111",f:76,s:"11.1.1",e:16,i:11,ios:"12.3",samsung:9.0,o:62,o_a:52,y:"20",v:"2.7",uc:"13.1"};
  10. this.vsdefault = {c:-3,f:-3,s:-1,e:17,i:11,ios:10,samsung:9.9,o:-3,o_a:-3,y:20.4,v:2.6,uc:13.0,a:535};
  11. this.names={c:"Chrome",f:'Firefox',s:'Safari',e:"Edge",i:'Internet Explorer',ios:"iOS",samsung:"Samsung Internet",o:'Opera',o_a:'Opera', e_a:"Edge", y:"Yandex Browser",v:"Vivaldi",uc:"UC Browser",a:"Android Browser",x:"Other",silk:"Silk"};
  12. this.get_browser = function(ua) {
  13. var n,ua=(ua||navigator.userAgent).replace("_","."),r={n:"x",v:0,t:"other browser",age_years:undefined,no_device_update:false,available:s.vsakt};
  14. function ignore(reason,pattern){if (new RegExp(pattern,"i").test(ua)) return reason;return false}
  15. r.other=ignore("bot","Pagespeed|pingdom|Preview|ktxn|dynatrace|Ruxit|PhantomJS|Headless|Lighthouse|bot|spider|archiver|transcoder|crawl|checker|monitoring|prerender|screenshot|python-|php|uptime|validator|fetcher|facebook|slurp|google|yahoo|node|mail.ru|github|cloudflare|addthis|thumb|proxy|feed|fetch|favicon|link|http|scrape|seo|page|search console|AOLBuild|Teoma|Expeditor")||
  16. ignore("TV","SMART-TV|SmartTV") ||
  17. ignore("niche browser","OculusBrowser|Falkon|Brave|Classic Browser|Dorado|LBBROWSER|Focus|waterfox|Firefox/56.2|Firefox/56.3|Whale|MIDP|k-meleon|sparrow|wii|Chromium|Puffin|Opera Mini|maxthon|maxton|dolfin|dolphin|seamonkey|opera mini|netfront|moblin|maemo|arora|kazehakase|epiphany|konqueror|rekonq|symbian|webos|PaleMoon|Basilisk|QupZilla|Otter|Midori|qutebrowser") ||
  18. ignore("mobile without upgrade path or landing page","OPR/44.12.2246|cros|kindle|tizen|silk|blackberry|bb10|RIM|PlayBook|meego|nokia|ucweb|ZuneWP7|537.85.10");
  19. // ignore("android(chrome) web view","; wv");
  20. r.embedded=/"QtWebEngine|Teams|Electron/i.test(ua);
  21. r.mobile=(/iphone|ipod|ipad|android|mobile|phone|ios|iemobile/i.test(ua));
  22. r.discontinued=(/netscape|greenbrowser|camino|flot|fennec|galeon|coolnovo/i.test(ua));
  23. var pats=[
  24. ["CriOS.VV","c",'ios'],
  25. ["FxiOS.VV","f",'ios'],
  26. ["Trident.*rv:VV","i",'i'],
  27. ["Trident.VV","io",'i'],
  28. ["UCBrowser.VV","uc",'c'],
  29. ["MSIE.VV","i",'i'],
  30. ["Edge.VV","e",'e'],
  31. ["Edg.VV","e",'c'],
  32. ["EdgA.VV","e_a",'c'],
  33. ["Vivaldi.VV","v",'c'],
  34. ["Android.*OPR.VV","o_a",'c'],
  35. ["OPR.VV","o",'c'],
  36. ["YaBrowser.VV","y",'c'],
  37. ["SamsungBrowser.VV","samsung",'c'],
  38. ["Silk.VV","silk",'c'],
  39. ["Chrome.VV","c",'c'],
  40. ["Firefox.VV","f",'f'],
  41. [" OS.VV.*Safari","ios",'ios'],
  42. ["Version.VV.*Safari","s",'s'],
  43. ["Safari.VV","so",'s'],
  44. ["Opera.*Version.VV","o"],
  45. ["Opera.VV","o"]
  46. ];
  47. var VV="(\\d+\\.?\\d+\\.?\\d*\\.?\\d*)";
  48. for (var i=0; i < pats.length; i++) {
  49. if (ua.match(new RegExp(pats[i][0].replace("VV",VV),"i"))) {
  50. r.n=pats[i][1];
  51. r.engine=pats[i][2];
  52. break;
  53. }
  54. }
  55. r.fullv=RegExp.$1;
  56. r.v=parseFloat(r.fullv);
  57. // Special treatment of some systems
  58. //do not notify old systems since there is no up-to-date browser available
  59. if (/windows.nt.5.0|windows.nt.4.0|windows.95|windows.98|os x 10.2|os x 10.3|os x 10.4|os x 10.5/i.test(ua)) {
  60. r.no_device_update=true;
  61. r.available={}
  62. }
  63. //Safari on iOS 13 in Desktop mode
  64. if (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) {
  65. r.n="ios";
  66. r.engine='ios';
  67. r.fullv=r.v=13;
  68. r.no_device_update=true;//For now, never show a message, TODO!
  69. }
  70. //iOS
  71. if (/iphone|ipod|ipad|ios/i.test(ua)) {
  72. ua.match(new RegExp("OS."+VV,"i"));
  73. r.n="ios";
  74. r.fullv=RegExp.$1;
  75. r.v=parseFloat(r.fullv);
  76. r.engine='ios';
  77. var av=s.available_ios(ua,r.v);
  78. /*
  79. var newmap={10:"10.3.4",11:"12.4.3",12:"12.4.3",13:s.vsakt["ios"]};
  80. if (av in newmap)
  81. av=newmap[av];
  82. */
  83. if (av < 12 && Math.round(r.v)===11)// all devices with ios 11 support ios 12
  84. av=12
  85. r.available = {"ios": av};
  86. if (parseFloat(r.available.ios)<11)
  87. r.no_device_update=true;
  88. }
  89. //winxp/vista/2003
  90. if (/windows.nt.5.1|windows.nt.5.2|windows.nt.6.0/i.test(ua)) {
  91. r.available={"c":49.9,"f":52.9}
  92. }
  93. //old mac
  94. if (/os x 10.6/i.test(ua)) {
  95. r.available = {"s": "5.1.10", "c": 49.9, "f": 48}
  96. r.no_device_update=true;
  97. }
  98. if (/os x 10.7|os x 10.8/i.test(ua)) {
  99. r.available = {"s": "6.2.8", "c": 49.9, "f": 48}
  100. r.no_device_update=true;
  101. }
  102. if (/os x 10.9/i.test(ua))
  103. r.available.s="9.1.3"
  104. if (/os x 10.10/i.test(ua))
  105. r.available.s="10.1.2"
  106. //check for android stock browser
  107. if (ua.indexOf('Android')>-1 && r.n==="s") {
  108. var v=parseInt((/WebKit\/([0-9]+)/i.exec(ua) || 0)[1],10) || 2000;
  109. if (v <= 534) {
  110. r.n="a";
  111. r.fullv=r.v=v;
  112. r.is_insecure=true;
  113. }
  114. }
  115. // Special treatment of some browsers
  116. if (r.n==="so") {
  117. r.v=r.fullv=4.0;
  118. r.n="s";
  119. }
  120. if (r.n==="io") {
  121. r.n="i";
  122. if (r.v>6) r.v=11;
  123. else if (r.v>5) r.v=10;
  124. else if (r.v>4) r.v=9;
  125. else if (r.v>3.1) r.v=8;
  126. else if (r.v>3) r.v=7;
  127. else r.v=9;
  128. r.fullv=r.v;
  129. }
  130. r.t=s.names[r.n]+" "+r.v;
  131. r.is_supported=r.is_latest= !s.vsakt[r.n] ? undefined : s.less(r.fullv,s.vsakt[r.n])<=0;
  132. r.vmaj=Math.round(r.v);
  133. r.is_insecure= r.is_insecure|| !s.vsinsecure_below[r.n] ? undefined : s.less(r.fullv,s.vsinsecure_below[r.n])===1;
  134. if ((r.n==="f" && (r.vmaj===78)) || (r.n==="i" && r.vmaj===11)) {
  135. r.is_supported=true;
  136. r.is_insecure=false;
  137. if (r.n==="f")
  138. r.esr=true;
  139. }
  140. if (r.n==="ios" && r.v>10.3)
  141. r.is_supported=true;
  142. if (r.n==="a" || r.n==="x")
  143. r.t=s.names[r.n];
  144. if (r.n==="e") {
  145. r.t = s.names[r.n] + " " + r.vmaj;
  146. r.is_supported = s.less(r.fullv, "18.15063") != 1
  147. }
  148. if (r.n in ["c","f","o","e"] && s.less(r.fullv,parseFloat(s.vsakt[r.n])-1)<=0)
  149. r.is_supported=true; //mark also the version before the current version as supported to make the transitions smoother
  150. var releases_per_year={'f':7,'c':8,'o':8,'i':1,'e':1,'s':1}//,'v':1}
  151. if (releases_per_year[r.n]) {
  152. r.age_years=Math.round(((s.vsakt[r.n]-r.v)/releases_per_year[r.n])*10)/10 || 0
  153. }
  154. var engines={e:"Edge.VV",c:"Chrome.VV",f:"Firefox.VV",s:"Version.VV",i:"MSIE.VV","ios":" OS.VV"}
  155. if (r.engine) {
  156. ua.match(new RegExp(engines[r.engine].replace("VV",VV),"i"))
  157. r.engine_version=parseFloat(RegExp.$1)
  158. }
  159. return r
  160. }
  161. this.semver = function(vstr) {
  162. if (vstr instanceof Array)
  163. return vstr
  164. var x = (vstr+(".0.0.0")).split('.')
  165. return [parseInt(x[0]) || 0, parseInt(x[1]) || 0, parseInt(x[2]) || 0, parseInt(x[3]) || 0]
  166. }
  167. this.less= function(v1,v2) {
  168. //semantic version comparison: returns 1 if v1<v2 , 0 if equal, -1 if v1>v2
  169. v1=s.semver(v1)
  170. v2=s.semver(v2)
  171. for (var i=0; ;i++) {
  172. if (i>=v1.length) return i>=v2.length ? 0 : 1;
  173. if (i>=v2.length) return -1;
  174. var diff = v2[i]-v1[i]
  175. if (diff) return diff>0 ? 1 : -1;
  176. }
  177. }
  178. this.available_ios=function(ua,v) {
  179. var h = Math.max(window.screen.height, window.screen.width),pr = window.devicePixelRatio
  180. if (/ipad/i.test(ua)) {
  181. if (h == 1024 && pr == 2) // iPad 3 (iOS 9), 4, 5, Mini 2, Mini 3, Mini 4, Air, Air 2, Pro 9.7
  182. return 10//? only ipad 4 has ios 10, all other can have ios 11
  183. if (h == 1112)// iPad Pro 10.5
  184. return 15;
  185. if (h == 1366)//iPad Pro 12.9, Pro 12.9 (2nd Gen)
  186. return 15
  187. if (h == 1024 && v < 6)
  188. return 5 // iPad
  189. return 9 // iPad 2, iPad Mini
  190. }
  191. if (pr == 1)// 1/3G/3GS
  192. return 6//for 3GS
  193. if (h == 812)// && pr == 3)// X
  194. return 11 + 4
  195. if ((h == 736 || h == 667))// && pr == 3)// 6+/6s+/7+ and 8+ or // 6+/6s+/7+ and 8+ in zoom mode + // 6/6s/7 and 8
  196. return 12//latest version for iphone 6 is 12, 13 is for 6S
  197. if (h == 568) // 5/5C/5s/SE or 6/6s/7 and 8 in zoom mode
  198. return 10
  199. if (h == 480) // i4/4s
  200. return 7
  201. return 6
  202. }
  203. /*
  204. this.sub= function(v,minus) {
  205. //semantic version subtraction
  206. v=s.semver(v)
  207. minus=s.semver(minus)
  208. for (var i=0; ;i++) {
  209. if (i>=v.length||i>minus.length) break;
  210. v[i]-=v[minus];
  211. }
  212. return v.join('.')
  213. }
  214. */
  215. }
  216. window.$bu_getBrowser=$bu_.get_browser;
  217. var $buo = function(op,test) {
  218. var n = window.navigator,b;
  219. op=window._buorgres=op||{};
  220. var ll = op.l||(n.languages ? n.languages[0] : null) || n.language || n.browserLanguage || n.userLanguage||document.documentElement.getAttribute("lang")||"en";
  221. op.llfull=ll.replace("_","-").toLowerCase().substr(0,5);
  222. op.ll=op.llfull.substr(0,2);
  223. op.domain=op.domain!==undefined?op.domain:(/file:/.test(location.href)?"https:":"")+"//browser-update.org";
  224. op.apiver=op.api||op.c||-1;
  225. op.jsv=$bu_.version;
  226. var required_min=(op.apiver<2018&&{i:10,f:11,o:21,s:8,c:30})||{};
  227. var vs=op.notify||op.vs||{};//legacy config: maximum version to notify
  228. vs.e=vs.e||vs.i;
  229. vs.i=vs.i||vs.e;
  230. var required=op.required||{};//minimum browser versions needed
  231. required.e=required.e||required.i;
  232. if (!required.i) {
  233. required.i=required.e;
  234. $bu_.vsakt.i=$bu_.vsakt.e;
  235. }
  236. for (b in $bu_.vsdefault) {
  237. if (vs[b]) {//legacy style config: browsers to notify
  238. if ($bu_.less(vs[b],0)>=0) // required <= 0
  239. required[b]= parseFloat($bu_.vsakt[b])+parseFloat(vs[b])+0.01
  240. else
  241. required[b] = parseFloat(vs[b]) + 0.01
  242. }
  243. if (!(b in required) || required[b]==null)
  244. required[b]=$bu_.vsdefault[b]
  245. if ($bu_.less(required[b],0)>=0) // case for required <= 0 --> relative to latest version
  246. required[b]=parseFloat($bu_.vsakt[b])+parseFloat(required[b]) // TODO: make it work for string version
  247. if (required_min[b] && $bu_.less(required[b],required_min[b])===1) // required < required_min
  248. required[b]=required_min[b]
  249. }
  250. required.ios=required.ios||required.s;
  251. if (required.i<79 && required.i>65)
  252. required.i=required.i-60
  253. if (required.e<79 && required.e>65)
  254. required.e=required.e-60
  255. op.required=required;
  256. op.reminder=op.reminder<0.1 ? 0 : op.reminder||(24*7);
  257. op.reminderClosed=op.reminderClosed<1 ? 0 : op.reminderClosed||(24*7);
  258. op.onshow = op.onshow||function(o){};
  259. op.onclick = op.onclick||function(o){};
  260. op.onclose = op.onclose||function(o){};
  261. op.pageurl = op.pageurl || location.hostname || "x";
  262. op.newwindow=(op.newwindow!==false);
  263. op.test=test||op.test||(location.hash==="#test-bu")||false;
  264. op.ignorecookie=op.ignorecookie||location.hash==="#ignorecookie-bu";
  265. op.reasons=[];
  266. op.hide_reasons=[];
  267. function check_show(op) {
  268. var bb=op.browser=$bu_.get_browser(op.override_ua);
  269. op.is_below_required = required[bb.n] && $bu_.less(bb.fullv,required[bb.n])===1; //bb.fullv<required
  270. if (bb.other!==false)
  271. op.hide_reasons.push("is other browser:" + bb.other)
  272. if (bb.embedded!==false)
  273. op.hide_reasons.push("is embedded browser:" + bb.embedded)
  274. if ( bb.esr && !op.notify_esr)// || (bb.is_supported && !op.notify_also_supported))
  275. op.hide_reasons.push("Extended support (ESR)")
  276. if (bb.mobile&&op.mobile===false)
  277. op.hide_reasons.push("do not notify mobile")
  278. if (bb.is_latest)//the latest versions of a browser can not be notified
  279. op.hide_reasons.push("is latest version of the browser")
  280. if (bb.no_device_update)
  281. op.hide_reasons.push("no device update")
  282. if (op.is_below_required)
  283. op.reasons.push("below required")
  284. if ((op.insecure||op.unsecure) && bb.is_insecure)
  285. op.reasons.push("insecure")
  286. if (op.unsupported && !bb.is_supported)
  287. op.reasons.push("no vendor support")
  288. if (op.hide_reasons.length>0)
  289. return false
  290. if (op.reasons.length>0)
  291. return true
  292. return false
  293. }
  294. op.notified=check_show(op);
  295. op.already_shown=document.cookie.indexOf("browserupdateorg=pause")>-1 && !op.ignorecookie;
  296. if (!op.test && (!op.notified || op.already_shown))
  297. return;
  298. op.setCookie=function(hours) { //sets a cookie that the user has already seen the notification, closed it or permanently wants to hide it. No information on the user is stored.
  299. document.cookie = 'browserupdateorg=pause; expires='+(new Date(new Date().getTime()+3600000*hours)).toGMTString()+'; path=/; SameSite=Lax';
  300. };
  301. if (op.already_shown && (op.ignorecookie || op.test))
  302. op.setCookie(-10)// remove old cookies if in test mode
  303. if (op.reminder>0)
  304. op.setCookie(op.reminder);
  305. if (op.nomessage) {
  306. op.onshow(op);
  307. return;
  308. }
  309. var e=document.createElement("script");
  310. e.src = op.jsshowurl||op.domain+"/update.show.min.js";
  311. document.body.appendChild(e);
  312. };
  313. if( typeof( module ) !== 'undefined' ) {
  314. module.exports = $buo;
  315. }