Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * User agent test suite.
  19   *
  20   * @package    core
  21   * @copyright  2013 Sam Hemelryk
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   * @covers \core_useragent
  24   */
  25  class useragent_test extends advanced_testcase {
  26  
  27      /**
  28       * Restores the user agent to the default one.
  29       */
  30      public function tearDown(): void {
  31          core_useragent::instance(true);
  32      }
  33  
  34      /**
  35       * Data provider for known user agents.
  36       *
  37       * @return array
  38       */
  39      public function user_agents_providers() {
  40          // Note: When adding new entries to this list, please ensure that any new browser versions are added to the corresponding list.
  41          // This ensures that regression tests are applied to all known user agents.
  42          return array(
  43              'Microsoft Edge for Windows 10 Desktop' => array(
  44                  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136',
  45                  array(
  46                      'is_edge'                       => true,
  47                      'check_edge_version'            => array(
  48                          '12'                        => true,
  49                      ),
  50  
  51                      // Edge pretends to be WebKit.
  52                      'is_webkit'                     => true,
  53  
  54                      // Edge pretends to be Chrome.
  55                      // Note: Because Edge pretends to be Chrome, it will not be picked up as a Safari browser.
  56                      'is_chrome'                     => true,
  57                      'check_chrome_version'          => array(
  58                          '7'                         => true,
  59                          '8'                         => true,
  60                          '10'                        => true,
  61                          '39'                        => true,
  62                      ),
  63  
  64                      'versionclasses'                => array(
  65                          'edge',
  66                      ),
  67                  ),
  68              ),
  69              'Microsoft Edge for Windows 10 Mobile' => array(
  70                  'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.10136',
  71                  array(
  72                      'is_edge'                       => true,
  73                      'check_edge_version'              => array(
  74                          '12'                        => true,
  75                      ),
  76  
  77                      // Edge pretends to be WebKit.
  78                      'is_webkit'                     => true,
  79  
  80                      // Mobile Edge pretends to be Android.
  81                      'is_webkit_android'             => true,
  82                      'check_webkit_android_version'  => array(
  83                          '525'                       => true,
  84                          '527'                       => true,
  85                      ),
  86  
  87                      // Edge pretends to be Chrome.
  88                      // Note: Because Edge pretends to be Chrome, it will not be picked up as a Safari browser.
  89                      'is_chrome'                     => true,
  90                      'check_chrome_version'          => array(
  91                          '7'                         => true,
  92                          '8'                         => true,
  93                          '10'                        => true,
  94                          '39'                        => true,
  95                      ),
  96  
  97                      'versionclasses'                => array(
  98                          'edge'
  99                      ),
 100  
 101                      'devicetype'                    => 'mobile',
 102                  ),
 103              ),
 104              // Windows 98; Internet Explorer 5.0.
 105              array(
 106                  'Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)',
 107                  array(
 108                      // MSIE 5.0 is not considered a browser at all: known false results.
 109                      'is_ie'                         => false,
 110                      'check_ie_version'              => array(
 111                          '0'                         => true,
 112                          '5.0'                       => true,
 113                      ),
 114                      'versionclasses'                => array(
 115                          // IE 5.0 is not considered a browser.
 116                      ),
 117  
 118                      // IE 5.0 is a legacy browser.
 119                      'devicetype'                    => 'legacy',
 120  
 121                      'supports_svg'                  => false,
 122                      'supports_json_contenttype'     => false,
 123                  ),
 124              ),
 125  
 126              // Windows 2000; Internet Explorer 5.5.
 127              array(
 128                  'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)',
 129                  array(
 130                      'is_ie'                         => true,
 131                      'check_ie_version'              => array(
 132                          '0'                         => true,
 133                          '5.0'                       => true,
 134                          '5.5'                       => true,
 135                      ),
 136                      'versionclasses'                => array(
 137                          'ie',
 138                      ),
 139  
 140                      // IE 6.0 is a legacy browser.
 141                      'devicetype'                    => 'legacy',
 142  
 143                      'supports_svg'                  => false,
 144                      'supports_json_contenttype'     => false,
 145                  ),
 146              ),
 147  
 148              // Windows XP SP2; Internet Explorer 6.0.
 149              array(
 150                  'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
 151                  array(
 152                      'is_ie'                         => true,
 153                      'check_ie_version'              => array(
 154                          '0'                         => true,
 155                          '5.0'                       => true,
 156                          '5.5'                       => true,
 157                          '6.0'                       => true,
 158                      ),
 159                      'versionclasses'                => array(
 160                          'ie',
 161                          'ie6',
 162                      ),
 163  
 164                      // IE 7.0 is a legacy browser.
 165                      'devicetype'                    => 'legacy',
 166  
 167                      'supports_svg'                  => false,
 168                      'supports_json_contenttype'     => false,
 169                  ),
 170              ),
 171  
 172              // Windows XP SP2; Internet Explorer 7.0.
 173              array(
 174                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
 175                  array(
 176                      'is_ie'                         => true,
 177                      'check_ie_version'              => array(
 178                          '0'                         => true,
 179                          '5.0'                       => true,
 180                          '5.5'                       => true,
 181                          '6.0'                       => true,
 182                          '7.0'                       => true,
 183                      ),
 184                      'versionclasses'                => array(
 185                          'ie',
 186                          'ie7',
 187                      ),
 188  
 189                      'supports_svg'                  => false,
 190                      'supports_json_contenttype'     => false,
 191                  ),
 192              ),
 193  
 194              // Windows XP SP2; Internet Explorer 7.0; Meridio extension.
 195              array(
 196                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Meridio for Excel 5.0.251; Meridio for PowerPoint 5.0.251; Meridio for Word 5.0.251; Meridio Protocol; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)',
 197                  array(
 198                      'is_ie'                         => true,
 199                      'check_ie_version'              => array(
 200                          '0'                         => true,
 201                          '5.0'                       => true,
 202                          '5.5'                       => true,
 203                          '6.0'                       => true,
 204                          '7.0'                       => true,
 205                      ),
 206                      'versionclasses'                => array(
 207                          'ie',
 208                          'ie7',
 209                      ),
 210  
 211                      'supports_svg'                  => false,
 212                      'supports_json_contenttype'     => false,
 213                  ),
 214              ),
 215  
 216              // Windows Vista; Internet Explorer 8.0.
 217              array(
 218                  'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)',
 219                  array(
 220                      'is_ie'                         => true,
 221                      'check_ie_version'              => array(
 222                          '0'                         => true,
 223                          '5.0'                       => true,
 224                          '5.5'                       => true,
 225                          '6.0'                       => true,
 226                          '7.0'                       => true,
 227                          '8.0'                       => true,
 228                      ),
 229                      'versionclasses'                => array(
 230                          'ie',
 231                          'ie8',
 232                      ),
 233  
 234                      'supports_svg'                  => false,
 235                  ),
 236              ),
 237  
 238              // Windows 7; Internet Explorer 9.0.
 239              array(
 240                  'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
 241                  array(
 242                      'is_ie'                         => true,
 243                      'check_ie_version'              => array(
 244                          '0'                         => true,
 245                          '5.0'                       => true,
 246                          '5.5'                       => true,
 247                          '6.0'                       => true,
 248                          '7.0'                       => true,
 249                          '8.0'                       => true,
 250                          '9.0'                       => true,
 251                      ),
 252                      'versionclasses'                => array(
 253                          'ie',
 254                          'ie9',
 255                      ),
 256                  ),
 257              ),
 258  
 259              // Windows 7; Internet Explorer 9.0i.
 260              array(
 261                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)',
 262                  array(
 263                      'is_ie'                         => true,
 264                      'check_ie_version'              => array(
 265                          '0'                         => true,
 266                          '5.0'                       => true,
 267                          '5.5'                       => true,
 268                          '6.0'                       => true,
 269                          '7.0'                       => true,
 270                          '8.0'                       => true,
 271                          '9.0'                       => true,
 272                      ),
 273                      'versionclasses'                => array(
 274                          'ie',
 275                          'ie9',
 276                      ),
 277                      'iecompatibility'               => true,
 278  
 279                      // IE 9 in Compatiblity mode does not support SVG.
 280                      'supports_svg'                  => false,
 281  
 282                      // IE in Compatiblity mode does not support JSON ContentType.
 283                      'supports_json_contenttype'     => false,
 284                  ),
 285              ),
 286  
 287              // Windows 8; Internet Explorer 10.0.
 288              array(
 289                  'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)',
 290                  array(
 291                      'is_ie'                         => true,
 292                      'check_ie_version'              => array(
 293                          '0'                         => true,
 294                          '5.0'                       => true,
 295                          '5.5'                       => true,
 296                          '6.0'                       => true,
 297                          '7.0'                       => true,
 298                          '8.0'                       => true,
 299                          '9.0'                       => true,
 300                          '10'                        => true,
 301                      ),
 302                      'versionclasses'                => array(
 303                          'ie',
 304                          'ie10',
 305                      ),
 306                  ),
 307              ),
 308  
 309              // Windows 8; Internet Explorer 10.0i.
 310              array(
 311                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Trident/6.0; Touch; .NET4.0E; .NET4.0C; Tablet PC 2.0)',
 312                  array(
 313                      'is_ie'                         => true,
 314                      'check_ie_version'              => array(
 315                          '0'                         => true,
 316                          '5.0'                       => true,
 317                          '5.5'                       => true,
 318                          '6.0'                       => true,
 319                          '7.0'                       => true,
 320                          '8.0'                       => true,
 321                          '9.0'                       => true,
 322                          '10'                        => true,
 323                      ),
 324                      'iecompatibility'               => true,
 325                      'versionclasses'                => array(
 326                          'ie',
 327                          'ie10',
 328                      ),
 329  
 330                      // IE in Compatiblity mode does not support JSON ContentType.
 331                      'supports_json_contenttype'     => false,
 332                  ),
 333              ),
 334  
 335              // Windows 8.1; Internet Explorer 11.0.
 336              array(
 337                  'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0)',
 338                  array(
 339                      'is_ie'                         => true,
 340                      'check_ie_version'              => array(
 341                          '0'                         => true,
 342                          '5.0'                       => true,
 343                          '5.5'                       => true,
 344                          '6.0'                       => true,
 345                          '7.0'                       => true,
 346                          '8.0'                       => true,
 347                          '9.0'                       => true,
 348                          '10'                        => true,
 349                          '11'                        => true,
 350                      ),
 351                      'versionclasses'                => array(
 352                          'ie',
 353                          'ie11',
 354                      ),
 355                  ),
 356              ),
 357  
 358              // Windows 8.1; Internet Explorer 11.0i.
 359              array(
 360                  ' Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)',
 361                  array(
 362                      'is_ie'                         => true,
 363                      'check_ie_version'              => array(
 364                          '0'                         => true,
 365                          '5.0'                       => true,
 366                          '5.5'                       => true,
 367                          '6.0'                       => true,
 368                          '7.0'                       => true,
 369                          '8.0'                       => true,
 370                          '9.0'                       => true,
 371                          '10'                        => true,
 372                          '11'                        => true,
 373                      ),
 374                      'iecompatibility'               => true,
 375                      'versionclasses'                => array(
 376                          'ie',
 377                          'ie11',
 378                      ),
 379  
 380                      // IE in Compatiblity mode does not support JSON ContentType.
 381                      'supports_json_contenttype'     => false,
 382                  ),
 383              ),
 384  
 385              // Windows XP; Firefox 1.0.6.
 386              array(
 387                  'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6',
 388                  array(
 389                      'is_firefox'                    => true,
 390  
 391                      'is_gecko'                      => true,
 392                      'check_gecko_version'           => array(
 393                          '1'                         => true,
 394                      ),
 395  
 396                      'versionclasses'                => array(
 397                          'gecko',
 398                          'gecko17',
 399                      ),
 400                  ),
 401              ),
 402  
 403              // Windows XP; Firefox 1.0.6.
 404              array(
 405                  'Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5',
 406                  array(
 407                      'is_firefox'                    => true,
 408                      'check_firefox_version'         => array(
 409                          '1.5'                       => true,
 410                      ),
 411  
 412                      'is_gecko'                      => true,
 413                      'check_gecko_version'           => array(
 414                          '1'                         => true,
 415                          '20030516'                  => true,
 416                          '20051116'                  => true,
 417                      ),
 418  
 419                      'versionclasses'                => array(
 420                          'gecko',
 421                          'gecko18',
 422                      ),
 423                  ),
 424              ),
 425  
 426              // Windows XP; Firefox 1.5.0.1.
 427              array(
 428                  'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1',
 429                  array(
 430                      'is_firefox'                    => true,
 431                      'check_firefox_version'         => array(
 432                          '1.5'                       => true,
 433                      ),
 434  
 435                      'is_gecko'                      => true,
 436                      'check_gecko_version'           => array(
 437                          '1'                         => true,
 438                          '20030516'                  => true,
 439                          '20051116'                  => true,
 440                      ),
 441  
 442                      'versionclasses'                => array(
 443                          'gecko',
 444                          'gecko18',
 445                      ),
 446                  ),
 447              ),
 448  
 449              // Windows XP; Firefox 2.0.
 450              array(
 451                  'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1',
 452                  array(
 453                      'is_firefox'                    => true,
 454                      'check_firefox_version'         => array(
 455                          '1.5'                       => true,
 456                      ),
 457  
 458                      'is_gecko'                      => true,
 459                      'check_gecko_version'           => array(
 460                          '1'                         => true,
 461                          '2'                         => true,
 462                          '20030516'                  => true,
 463                          '20051116'                  => true,
 464                          '2006010100'                => true,
 465                      ),
 466  
 467                      'versionclasses'                => array(
 468                          'gecko',
 469                          'gecko18',
 470                      ),
 471                  ),
 472              ),
 473  
 474              // Ubuntu Linux amd64; Firefox 2.0.
 475              array(
 476                  'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1) Gecko/20060601 Firefox/2.0 (Ubuntu-edgy)',
 477                  array(
 478                      'is_firefox'                    => true,
 479                      'check_firefox_version'         => array(
 480                          '1.5'                       => true,
 481                      ),
 482  
 483                      'is_gecko'                      => true,
 484                      'check_gecko_version'           => array(
 485                          '1'                         => true,
 486                          '2'                         => true,
 487                          '20030516'                  => true,
 488                          '20051116'                  => true,
 489                          '2006010100'                => true,
 490                      ),
 491  
 492                      'versionclasses'                => array(
 493                          'gecko',
 494                          'gecko18',
 495                      ),
 496                  ),
 497              ),
 498  
 499              // SUSE; Firefox 3.0.6.
 500              array(
 501                  'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.6) Gecko/2009012700 SUSE/3.0.6-1.4 Firefox/3.0.6',
 502                  array(
 503                      'is_firefox'                    => true,
 504                      'check_firefox_version'         => array(
 505                          '1.5'                       => true,
 506                          '3.0'                       => true,
 507                      ),
 508  
 509                      'is_gecko'                      => true,
 510                      'check_gecko_version'           => array(
 511                          '1'                         => true,
 512                          '2'                         => true,
 513                          '20030516'                  => true,
 514                          '20051116'                  => true,
 515                          '2006010100'                => true,
 516                      ),
 517  
 518                      'versionclasses'                => array(
 519                          'gecko',
 520                          'gecko19',
 521                      ),
 522                  ),
 523              ),
 524  
 525              // Linux i686; Firefox 3.6.
 526              array(
 527                  'Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/3.6',
 528                  array(
 529                      'is_firefox'                    => true,
 530                      'check_firefox_version'         => array(
 531                          '1.5'                       => true,
 532                          '3.0'                       => true,
 533                      ),
 534  
 535                      'is_gecko'                      => true,
 536                      'check_gecko_version'           => array(
 537                          '1'                         => true,
 538                          '2'                         => true,
 539                          '20030516'                  => true,
 540                          '20051116'                  => true,
 541                          '2006010100'                => true,
 542                          '3.6'                       => true,
 543                          '20100101'                  => true,
 544                      ),
 545  
 546                      'versionclasses'                => array(
 547                          'gecko',
 548                          'gecko20',
 549                      ),
 550                  ),
 551              ),
 552  
 553              // Windows; Firefox 11.0.
 554              array(
 555                  'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko Firefox/11.0',
 556                  array(
 557                      'is_firefox'                    => true,
 558                      'check_firefox_version'         => array(
 559                          '1.5'                       => true,
 560                          '3.0'                       => true,
 561                          '4'                         => true,
 562                          '10'                        => true,
 563                      ),
 564  
 565                      'is_gecko'                      => true,
 566                      'check_gecko_version'           => array(
 567                          '1'                         => true,
 568                          '2'                         => true,
 569                          '20030516'                  => true,
 570                          '20051116'                  => true,
 571                          '2006010100'                => true,
 572                          '20100101'                  => true,
 573                          '3.6'                       => true,
 574                          '4.0'                       => true,
 575                      ),
 576  
 577                      'versionclasses'                => array(
 578                          'gecko',
 579                      ),
 580                  ),
 581              ),
 582  
 583              // Windows; Firefox 15.0a2.
 584              array(
 585                  'Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2',
 586                  array(
 587                      'is_firefox'                    => true,
 588                      'check_firefox_version'         => array(
 589                          '1.5'                       => true,
 590                          '3.0'                       => true,
 591                          '4'                         => true,
 592                          '10'                        => true,
 593                          '15'                        => true,
 594                      ),
 595  
 596                      'is_gecko'                      => true,
 597                      'check_gecko_version'           => array(
 598                          '1'                         => true,
 599                          '2'                         => true,
 600                          '20030516'                  => true,
 601                          '20051116'                  => true,
 602                          '2006010100'                => true,
 603                          '20100101'                  => true,
 604                          '3.6'                       => true,
 605                          '4.0'                       => true,
 606                          '15.0'                      => true,
 607                      ),
 608  
 609                      'versionclasses'                => array(
 610                          'gecko',
 611                      ),
 612                  ),
 613              ),
 614  
 615              // Firefox 18; Mac OS X 10.
 616              array(
 617                  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/18.0 Firefox/18.0',
 618                  array(
 619                      'is_firefox'                    => true,
 620                      'check_firefox_version'         => array(
 621                          '1.5'                       => true,
 622                          '3.0'                       => true,
 623                          '4'                         => true,
 624                          '10'                        => true,
 625                          '15'                        => true,
 626                          '18'                        => true,
 627                      ),
 628  
 629                      'is_gecko'                      => true,
 630                      'check_gecko_version'           => array(
 631                          '1'                         => true,
 632                          '2'                         => true,
 633                          '20030516'                  => true,
 634                          '20051116'                  => true,
 635                          '2006010100'                => true,
 636                          '3.6'                       => true,
 637                          '4.0'                       => true,
 638                          '15.0'                      => true,
 639                          '18.0'                      => true,
 640                          '20100101'                  => true,
 641                      ),
 642  
 643                      'versionclasses'                => array(
 644                          'gecko',
 645                      ),
 646                  ),
 647              ),
 648  
 649              // Firefox 33; Mac OS X 10.10.
 650              array(
 651                  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:33.0) Gecko/20100101 Firefox/33.0',
 652                  array(
 653                      'is_firefox'                    => true,
 654                      'check_firefox_version'         => array(
 655                          '1.5'                       => true,
 656                          '3.0'                       => true,
 657                          '4'                         => true,
 658                          '10'                        => true,
 659                          '15'                        => true,
 660                          '18'                        => true,
 661                          '19'                        => true,
 662                          '33'                        => true,
 663                      ),
 664  
 665                      'is_gecko'                      => true,
 666                      'check_gecko_version'           => array(
 667                          '1'                         => true,
 668                          '2'                         => true,
 669                          '20030516'                  => true,
 670                          '20051116'                  => true,
 671                          '2006010100'                => true,
 672                          '3.6'                       => true,
 673                          '4.0'                       => true,
 674                          '15.0'                      => true,
 675                          '18.0'                      => true,
 676                          '19.0'                      => true,
 677                          '20100101'                  => true,
 678                      ),
 679  
 680                      'versionclasses'                => array(
 681                          'gecko',
 682                      ),
 683                  ),
 684              ),
 685  
 686              // SeaMonkey 2.0; Windows.
 687              array(
 688                  'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b3pre) Gecko/20081208 SeaMonkey/2.0',
 689                  array(
 690                      'is_gecko'                      => true,
 691                      'check_gecko_version'           => array(
 692                          '1'                         => true,
 693                          '2'                         => true,
 694                          '20030516'                  => true,
 695                          '20051106'                  => true,
 696                          '20051116'                  => true,
 697                          '2006010100'                => true,
 698                      ),
 699  
 700                      'versionclasses'                => array(
 701                          'gecko',
 702                          'gecko19',
 703                      ),
 704                  ),
 705              ),
 706  
 707              // SeaMonkey 2.1; Linux.
 708              array(
 709                  'Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20110609 Firefox/4.0.1 SeaMonkey/2.1',
 710                  array(
 711                      'is_gecko'                      => true,
 712                      'check_gecko_version'           => array(
 713                          '1'                         => true,
 714                          '2'                         => true,
 715                          '20030516'                  => true,
 716                          '20051116'                  => true,
 717                          '2006010100'                => true,
 718                          '20100101'                  => true,
 719                          '3.6'                       => true,
 720                          '4.0'                       => true,
 721                      ),
 722  
 723                      'is_firefox'                    => true,
 724                      'check_firefox_version'         => array(
 725                          '1.5'                       => true,
 726                          '3.0'                       => true,
 727                          '4'                         => true,
 728                      ),
 729  
 730                      'versionclasses'                => array(
 731                          'gecko',
 732                          'gecko20',
 733                      ),
 734                  ),
 735              ),
 736  
 737              // SeaMonkey 2.3; FreeBSD.
 738              array(
 739                  'Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0) Gecko/20110818 Firefox/6.0 SeaMonkey/2.3',
 740                  array(
 741                      'is_gecko'                      => true,
 742                      'check_gecko_version'           => array(
 743                          '1'                         => true,
 744                          '2'                         => true,
 745                          '20030516'                  => true,
 746                          '20051116'                  => true,
 747                          '2006010100'                => true,
 748                          '20100101'                  => true,
 749                          '3.6'                       => true,
 750                          '4.0'                       => true,
 751                      ),
 752  
 753                      'is_firefox'                    => true,
 754                      'check_firefox_version'         => array(
 755                          '1.5'                       => true,
 756                          '3.0'                       => true,
 757                          '4'                         => true,
 758                      ),
 759  
 760                      'versionclasses'                => array(
 761                          'gecko',
 762                      ),
 763                  ),
 764              ),
 765  
 766              // Windows 7; MS Word 2010.
 767              array(
 768                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; ms-office)',
 769                  array(
 770                      'is_ie'                         => true,
 771                      'check_ie_version'              => array(
 772                          '0'                         => true,
 773                          '5.0'                       => true,
 774                          '5.5'                       => true,
 775                          '6.0'                       => true,
 776                          '7.0'                       => true,
 777                          '8.0'                       => true,
 778                      ),
 779                      'iecompatibility'               => true,
 780                      'versionclasses'                => array(
 781                          'ie',
 782                          'ie8',
 783                      ),
 784  
 785                      'is_msword'                     => true,
 786  
 787                      'supports_svg'                  => false,
 788                      'supports_json_contenttype'     => false,
 789                  ),
 790              ),
 791  
 792              // Windows 7; MS Outlook 2010.
 793              array(
 794                  'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; Microsoft Outlook 14.0.7113; ms-office; MSOffice 14)',
 795                  array(
 796                      'is_ie'                         => true,
 797                      'check_ie_version'              => array(
 798                          '0'                         => true,
 799                          '5.0'                       => true,
 800                          '5.5'                       => true,
 801                          '6.0'                       => true,
 802                          '7.0'                       => true,
 803                          '8.0'                       => true,
 804                      ),
 805                      'iecompatibility'               => true,
 806                      'versionclasses'                => array(
 807                          'ie',
 808                          'ie8',
 809                      ),
 810  
 811                      // Note: Outlook is deliberately not considered to be MS Word.
 812                      'is_msword'                     => false,
 813  
 814                      'supports_svg'                  => false,
 815                      'supports_json_contenttype'     => false,
 816                  ),
 817              ),
 818  
 819              // Mac OS X; MS Word 14.
 820              array(
 821                  'Mozilla/5.0 (Macintosh; Intel Mac OS X) Word/14.38.0',
 822                  array(
 823                      'versionclasses'                => array(
 824                      ),
 825  
 826                      'is_msword'                     => true,
 827                  ),
 828              ),
 829  
 830              // Safari 312; Max OS X.
 831              array(
 832                  'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312',
 833                  array(
 834                      'is_safari'                     => true,
 835                      'check_safari_version'          => array(
 836                          '1'                         => true,
 837                          '312'                       => true,
 838                      ),
 839  
 840                      'is_webkit'                     => true,
 841  
 842                      'versionclasses'                => array(
 843                          'safari',
 844                      ),
 845                  ),
 846              ),
 847  
 848              // Safari 412; Max OS X.
 849              array(
 850                  'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412',
 851                  array(
 852                      'is_safari'                     => true,
 853                      'check_safari_version'          => array(
 854                          '1'                         => true,
 855                          '312'                       => true,
 856                      ),
 857  
 858                      'is_webkit'                     => true,
 859  
 860                      'versionclasses'                => array(
 861                          'safari',
 862                      ),
 863                  ),
 864              ),
 865  
 866              // Safari 2.0; Max OS X.
 867              array(
 868                  'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412',
 869                  array(
 870                      'is_safari'                     => true,
 871                      'check_safari_version'          => array(
 872                          '1'                         => true,
 873                          '312'                       => true,
 874                      ),
 875  
 876                      'is_webkit'                     => true,
 877  
 878                      'versionclasses'                => array(
 879                          'safari',
 880                      ),
 881                  ),
 882              ),
 883  
 884              // iOS Safari 528; iPhone.
 885              array(
 886                  'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; cs-cz) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16',
 887                  array(
 888                      // Note: We do *not* identify mobile Safari as Safari.
 889                      'is_safari_ios'                 => true,
 890                      'is_ios'                        => true,
 891                      'check_safari_ios_version'      => array(
 892                          '527'                       => true,
 893                      ),
 894  
 895                      'is_webkit'                     => true,
 896  
 897                      'versionclasses'                => array(
 898                          'ios'
 899                      ),
 900  
 901                      'devicetype'                    => 'mobile',
 902                 ),
 903              ),
 904  
 905              // Safari; iPhone 6 Plus; iOS 8.1; Build 12B411.
 906              array(
 907                  'Mozilla/5.0 (iPhone; CPU iPhone OS 10_10 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4',
 908                  array(
 909                      // Note: We do *not* identify mobile Safari as Safari.
 910                      'is_safari_ios'                 => true,
 911                      'is_ios'                        => true,
 912                      'check_safari_ios_version'      => array(
 913                          '527'                       => true,
 914                          '590'                       => true,
 915                          '600'                       => true,
 916                      ),
 917  
 918                      'is_webkit'                     => true,
 919  
 920                      'versionclasses'                => array(
 921                          'ios',
 922                      ),
 923  
 924                      'devicetype'                    => 'mobile',
 925                 ),
 926              ),
 927  
 928              // iOS Safari 533; iPad.
 929              array(
 930                  'Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5',
 931                  array(
 932                      // Note: We do *not* identify mobile Safari as Safari.
 933                      'is_safari_ios'                 => true,
 934                      'is_ios'                        => true,
 935                      'check_safari_ios_version'      => array(
 936                          '527'                       => true,
 937                      ),
 938  
 939                      'is_webkit'                     => true,
 940  
 941                      'versionclasses'                => array(
 942                          'ios',
 943                      ),
 944  
 945                      'devicetype'                    => 'tablet',
 946                 ),
 947              ),
 948  
 949              // Android WebKit 525; G1 Phone.
 950              'Android WebKit 525; G1 Phone' => array(
 951                  'Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 – G1 Phone',
 952                  array(
 953                      'is_webkit_android'             => true,
 954                      'check_webkit_android_version'  => array(
 955                          '525'                       => true,
 956                      ),
 957  
 958                      'is_webkit'                     => true,
 959  
 960                      'versionclasses'                => array(
 961                          'android',
 962                      ),
 963  
 964                      'devicetype'                    => 'mobile',
 965  
 966                      'supports_svg'                  => false,
 967                 ),
 968              ),
 969  
 970              // Android WebKit 530; Nexus.
 971              'Android WebKit 530; Nexus' => array(
 972                  'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 –Nexus',
 973                  array(
 974                      'is_webkit_android'             => true,
 975                      'check_webkit_android_version'  => array(
 976                          '525'                       => true,
 977                          '527'                       => true,
 978                      ),
 979  
 980                      'is_webkit'                     => true,
 981  
 982                      'versionclasses'                => array(
 983                          'android',
 984                      ),
 985  
 986                      'devicetype'                    => 'mobile',
 987  
 988                      'supports_svg'                  => false,
 989                 ),
 990              ),
 991  
 992              // Android WebKit 537; Samsung GT-9505.
 993              array(
 994                  'Mozilla/5.0 (Linux; Android 4.3; it-it; SAMSUNG GT-I9505/I9505XXUEMJ7 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36',
 995                  array(
 996                      'is_webkit_android'             => true,
 997                      'check_webkit_android_version'  => array(
 998                          '525'                       => true,
 999                          '527'                       => true,
1000                      ),
1001  
1002                      'is_webkit'                     => true,
1003  
1004                      'is_chrome'                     => true,
1005                      'check_chrome_version'          => array(
1006                          '7'                         => true,
1007                          '8'                         => true,
1008                          '10'                        => true,
1009                      ),
1010  
1011                      'versionclasses'                => array(
1012                          'chrome',
1013                          'android',
1014                      ),
1015  
1016                      'devicetype'                    => 'mobile',
1017                  ),
1018              ),
1019  
1020              // Android WebKit 537; Nexus 5.
1021              array(
1022                  'Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Mobile Safari/537.36',
1023                  array(
1024                      'is_webkit_android'             => true,
1025                      'check_webkit_android_version'  => array(
1026                          '525'                       => true,
1027                          '527'                       => true,
1028                      ),
1029  
1030                      'is_webkit'                     => true,
1031  
1032                      'is_chrome'                     => true,
1033                      'check_chrome_version'          => array(
1034                          '7'                         => true,
1035                          '8'                         => true,
1036                          '10'                        => true,
1037                      ),
1038  
1039                      'versionclasses'                => array(
1040                          'chrome',
1041                          'android',
1042                      ),
1043  
1044                      'devicetype'                    => 'mobile',
1045                  ),
1046              ),
1047  
1048              // Chrome 8; Mac OS X.
1049              array(
1050                  'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10',
1051                  array(
1052                      'is_chrome'                     => true,
1053                      'check_chrome_version'          => array(
1054                          '7'                         => true,
1055                          '8'                         => true,
1056                      ),
1057  
1058                      'is_webkit'                     => true,
1059  
1060                      'versionclasses'                => array(
1061                          'chrome',
1062                      ),
1063                  ),
1064              ),
1065  
1066              // Chrome 39; Mac OS X.
1067              array(
1068                  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
1069                  array(
1070                      'is_chrome'                     => true,
1071                      'check_chrome_version'          => array(
1072                          '7'                         => true,
1073                          '8'                         => true,
1074                          '10'                        => true,
1075                          '39'                        => true,
1076                      ),
1077  
1078                      'is_webkit'                     => true,
1079  
1080                      'versionclasses'                => array(
1081                          'chrome',
1082                      ),
1083                  ),
1084              ),
1085  
1086              // Opera 8.51; Windows XP.
1087              array(
1088                  'Opera/8.51 (Windows NT 5.1; U; en)',
1089                  array(
1090                      'is_opera'                      => true,
1091                      'check_opera_version'           => array(
1092                          '8.0'                       => true,
1093                      ),
1094  
1095                      'versionclasses'                => array(
1096                          'opera',
1097                      ),
1098  
1099                      'supports_svg'                  => false,
1100                 ),
1101              ),
1102  
1103              // Opera 9.0; Windows XP.
1104              array(
1105                  'Opera/9.0 (Windows NT 5.1; U; en)',
1106                  array(
1107                      'is_opera'                      => true,
1108                      'check_opera_version'           => array(
1109                          '8.0'                       => true,
1110                          '9.0'                       => true,
1111                      ),
1112  
1113                      'versionclasses'                => array(
1114                          'opera',
1115                      ),
1116  
1117                      'supports_svg'                  => false,
1118                 ),
1119              ),
1120  
1121              // Opera 12.15 (Build 1748); Mac OS X.
1122              array(
1123                  'Opera/9.80 (Macintosh; Intel Mac OS X 10.10.0; Edition MAS) Presto/2.12.388 Version/12.15',
1124                  array(
1125                      'is_opera'                      => true,
1126                      'check_opera_version'           => array(
1127                          '8.0'                       => true,
1128                          '9.0'                       => true,
1129                          '10.0'                      => true,
1130                          '12.15'                     => true,
1131                      ),
1132  
1133                      'versionclasses'                => array(
1134                          'opera',
1135                      ),
1136  
1137                      'supports_svg'                  => false,
1138                 ),
1139              ),
1140  
1141              // Opera 9.0; Debian Linux.
1142              array(
1143                  'Opera/9.01 (X11; Linux i686; U; en)',
1144                  array(
1145                      'is_opera'                      => true,
1146                      'check_opera_version'           => array(
1147                          '8.0'                       => true,
1148                          '9.0'                       => true,
1149                      ),
1150  
1151                      'versionclasses'                => array(
1152                          'opera',
1153                      ),
1154  
1155                      'supports_svg'                  => false,
1156                 ),
1157              ),
1158  
1159              // Google web crawlers.
1160              array(
1161                  'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
1162                  array(
1163                      'is_web_crawler'                => true,
1164                      'versionclasses'                => array(
1165                      ),
1166                 ),
1167              ),
1168              array(
1169                  'Googlebot/2.1 (+http://www.googlebot.com/bot.html)',
1170                  array(
1171                      'is_web_crawler'                => true,
1172                      'versionclasses'                => array(
1173                      ),
1174                 ),
1175              ),
1176              array(
1177                  'Googlebot-Image/1.0',
1178                  array(
1179                      'is_web_crawler'                => true,
1180                      'versionclasses'                => array(
1181                      ),
1182                 ),
1183              ),
1184  
1185              // Yahoo crawlers.
1186              // See https://help.yahoo.com/kb/slurp-crawling-page-sln22600.html.
1187              array(
1188                  'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)',
1189                  array(
1190                      'is_web_crawler'                => true,
1191                      'versionclasses'                => array(
1192                      ),
1193                 ),
1194              ),
1195  
1196              // Bing / MSN / AdIdx crawlers.
1197              // See http://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0.
1198              array(
1199                  'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)',
1200                  array(
1201                      'is_web_crawler'                => true,
1202                      'versionclasses'                => array(
1203                      ),
1204                 ),
1205              ),
1206              array(
1207                  'Mozilla/5.0 (compatible; bingbot/2.0 +http://www.bing.com/bingbot.htm)',
1208                  array(
1209                      'is_web_crawler'                => true,
1210                      'versionclasses'                => array(
1211                      ),
1212                 ),
1213              ),
1214              array(
1215                  'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)',
1216                  array(
1217                      'is_web_crawler'                => true,
1218                      'is_webkit'                     => true,
1219                      'is_safari_ios'                 => true,
1220                      'is_ios'                        => true,
1221                      'check_safari_ios_version'      => array(
1222                          '527'                       => true,
1223                      ),
1224  
1225                      'versionclasses'                => array(
1226                          'ios',
1227                      ),
1228  
1229                      'devicetype'                    => 'mobile',
1230                 ),
1231              ),
1232              array(
1233                  'Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)',
1234                  array(
1235                      'is_web_crawler'                => true,
1236                      'is_ie'                         => true,
1237                      'check_ie_version'              => array(
1238                          '0'                         => true,
1239                          '5.0'                       => true,
1240                          '5.5'                       => true,
1241                          '6.0'                       => true,
1242                          '7.0'                       => true,
1243                          '8.0'                       => true,
1244                          '9.0'                       => true,
1245                          '10'                        => true,
1246                          '11'                        => true,
1247                      ),
1248                      'versionclasses'                => array(
1249                          'ie',
1250                          'ie11',
1251                      ),
1252                      'devicetype'                    => 'mobile',
1253                 ),
1254              ),
1255  
1256              array(
1257                  'msnbot/2.0b (+http://search.msn.com/msnbot.htm)',
1258                  array(
1259                      'is_web_crawler'                => true,
1260                      'versionclasses'                => array(
1261                      ),
1262                 ),
1263              ),
1264              array(
1265                  'msnbot/2.1',
1266                  array(
1267                      'is_web_crawler'                => true,
1268                      'versionclasses'                => array(
1269                      ),
1270                 ),
1271              ),
1272              array(
1273                  'msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)',
1274                  array(
1275                      'is_web_crawler'                => true,
1276                      'versionclasses'                => array(
1277                      ),
1278                 ),
1279              ),
1280              array(
1281                  'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b',
1282                  array(
1283                      'is_web_crawler'                => true,
1284                      'is_webkit'                     => true,
1285                      'is_safari'                     => true,
1286                      'check_safari_version'          => array(
1287                          '1'                         => true,
1288                          '312'                       => true,
1289                          '500'                       => true,
1290                      ),
1291  
1292                      'versionclasses'                => array(
1293                          'safari',
1294                      ),
1295                 ),
1296              ),
1297              array(
1298                  'Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko BingPreview/1.0b',
1299                  array(
1300                      'is_web_crawler'                => true,
1301                      'is_ie'                         => true,
1302                      'check_ie_version'              => array(
1303                          '0'                         => true,
1304                          '5.0'                       => true,
1305                          '5.5'                       => true,
1306                          '6.0'                       => true,
1307                          '7.0'                       => true,
1308                          '8.0'                       => true,
1309                          '9.0'                       => true,
1310                          '10'                        => true,
1311                          '11'                        => true,
1312                      ),
1313                      'versionclasses'                => array(
1314                          'ie',
1315                          'ie11',
1316                      ),
1317                      'devicetype'                    => 'mobile',
1318                 ),
1319              ),
1320  
1321              // Yandex.
1322              // See http://help.yandex.com/search/robots/agent.xml.
1323              array(
1324                  'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)',
1325                  array(
1326                      'is_web_crawler'                => true,
1327                      'versionclasses'                => array(
1328                      ),
1329                 ),
1330              ),
1331              array(
1332                  'Mozilla/5.0 (compatible; YandexImages/3.0; +http://yandex.com/bots)',
1333                  array(
1334                      'is_web_crawler'                => true,
1335                      'versionclasses'                => array(
1336                      ),
1337                 ),
1338              ),
1339  
1340              // AltaVista.
1341              array(
1342                  'AltaVista V2.0B crawler@evreka.com',
1343                  array(
1344                      'is_web_crawler'                => true,
1345                      'versionclasses'                => array(
1346                      ),
1347                 ),
1348              ),
1349  
1350              // ZoomSpider.
1351              array(
1352                  'ZoomSpider - wrensoft.com [ZSEBOT]',
1353                  array(
1354                      'is_web_crawler'                => true,
1355                      'versionclasses'                => array(
1356                      ),
1357                 ),
1358              ),
1359  
1360              // Baidu.
1361              array(
1362                  'Baiduspider+(+http://www.baidu.com/search/spider_jp.html)',
1363                  array(
1364                      'is_web_crawler'                => true,
1365                      'versionclasses'                => array(
1366                      ),
1367                 ),
1368              ),
1369              array(
1370                  'Baiduspider+(+http://www.baidu.com/search/spider.htm)',
1371                  array(
1372                      'is_web_crawler'                => true,
1373                      'versionclasses'                => array(
1374                      ),
1375                 ),
1376              ),
1377  
1378              // Ask.com.
1379              array(
1380                  'User-Agent: Mozilla/2.0 (compatible; Ask Jeeves/Teoma)',
1381                  array(
1382                      'is_web_crawler'                => true,
1383                      'versionclasses'                => array(
1384                      ),
1385                 ),
1386              ),
1387  
1388              // MoodleBot.
1389              array(
1390                  'User-Agent: MoodleBot/3.8 (+https://moodle.org)',
1391                  array(
1392                      'is_web_crawler'                => true,
1393                      'versionclasses'                => array(
1394                      ),
1395                 ),
1396              ),
1397  
1398              // Macos Desktop app.
1399              array(
1400                  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) moodlemobile/3.6.0 Chrome/69.0.3497.106 Electron/4.0.1 Safari/537.36 MoodleMobile',
1401                  array(
1402                      'is_moodle_app'                => true,
1403                      'is_webkit'                    => true,
1404                      'is_chrome'                    => true,
1405                      'check_chrome_version'         => array(
1406                          '7'                        => true,
1407                          '8'                        => true,
1408                          '10'                       => true,
1409                          '39'                       => true,
1410                      ),
1411                      'versionclasses'               => array(
1412                          'chrome',
1413                      ),
1414                 ),
1415              ),
1416  
1417              // Linux Desktop app.
1418              array(
1419                  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) moodledesktop/3.6.0 Chrome/69.0.3497.106 Electron/4.0.1 Safari/537.36 MoodleMobile',
1420                  array(
1421                      'is_moodle_app'                => true,
1422                      'is_webkit'                    => true,
1423                      'is_chrome'                    => true,
1424                      'check_chrome_version'         => array(
1425                          '7'                        => true,
1426                          '8'                        => true,
1427                          '10'                       => true,
1428                          '39'                       => true,
1429                      ),
1430                      'versionclasses'               => array(
1431                          'chrome',
1432                      ),
1433                 ),
1434              ),
1435  
1436              // Windows Desktop app.
1437              array(
1438                  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) moodledesktop/3.6.0 Chrome/69.0.3497.106 Electron/4.0.1 Safari/537.36 MoodleMobile',
1439                  array(
1440                      'is_moodle_app'                => true,
1441                      'is_webkit'                    => true,
1442                      'is_chrome'                    => true,
1443                      'check_chrome_version'         => array(
1444                          '7'                        => true,
1445                          '8'                        => true,
1446                          '10'                       => true,
1447                          '39'                       => true,
1448                      ),
1449                      'versionclasses'               => array(
1450                          'chrome',
1451                      ),
1452                 ),
1453              ),
1454  
1455              // Android app.
1456              array(
1457                  'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 MoodleMobile',
1458                  array(
1459                      'is_moodle_app'                => true,
1460                      'is_webkit'                    => true,
1461                      'is_webkit_android'            => true,
1462                      'is_chrome'                    => true,
1463                      'check_chrome_version'         => array(
1464                          '7'                        => true,
1465                          '8'                        => true,
1466                          '10'                       => true,
1467                          '39'                       => true,
1468                      ),
1469                      'devicetype'                   => 'mobile',
1470                      'check_webkit_android_version' => array(
1471                          '525'                       => true,
1472                          '527'                       => true,
1473                      ),
1474                      'versionclasses'               => array(
1475                          'android',
1476                          'chrome'
1477                      ),
1478                 ),
1479              ),
1480  
1481              // Android app, user agent lower case.
1482              array(
1483                  'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 moodlemobile',
1484                  array(
1485                      'is_moodle_app'                => true,
1486                      'is_webkit'                    => true,
1487                      'is_webkit_android'            => true,
1488                      'is_chrome'                    => true,
1489                      'check_chrome_version'         => array(
1490                          '7'                        => true,
1491                          '8'                        => true,
1492                          '10'                       => true,
1493                          '39'                       => true,
1494                      ),
1495                      'devicetype'                   => 'mobile',
1496                      'check_webkit_android_version' => array(
1497                          '525'                       => true,
1498                          '527'                       => true,
1499                      ),
1500                      'versionclasses'               => array(
1501                          'android',
1502                          'chrome'
1503                      ),
1504                 ),
1505              ),
1506  
1507              // iOS (iPhone) app.
1508              array(
1509                  'Mozilla/5.0 (iPhone; CPU OS 13_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 MoodleMobile',
1510                  array(
1511                      'is_moodle_app'                => true,
1512                      'is_ios'                       => true,
1513                      'is_webkit'                    => true,
1514                      'devicetype'                   => 'mobile',
1515                      'versionclasses'               => array(
1516                      ),
1517                 ),
1518              ),
1519  
1520              // iOS (iPad) app.
1521              array(
1522                  'Mozilla/5.0 (iPad; CPU OS 12_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D39 MoodleMobile',
1523                  array(
1524                      'is_moodle_app'                => true,
1525                      'is_ios'                       => true,
1526                      'is_webkit'                    => true,
1527                      'devicetype'                   => 'tablet',
1528                      'versionclasses'               => array(
1529                      ),
1530                 ),
1531              ),
1532          );
1533      }
1534  
1535      /**
1536       * Test instance generation.
1537       */
1538      public function test_instance() {
1539          $this->assertInstanceOf('core_useragent', core_useragent::instance());
1540          $this->assertInstanceOf('core_useragent', core_useragent::instance(true));
1541      }
1542  
1543      /**
1544       * @dataProvider user_agents_providers
1545       */
1546      public function test_useragent_edge($useragent, $tests) {
1547          // Setup the core_useragent instance.
1548          core_useragent::instance(true, $useragent);
1549  
1550          // Edge Tests.
1551          if (isset($tests['is_edge']) && $tests['is_edge']) {
1552              $this->assertTrue(core_useragent::is_edge());
1553          } else {
1554              $this->assertFalse(core_useragent::is_edge());
1555          }
1556  
1557          $versions = array(
1558              // New versions of should be added here.
1559              '12'   => false,
1560          );
1561  
1562          if (isset($tests['check_edge_version'])) {
1563              // The test provider has overwritten some of the above checks.
1564              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1565              $versions = $tests['check_edge_version'] + $versions;
1566          }
1567  
1568          foreach ($versions as $version => $result) {
1569              $this->assertEquals($result, core_useragent::check_edge_version($version),
1570                  "Version incorrectly determined for Edge version '{$version}'");
1571          }
1572      }
1573  
1574      /**
1575       * @dataProvider user_agents_providers
1576       */
1577      public function test_useragent_ie($useragent, $tests) {
1578          // Setup the core_useragent instance.
1579          core_useragent::instance(true, $useragent);
1580  
1581          // IE Tests.
1582          if (isset($tests['is_ie']) && $tests['is_ie']) {
1583              $this->assertTrue(core_useragent::is_ie());
1584          } else {
1585              $this->assertFalse(core_useragent::is_ie());
1586          }
1587  
1588          $versions = array(
1589              // New versions of should be added here.
1590              '0'    => false,
1591              '5.0'  => false,
1592              '5.5'  => false,
1593              '6.0'  => false,
1594              '7.0'  => false,
1595              '8.0'  => false,
1596              '9.0'  => false,
1597              '10'   => false,
1598              '11'   => false,
1599              '12'   => false,
1600              '13'   => false,
1601              '14'   => false,
1602          );
1603  
1604          if (isset($tests['check_ie_version'])) {
1605              // The test provider has overwritten some of the above checks.
1606              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1607              $versions = $tests['check_ie_version'] + $versions;
1608          }
1609  
1610          foreach ($versions as $version => $result) {
1611              $this->assertEquals($result, core_useragent::check_ie_version($version),
1612                  "Version incorrectly determined for IE version '{$version}'");
1613          }
1614  
1615          // IE Compatibility mode.
1616          if (isset($tests['iecompatibility']) && $tests['iecompatibility']) {
1617              $this->assertTrue(core_useragent::check_ie_compatibility_view(), "IE Compability false negative");
1618          } else {
1619              $this->assertFalse(core_useragent::check_ie_compatibility_view(), "IE Compability false positive");
1620          }
1621  
1622      }
1623  
1624      /**
1625       * @dataProvider user_agents_providers
1626       */
1627      public function test_useragent_msword($useragent, $tests) {
1628          // Setup the core_useragent instance.
1629          core_useragent::instance(true, $useragent);
1630  
1631          // MSWord Tests.
1632          if (isset($tests['is_msword']) && $tests['is_msword']) {
1633              $this->assertTrue(core_useragent::is_msword());
1634          } else {
1635              $this->assertFalse(core_useragent::is_msword());
1636          }
1637      }
1638  
1639      /**
1640       * @dataProvider user_agents_providers
1641       */
1642      public function test_useragent_supports($useragent, $tests) {
1643          // Setup the core_useragent instance.
1644          core_useragent::instance(true, $useragent);
1645  
1646          // Supports SVG.
1647          if (!isset($tests['supports_svg']) || $tests['supports_svg']) {
1648              $this->assertTrue(core_useragent::supports_svg(),
1649                  "SVG Support was not reported (and should have been)");
1650          } else {
1651              $this->assertFalse(core_useragent::supports_svg(),
1652                  "SVG Support was reported (and should not have been)");
1653          }
1654  
1655          // Supports JSON ContentType.
1656          if (!isset($tests['supports_json_contenttype']) || $tests['supports_json_contenttype']) {
1657              $this->assertTrue(core_useragent::supports_json_contenttype(),
1658                  "JSON ContentType Support was not reported (and should have been)");
1659          } else {
1660              $this->assertFalse(core_useragent::supports_json_contenttype(),
1661                  "JSON ContentType Support was reported (and should not have been)");
1662          }
1663      }
1664  
1665      /**
1666       * @dataProvider user_agents_providers
1667       */
1668      public function test_useragent_webkit($useragent, $tests) {
1669          // Setup the core_useragent instance.
1670          core_useragent::instance(true, $useragent);
1671  
1672          if (isset($tests['is_webkit']) && $tests['is_webkit']) {
1673              $this->assertTrue(core_useragent::is_webkit(),
1674                  "Browser was not identified as a webkit browser");
1675              $this->assertTrue(core_useragent::check_webkit_version());
1676          } else {
1677              $this->assertFalse(core_useragent::is_webkit(),
1678                  "Browser was incorrectly identified as a webkit browser");
1679              $this->assertFalse(core_useragent::check_webkit_version());
1680          }
1681  
1682          $versions = array(
1683              // New versions should be added here.
1684          );
1685  
1686          if (isset($tests['check_webkit_version'])) {
1687              // The test provider has overwritten some of the above checks.
1688              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1689              $versions = $tests['check_webkit_version'] + $versions;
1690          }
1691  
1692          foreach ($versions as $version => $result) {
1693              $this->assertEquals($result, core_useragent::check_webkit_version($version),
1694                  "Version incorrectly determined for Webkit version '{$version}'");
1695          }
1696      }
1697  
1698      /**
1699       * @dataProvider user_agents_providers
1700       */
1701      public function test_useragent_webkit_android($useragent, $tests) {
1702          // Setup the core_useragent instance.
1703          core_useragent::instance(true, $useragent);
1704  
1705          if (isset($tests['is_webkit_android']) && $tests['is_webkit_android']) {
1706              $this->assertTrue(core_useragent::is_webkit_android(),
1707                  "Browser was not identified as an Android webkit browser");
1708              $this->assertTrue(core_useragent::check_webkit_android_version());
1709          } else {
1710              $this->assertFalse(core_useragent::is_webkit_android(),
1711                  "Browser was incorrectly identified as an Android webkit browser");
1712              $this->assertFalse(core_useragent::check_webkit_android_version());
1713          }
1714  
1715          $versions = array(
1716              // New versions should be added here.
1717              '525'       => false,
1718              '527'       => false,
1719              '590'       => false,
1720          );
1721  
1722          if (isset($tests['check_webkit_android_version'])) {
1723              // The test provider has overwritten some of the above checks.
1724              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1725              $versions = $tests['check_webkit_android_version'] + $versions;
1726          }
1727  
1728          foreach ($versions as $version => $result) {
1729              $this->assertEquals($result, core_useragent::check_webkit_android_version($version),
1730                  "Version incorrectly determined for Android webkit version '{$version}'");
1731          }
1732      }
1733  
1734      /**
1735       * @dataProvider user_agents_providers
1736       */
1737      public function test_useragent_chrome($useragent, $tests) {
1738          // Setup the core_useragent instance.
1739          core_useragent::instance(true, $useragent);
1740  
1741          if (isset($tests['is_chrome']) && $tests['is_chrome']) {
1742              $this->assertTrue(core_useragent::is_chrome(),
1743                  "Browser was not identified as a chrome browser");
1744              $this->assertTrue(core_useragent::check_chrome_version());
1745          } else {
1746              $this->assertFalse(core_useragent::is_chrome(),
1747                  "Browser was incorrectly identified as a chrome browser");
1748              $this->assertFalse(core_useragent::check_chrome_version());
1749          }
1750  
1751          $versions = array(
1752              // New versions should be added here.
1753              '7'         => false,
1754              '8'         => false,
1755              '10'        => false,
1756              '39'        => false,
1757          );
1758  
1759          if (isset($tests['check_chrome_version'])) {
1760              // The test provider has overwritten some of the above checks.
1761              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1762              $versions = $tests['check_chrome_version'] + $versions;
1763          }
1764  
1765          foreach ($versions as $version => $result) {
1766              $this->assertEquals($result, core_useragent::check_chrome_version($version),
1767                  "Version incorrectly determined for Chrome version '{$version}'");
1768          }
1769      }
1770  
1771      /**
1772       * @dataProvider user_agents_providers
1773       */
1774      public function test_useragent_safari($useragent, $tests) {
1775          // Setup the core_useragent instance.
1776          core_useragent::instance(true, $useragent);
1777  
1778          if (isset($tests['is_safari']) && $tests['is_safari']) {
1779              $this->assertTrue(core_useragent::is_safari(),
1780                  "Browser was not identified as a safari browser");
1781              $this->assertTrue(core_useragent::check_safari_version());
1782          } else {
1783              $this->assertFalse(core_useragent::is_safari(),
1784                  "Browser was incorrectly identified as a safari browser");
1785              $this->assertFalse(core_useragent::check_safari_version());
1786          }
1787  
1788          // Check Safari (generic).
1789          $versions = array(
1790              // New versions should be added here.
1791              '1'         => false,
1792              '312'       => false,
1793              '500'       => false,
1794          );
1795  
1796          if (isset($tests['check_safari_version'])) {
1797              // The test provider has overwritten some of the above checks.
1798              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1799              $versions = $tests['check_safari_version'] + $versions;
1800          }
1801  
1802          foreach ($versions as $version => $result) {
1803              $this->assertEquals($result, core_useragent::check_safari_version($version),
1804                  "Version incorrectly determined for Safari (generic) version '{$version}'");
1805          }
1806      }
1807  
1808      /**
1809       * @dataProvider user_agents_providers
1810       */
1811      public function test_useragent_ios_safari($useragent, $tests) {
1812          // Setup the core_useragent instance.
1813          core_useragent::instance(true, $useragent);
1814  
1815          if (isset($tests['is_safari_ios']) && $tests['is_safari_ios']) {
1816              $this->assertTrue(core_useragent::is_safari_ios(),
1817                  "Browser was not identified as an iOS safari browser");
1818              $this->assertTrue(core_useragent::check_safari_ios_version());
1819          } else {
1820              $this->assertFalse(core_useragent::is_safari_ios(),
1821                  "Browser was incorrectly identified as an iOS safari browser");
1822              $this->assertFalse(core_useragent::check_safari_ios_version());
1823          }
1824  
1825          // Check iOS Safari.
1826          $versions = array(
1827              // New versions should be added here.
1828              '527'       => false,
1829              '590'       => false,
1830              '600'       => false,
1831          );
1832  
1833          if (isset($tests['check_safari_ios_version'])) {
1834              // The test provider has overwritten some of the above checks.
1835              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1836              $versions = $tests['check_safari_ios_version'] + $versions;
1837          }
1838  
1839          foreach ($versions as $version => $result) {
1840              $this->assertEquals($result, core_useragent::check_safari_ios_version($version),
1841                  "Version incorrectly determined for iOS Safari version '{$version}'");
1842          }
1843      }
1844  
1845      /**
1846       * @dataProvider user_agents_providers
1847       */
1848      public function test_useragent_ios($useragent, $tests) {
1849          // Setup the core_useragent instance.
1850          core_useragent::instance(true, $useragent);
1851  
1852          if (isset($tests['is_ios']) && $tests['is_ios']) {
1853              $this->assertTrue(core_useragent::is_ios(),
1854                  "Browser was not identified as an iOS device browser");
1855              // The iOS app is not Safari based.
1856              if (!isset($tests['is_moodle_app']) || !$tests['is_moodle_app']) {
1857                  $this->assertTrue(core_useragent::check_safari_ios_version());
1858              }
1859          } else {
1860              $this->assertFalse(core_useragent::is_ios(),
1861                  "Browser was incorrectly identified as an iOS device browser");
1862              $this->assertFalse(core_useragent::check_safari_ios_version());
1863          }
1864      }
1865  
1866      /**
1867       * @dataProvider user_agents_providers
1868       */
1869      public function test_useragent_gecko($useragent, $tests) {
1870          // Setup the core_useragent instance.
1871          core_useragent::instance(true, $useragent);
1872  
1873          if (isset($tests['is_gecko']) && $tests['is_gecko']) {
1874              $this->assertTrue(core_useragent::is_gecko(),
1875                  "Browser was not identified as a gecko browser");
1876              $this->assertTrue(core_useragent::check_gecko_version());
1877          } else {
1878              $this->assertFalse(core_useragent::is_gecko(),
1879                  "Browser was incorrectly identified as a gecko browser");
1880              $this->assertFalse(core_useragent::check_gecko_version());
1881          }
1882  
1883          $versions = array(
1884              // New versions should be added here.
1885              '1'             => false,
1886              '2'             => false,
1887              '3.6'           => false,
1888              '4.0'           => false,
1889              '20030516'      => false,
1890              '20051116'      => false,
1891              '2006010100'    => false,
1892              '20100101'      => false,
1893              '15.0'          => false,
1894              '18.0'          => false,
1895              '19.0'          => false,
1896          );
1897  
1898          if (isset($tests['check_gecko_version'])) {
1899              // The test provider has overwritten some of the above checks.
1900              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1901              $versions = $tests['check_gecko_version'] + $versions;
1902          }
1903  
1904          foreach ($versions as $version => $result) {
1905              $this->assertEquals($result, core_useragent::check_gecko_version($version),
1906                  "Version incorrectly determined for Gecko version '{$version}'");
1907          }
1908      }
1909  
1910      /**
1911       * @dataProvider user_agents_providers
1912       */
1913      public function test_useragent_firefox($useragent, $tests) {
1914          // Setup the core_useragent instance.
1915          core_useragent::instance(true, $useragent);
1916  
1917          if (isset($tests['is_firefox']) && $tests['is_firefox']) {
1918              $this->assertTrue(core_useragent::is_firefox(),
1919                  "Browser was not identified as a firefox browser");
1920              $this->assertTrue(core_useragent::check_firefox_version());
1921          } else {
1922              $this->assertFalse(core_useragent::is_firefox(),
1923                  "Browser was incorrectly identified as a firefox browser");
1924              $this->assertFalse(core_useragent::check_firefox_version());
1925          }
1926  
1927          $versions = array(
1928              // New versions should be added here.
1929              '1.5'       => false,
1930              '3.0'       => false,
1931              '4'         => false,
1932              '10'        => false,
1933              '15'        => false,
1934              '18'        => false,
1935              '19'        => false,
1936              '33'        => false,
1937          );
1938  
1939          if (isset($tests['check_firefox_version'])) {
1940              // The test provider has overwritten some of the above checks.
1941              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1942              $versions = $tests['check_firefox_version'] + $versions;
1943          }
1944  
1945          foreach ($versions as $version => $result) {
1946              $this->assertEquals($result, core_useragent::check_firefox_version($version),
1947                  "Version incorrectly determined for Firefox version '{$version}'");
1948          }
1949      }
1950  
1951      /**
1952       * @dataProvider user_agents_providers
1953       */
1954      public function test_useragent_opera($useragent, $tests) {
1955          // Setup the core_useragent instance.
1956          core_useragent::instance(true, $useragent);
1957  
1958          if (isset($tests['is_opera']) && $tests['is_opera']) {
1959              $this->assertTrue(core_useragent::is_opera(),
1960                  "Browser was not identified as a opera browser");
1961              $this->assertTrue(core_useragent::check_opera_version());
1962          } else {
1963              $this->assertFalse(core_useragent::is_opera(),
1964                  "Browser was incorrectly identified as a opera browser");
1965              $this->assertFalse(core_useragent::check_opera_version());
1966          }
1967  
1968          $versions = array(
1969              // New versions should be added here.
1970              '8.0'       => false,
1971              '9.0'       => false,
1972              '10.0'      => false,
1973              '12.15'     => false,
1974          );
1975  
1976          if (isset($tests['check_opera_version'])) {
1977              // The test provider has overwritten some of the above checks.
1978              // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes.
1979              $versions = $tests['check_opera_version'] + $versions;
1980          }
1981  
1982          foreach ($versions as $version => $result) {
1983              $this->assertEquals($result, core_useragent::check_opera_version($version),
1984                  "Version incorrectly determined for Opera version '{$version}'");
1985          }
1986      }
1987  
1988      /**
1989       * @dataProvider user_agents_providers
1990       */
1991      public function test_get_device_type($useragent, $tests) {
1992          // Setup the core_useragent instance.
1993          core_useragent::instance(true, $useragent);
1994  
1995          $expected = 'default';
1996          if (isset($tests['devicetype'])) {
1997              $expected = $tests['devicetype'];
1998          }
1999  
2000          $this->assertEquals($expected, core_useragent::get_device_type(),
2001              "Device Type was not correctly identified");
2002      }
2003  
2004      /**
2005       * @dataProvider user_agents_providers
2006       */
2007      public function test_get_browser_version_classes($useragent, $tests) {
2008          // Setup the core_useragent instance.
2009          core_useragent::instance(true, $useragent);
2010  
2011          $actual = core_useragent::get_browser_version_classes();
2012          foreach ($tests['versionclasses'] as $expectedclass) {
2013              $this->assertContains($expectedclass, $actual);
2014          }
2015          $this->assertCount(count($tests['versionclasses']), $actual);
2016      }
2017  
2018      /**
2019       * @dataProvider user_agents_providers
2020       */
2021      public function test_useragent_web_crawler($useragent, $tests) {
2022          // Setup the core_useragent instance.
2023          core_useragent::instance(true, $useragent);
2024  
2025          $expectation = isset($tests['is_web_crawler']) ? $tests['is_web_crawler'] : false;
2026          $this->assertSame($expectation, core_useragent::is_web_crawler());
2027      }
2028  
2029      /**
2030       * @dataProvider user_agents_providers
2031       */
2032      public function test_useragent_moodle_app($useragent, $tests) {
2033          // Setup the core_useragent instance.
2034          core_useragent::instance(true, $useragent);
2035  
2036          $expectation = isset($tests['is_moodle_app']) ? $tests['is_moodle_app'] : false;
2037          $this->assertSame($expectation, core_useragent::is_moodle_app());
2038      }
2039  }