Your message dated Thu, 21 Mar 2019 18:14:00 +0000
with message-id <e78b6403-3aff-45a9-1422-7e16d5622...@thykier.net>
and subject line Re: Bug#925229: unblock: uap-core/20190213-2
has caused the Debian Bug report #925229,
regarding unblock: uap-core/20190213-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
925229: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925229
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Dear Release Team,

Please consider unblocking package uap-core

This is a new release that fixes a A Regular Expression Denial of
Service (ReDoS) bug: CVE-2018-20164.

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=922717

I've attached the output from debdiff between the versions in testing
and unstable.

Thanks,

Edward Betts

unblock uap-core/20190213-2
diff -Nru uap-core-20181019/CONTRIBUTING.md uap-core-20190213/CONTRIBUTING.md
--- uap-core-20181019/CONTRIBUTING.md   2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/CONTRIBUTING.md   2019-02-13 17:27:26.000000000 +0000
@@ -10,9 +10,10 @@
        * `tests/test_device.yaml`
        * `tests/test_os.yaml`
        * `tests/test_ua.yaml`
-5. Push your branch to GitHub and submit a pull request
-6. Monitor the pull request to make sure the Travis build succeeds. If it 
fails simply make the necessary changes to your branch and push it. Travis will 
re-test the changes.
+5. Check that your regex is not vulnerable to 
[ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS)
 using the test in `tests/regexes.js`
+6. Push your branch to GitHub and submit a pull request
+7. Monitor the pull request to make sure the Travis build succeeds. If it 
fails simply make the necessary changes to your branch and push it. Travis will 
re-test the changes.
 
 That's it. If you don't feel comfortable forking the project or modifying the 
YAML you can also [submit an 
issue](https://github.com/ua-parser/uap-core/issues) that includes the 
appropriate user agent string and the expected results of parsing.
 
-Thanks!
\ No newline at end of file
+Thanks!
diff -Nru uap-core-20181019/debian/changelog uap-core-20190213/debian/changelog
--- uap-core-20181019/debian/changelog  2018-11-08 17:24:23.000000000 +0000
+++ uap-core-20190213/debian/changelog  2019-03-20 17:14:03.000000000 +0000
@@ -1,3 +1,19 @@
+uap-core (20190213-2) unstable; urgency=high
+
+  * The previous release was mistakenly based on 20180219-1, meaning that
+    the changes in 20180503-1 and 20181019-1 were missing.
+  * Restore missing changes. Closes: #924969
+
+ -- Edward Betts <edw...@4angle.com>  Wed, 20 Mar 2019 17:14:03 +0000
+
+uap-core (20190213-1) unstable; urgency=high
+
+  * New upstream release Closes: #922717
+    - CVE-2018-20164: Regular Expression Denial of Service
+  * debian/control: update Standards-Version
+
+ -- Edward Betts <edw...@4angle.com>  Tue, 05 Mar 2019 12:29:24 +0000
+
 uap-core (20181019-1) unstable; urgency=medium
 
   * New upstream release
diff -Nru uap-core-20181019/debian/control uap-core-20190213/debian/control
--- uap-core-20181019/debian/control    2018-11-08 17:24:23.000000000 +0000
+++ uap-core-20190213/debian/control    2019-03-20 17:14:03.000000000 +0000
@@ -3,7 +3,7 @@
 Priority: optional
 Maintainer: Edward Betts <edw...@4angle.com>
 Build-Depends: debhelper (>= 11)
-Standards-Version: 4.2.1
+Standards-Version: 4.3.0
 Homepage: https://github.com/ua-parser/uap-core
 
 Package: uap-core
diff -Nru uap-core-20181019/.gitignore uap-core-20190213/.gitignore
--- uap-core-20181019/.gitignore        2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/.gitignore        2019-02-13 17:27:26.000000000 +0000
@@ -1,3 +1,5 @@
 .DS_Store
 node_modules/
 package-lock.json
+*.tgz
+*.log
diff -Nru uap-core-20181019/.npmignore uap-core-20190213/.npmignore
--- uap-core-20181019/.npmignore        1970-01-01 01:00:00.000000000 +0100
+++ uap-core-20190213/.npmignore        2019-02-13 17:27:26.000000000 +0000
@@ -0,0 +1,8 @@
+node_modules/
+test_resources/
+tests/
+tmp/
+*.bak
+*.tgz
+*.log
+.*
diff -Nru uap-core-20181019/.npmrc uap-core-20190213/.npmrc
--- uap-core-20181019/.npmrc    1970-01-01 01:00:00.000000000 +0100
+++ uap-core-20190213/.npmrc    2019-02-13 17:27:26.000000000 +0000
@@ -0,0 +1 @@
+package-lock=false
diff -Nru uap-core-20181019/package.json uap-core-20190213/package.json
--- uap-core-20181019/package.json      2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/package.json      2019-02-13 17:27:26.000000000 +0000
@@ -1,7 +1,7 @@
 {
   "name": "uap-core",
   "description": "The regex file necessary to build language ports of 
Browserscope's user agent parser.",
-  "version": "0.5.0",
+  "version": "0.6.5",
   "maintainers": [
     {
       "name": "Tobie Langel",
@@ -25,11 +25,12 @@
     }
   ],
   "devDependencies": {
-    "yamlparser": ">=0.0.2",
     "mocha": "*",
-    "uap-ref-impl": "ua-parser/uap-ref-impl"
+    "safe-regex": "^2.0.1",
+    "uap-ref-impl": "git+https://github.com/ua-parser/uap-ref-impl#master";,
+    "yamlparser": ">=0.0.2"
   },
   "scripts": {
-    "test": "mocha -u tdd -R min ./tests/test.js"
+    "test": "mocha --opts ./tests/mocha.opts ./tests"
   }
 }
diff -Nru uap-core-20181019/README.md uap-core-20190213/README.md
--- uap-core-20181019/README.md 2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/README.md 2019-02-13 17:27:26.000000000 +0000
@@ -8,6 +8,7 @@
 Maintainers
 -----------
 
+* [Com Menthol](https://github.com/commenthol)
 * [Lindsey Simon](https://github.com/elsigh) 
([@elsigh](https://twitter.com/elsigh))
 * [Tobie Langel](https://github.com/tobie) 
([@tobie](https://twitter.com/tobie))
 
diff -Nru uap-core-20181019/regexes.yaml uap-core-20190213/regexes.yaml
--- uap-core-20181019/regexes.yaml      2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/regexes.yaml      2019-02-13 17:27:26.000000000 +0000
@@ -7,9 +7,9 @@
     family_replacement: 'AntennaPod'
   - regex: '(TopPodcasts)Pro/(\d+) CFNetwork'
   - regex: '(MusicDownloader)Lite/(\d+)\.(\d+)\.(\d+) CFNetwork'
-  - regex: '^(.*)-iPad/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
-  - regex: '^(.*)-iPhone/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
-  - regex: '^(.*)/(\d+)\.?(\d+)?.?(\d+)?.?(\d+)? CFNetwork'
+  - regex: '^(.*)-iPad\/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork'
+  - regex: '^(.*)-iPhone/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork'
+  - regex: '^(.*)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork'
 
   # Podcast catchers
   - regex: '(espn\.go)'
@@ -23,16 +23,23 @@
   - regex: ' (Rivo) RHYTHM'
 
   # @note: iOS / OSX Applications
-  - regex: '(CFNetwork)(?:/(\d+)\.(\d+)\.?(\d+)?)?'
+  - regex: '(CFNetwork)(?:/(\d+)\.(\d+)(?:\.(\d+)|)|)'
     family_replacement: 'CFNetwork'
 
   # Pingdom
-  - regex: '(Pingdom.com_bot_version_)(\d+)\.(\d+)'
+  - regex: '(Pingdom\.com_bot_version_)(\d+)\.(\d+)'
     family_replacement: 'PingdomBot'
   # 'Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like 
Gecko) PingdomTMS/0.8.5 Safari/534.34'
   - regex: '(PingdomTMS)/(\d+)\.(\d+)\.(\d+)'
     family_replacement: 'PingdomBot'
 
+  # PTST / WebPageTest.org crawlers
+  - regex: ' (PTST)/(\d+)\.(\d+)$'
+    family_replacement: 'WebPageTest.org bot'
+
+  # Datanyze.com spider
+  - regex: 'X11; (Datanyze); Linux'
+
   # New Relic Pinger
   - regex: '(NewRelicPinger)/(\d+)\.(\d+)'
     family_replacement: 'NewRelicPingerBot'
@@ -57,11 +64,11 @@
     family_replacement: 'GooglePlusBot'
 
   # Gmail
-  - regex: 'via ggpht.com GoogleImageProxy'
+  - regex: 'via ggpht\.com GoogleImageProxy'
     family_replacement: 'GmailImageProxy'
 
   # Yahoo
-  - regex: 'YahooMailProxy; 
https://help.yahoo.com/kb/yahoo-mail-proxy-SLN28749.html'
+  - regex: 'YahooMailProxy; 
https://help\.yahoo\.com/kb/yahoo-mail-proxy-SLN28749\.html'
     family_replacement: 'YahooMailProxy'
 
   # Twitter
@@ -69,37 +76,37 @@
     family_replacement: 'TwitterBot'
 
   # Bots Pattern '/name-0.0'
-  - regex: 
'/((?:Ant-)?Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[
 \-](\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: 
'/((?:Ant-|)Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[
 \-](\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
   # Bots Pattern 'name/0.0'
-  - regex: 
'\b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: 
'\b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
 
   # MSIECrawler
-  - regex: '(MSIE) (\d+)\.(\d+)([a-z]\d?)?;.* MSIECrawler'
+  - regex: '(MSIE) (\d+)\.(\d+)([a-z]\d|[a-z]|);.* MSIECrawler'
     family_replacement: 'MSIECrawler'
 
   # DAVdroid
-  - regex: '(DAVdroid)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(DAVdroid)/(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Downloader ...
-  - regex: 
'(Google-HTTP-Java-Client|Apache-HttpClient|Go-http-client|scalaj-http|http%20client|Python-urllib|HttpMonitor|TLSProber|WinHTTP|JNLP|okhttp|aihttp|reqwest)(?:[
 /](\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: 
'(Google-HTTP-Java-Client|Apache-HttpClient|Go-http-client|scalaj-http|http%20client|Python-urllib|HttpMonitor|TLSProber|WinHTTP|JNLP|okhttp|aihttp|reqwest)(?:[
 /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
 
   # Pinterestbot
-  - regex: 
'(Pinterest(?:bot)?)/(\d+)(?:\.(\d+)(?:\.(\d+))?)?[;\s\(]+\+https://www.pinterest.com/bot.html'
+  - regex: 
'(Pinterest(?:bot|))/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)[;\s(]+\+https://www.pinterest.com/bot.html'
     family_replacement: 'Pinterestbot'
 
   # Bots
-  - regex: '(1470\.net crawler|50\.nu|8bo Crawler 
Bot|Aboundex|Accoona-[A-z]+-Agent|AdsBot-Google(?:-[a-z]+)?|altavista|AppEngine-Google|archive.*?\.org_bot|archiver|Ask
 
Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]+)*|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader(?:
 
[A-Za-z]+)*|boitho.com-dc|BotSeer|BUbiNG|\b\w*favicon\w*\b|\bYeti(?:-[a-z]+)?|Catchpoint(?:
 bot)?|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) 
Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher)?|Feed
 Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite 
Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]+-)?Googlebot(?:-[a-zA-Z]+)?|Google
 
SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile)?|IconSurf|IlTrovatore(?:-Setaccio)?|InfuzApp|Innovazion
 
Crawler|InternetArchive|IP2[a-z]+Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee
 Bot|LinkAider|LinkedInBot|Lite 
Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft
 .*? Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media *)?|msrbot|Mtps Feed 
Aggregation 
System|netresearch|Netvibes|NewsGator[^/]*|^NING|Nutch[^/]*|Nymesis|ObjectsSearch|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo
 Screenshot 
Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival
 
IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|SemrushBot|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy
 Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny 
RSS|TwitterBot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay 
bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]+|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s)?
 Link Sleuth|Xerka [A-z]+Bot|yacy(?:bot)?|Yahoo[a-z]*Seeker|Yahoo! 
Slurp|Yandex\w+|YodaoBot(?:-[A-z]+)?|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[
 /]v?(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: '(CSimpleSpider|Cityreview 
Robot|CrawlDaddy|CrawlFire|Finderbots|Index crawler|Job Roboter|KiwiStatus 
Spider|Lijit Crawler|QuerySeekerSpider|ScollSpider|Trends 
Crawler|USyd-NLP-Spider|SiteCat 
Webbot|BotName\/\$BotVersion|123metaspider-Bot|1470\.net crawler|50\.nu|8bo 
Crawler 
Bot|Aboundex|Accoona-[A-z]{1,30}-Agent|AdsBot-Google(?:-[a-z]{1,30}|)|altavista|AppEngine-Google|archive.{0,30}\.org_bot|archiver|Ask
 
Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]{1,30})(?:-[A-Za-z]{1,30}|)|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader
 Blog Indexer|BoardReader Favicon 
Fetcher|boitho.com-dc|BotSeer|BUbiNG|\b\w{0,30}favicon\w{0,30}\b|\bYeti(?:-[a-z]{1,30}|)|Catchpoint(?:
 bot|)|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) 
Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher|)|Feed
 Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite 
Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]{1,30}-|)Googlebot(?:-[a-zA-Z]{1,30}|)|Google
 
SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile|)|IconSurf|IlTrovatore(?:-Setaccio|)|InfuzApp|Innovazion
 
Crawler|InternetArchive|IP2[a-z]{1,30}Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee
 Bot|LinkAider|LinkedInBot|Lite 
Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft
 .{0,30} Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media {0,2}|)|msrbot|Mtps Feed 
Aggregation 
System|netresearch|Netvibes|NewsGator[^/]{0,30}|^NING|Nutch[^/]{0,30}|Nymesis|ObjectsSearch|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo
 Screenshot 
Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival
 
IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|SemrushBot|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy
 Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny 
RSS|TwitterBot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay 
bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]{1,30}|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s|)
 Link Sleuth|Xerka [A-z]{1,30}Bot|yacy(?:bot|)|YahooSeeker|Yahoo! 
Slurp|Yandex\w{1,30}|YodaoBot(?:-[A-z]{1,30}|)|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[
 /]v?(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)'
 
   # AWS S3 Clients
   # must come before "Bots General matcher" to catch "boto"/"boto3" before 
"bot"
-  - regex: 
'\b(Boto3?|JetS3t|aws-(?:cli|sdk-(?:cpp|go|java|nodejs|ruby2?))|s3fs)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: 
'\b(Boto3?|JetS3t|aws-(?:cli|sdk-(?:cpp|go|java|nodejs|ruby2?))|s3fs)/(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Bots General matcher 'name/0.0'
-  - regex: '(?:\/[A-Za-z0-9\.]+)? *([A-Za-z0-9 
\-_\!\[\]:]*(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]*))/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
-  # Bots General matcher 'name 0.0'
-  - regex: '(?:\/[A-Za-z0-9\.]+)? *([A-Za-z0-9 
_\!\[\]:]*(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]*))
 (\d+)(?:\.(\d+)(?:\.(\d+))?)?'
-  # Bots containing spider|scrape|bot(but not CUBOT)|Crawl
-  - regex: '((?:[A-z0-9]+|[A-z\-]+ ?)?(?: the 
)?(?:[Ss][Pp][Ii][Dd][Ee][Rr]|[Ss]crape|[A-Za-z0-9-]*(?:[^C][^Uu])[Bb]ot|[Cc][Rr][Aa][Ww][Ll])[A-z0-9]*)(?:(?:[
 /]| v)(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: '(?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 
\-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50}))[/
 ](\d+)(?:\.(\d+)(?:\.(\d+)|)|)'
+  # Bots containing bot(but not CUBOT)
+  - regex: '((?:[A-Za-z][A-Za-z0-9 -]{0,50}|)[^C][^Uu][Bb]ot)\b(?:(?:[ /]| 
v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
+  # Bots containing spider|scrape|Crawl
+  - regex: '((?:[A-z0-9]{1,50}|[A-z\-]{1,50} ?|)(?: the 
|)(?:[Ss][Pp][Ii][Dd][Ee][Rr]|[Ss]crape|[Cc][Rr][Aa][Ww][Ll])[A-z0-9]{0,50})(?:(?:[
 /]| v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
 
   # HbbTV standard defines what features the browser should understand.
   # but it's like targeting "HTML5 browsers", effective browser support 
depends on the model
@@ -107,21 +114,21 @@
   - regex: '(HbbTV)/(\d+)\.(\d+)\.(\d+) \('
 
   # must go before Firefox to catch Chimera/SeaMonkey/Camino/Waterfox
-  - regex: 
'(Chimera|SeaMonkey|Camino|Waterfox)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)?'
+  - regex: 
'(Chimera|SeaMonkey|Camino|Waterfox)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*|)'
 
   # Social Networks
   # Facebook Messenger must go before Facebook
-  - regex: 
'\[(FBAN/MessengerForiOS|FB_IAB/MESSENGER);FBAV/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: 
'\[(FBAN/MessengerForiOS|FB_IAB/MESSENGER);FBAV/(\d+)(?:\.(\d+)(?:\.(\d+)|)|)'
     family_replacement: 'Facebook Messenger'
   # Facebook
-  - regex: '\[FB.*;(FBAV)/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: '\[FB.*;(FBAV)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
     family_replacement: 'Facebook'
   # Sometimes Facebook does not specify a version (FBAV)
   - regex: '\[FB.*;'
     family_replacement: 'Facebook'
   # Pinterest
   - regex: '\[(Pinterest)/[^\]]+\]'
-  - regex: '(Pinterest)(?: for Android(?: 
Tablet)?)?/(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: '(Pinterest)(?: for Android(?: 
Tablet|)|)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
   # Instagram app
   - regex: 'Mozilla.*Mobile.*(Instagram).(\d+)\.(\d+)\.(\d+)'
   # Flipboard app
@@ -138,7 +145,7 @@
     family_replacement: 'Basilisk'
 
   # Pale Moon
-  - regex: '(PaleMoon)/(\d+)\.(\d+)\.?(\d+)?'
+  - regex: '(PaleMoon)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Pale Moon'
 
   # Firefox
@@ -150,22 +157,22 @@
     family_replacement: 'Firefox Mobile'
   - regex: '(?:Mobile|Tablet);.*(Firefox)/(\d+)\.(\d+)'
     family_replacement: 'Firefox Mobile'
-  - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)\.(\d+(?:pre)?)'
+  - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)\.(\d+(?:pre|))'
     family_replacement: 'Firefox ($1)'
   - regex: '(Firefox)/(\d+)\.(\d+)(a\d+[a-z]*)'
     family_replacement: 'Firefox Alpha'
   - regex: '(Firefox)/(\d+)\.(\d+)(b\d+[a-z]*)'
     family_replacement: 'Firefox Beta'
-  - regex: '(Firefox)-(?:\d+\.\d+)?/(\d+)\.(\d+)(a\d+[a-z]*)'
+  - regex: '(Firefox)-(?:\d+\.\d+|)/(\d+)\.(\d+)(a\d+[a-z]*)'
     family_replacement: 'Firefox Alpha'
-  - regex: '(Firefox)-(?:\d+\.\d+)?/(\d+)\.(\d+)(b\d+[a-z]*)'
+  - regex: '(Firefox)-(?:\d+\.\d+|)/(\d+)\.(\d+)(b\d+[a-z]*)'
     family_replacement: 'Firefox Beta'
-  - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)([ab]\d+[a-z]*)?'
+  - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)([ab]\d+[a-z]*|)'
     family_replacement: 'Firefox ($1)'
   - regex: '(Firefox).*Tablet browser (\d+)\.(\d+)\.(\d+)'
     family_replacement: 'MicroB'
-  - regex: '(MozillaDeveloperPreview)/(\d+)\.(\d+)([ab]\d+[a-z]*)?'
-  - regex: '(FxiOS)/(\d+)\.(\d+)(\.(\d+))?(\.(\d+))?'
+  - regex: '(MozillaDeveloperPreview)/(\d+)\.(\d+)([ab]\d+[a-z]*|)'
+  - regex: '(FxiOS)/(\d+)\.(\d+)(\.(\d+)|)(\.(\d+)|)'
     family_replacement: 'Firefox iOS'
 
   # e.g.: Flock/2.0b2
@@ -181,7 +188,7 @@
   - regex: '(Navigator)/(\d+)\.(\d+)([ab]\d+)'
     family_replacement: 'Netscape'
 
-  - regex: '(Netscape6)/(\d+)\.(\d+)\.?([ab]?\d+)?'
+  - regex: '(Netscape6)/(\d+)\.(\d+)\.?([ab]?\d+|)'
     family_replacement: 'Netscape'
 
   - regex: '(MyIBrow)/(\d+)\.(\d+)'
@@ -194,8 +201,8 @@
 
   # Opera will stop at 9.80 and hide the real version in the Version string.
   # see: http://dev.opera.com/articles/view/opera-ua-string-changes/
-  - regex: '(Opera Tablet).*Version/(\d+)\.(\d+)(?:\.(\d+))?'
-  - regex: '(Opera Mini)(?:/att)?/?(\d+)?(?:\.(\d+))?(?:\.(\d+))?'
+  - regex: '(Opera Tablet).*Version/(\d+)\.(\d+)(?:\.(\d+)|)'
+  - regex: '(Opera Mini)(?:/att|)/?(\d+|)(?:\.(\d+)|)(?:\.(\d+)|)'
   - regex: '(Opera)/.+Opera Mobi.+Version/(\d+)\.(\d+)'
     family_replacement: 'Opera Mobile'
   - regex: '(Opera)/(\d+)\.(\d+).+Opera Mobi'
@@ -204,7 +211,7 @@
     family_replacement: 'Opera Mobile'
   - regex: 'Opera Mobi'
     family_replacement: 'Opera Mobile'
-  - regex: '(Opera)/9.80.*Version/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Opera)/9.80.*Version/(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Opera 14 for Android uses a WebKit render engine.
   - regex: '(?:Mobile Safari).*(OPR)/(\d+)\.(\d+)\.(\d+)'
@@ -227,7 +234,7 @@
     family_replacement: 'Opera Neon'
 
   # Palm WebOS looks a lot like Safari.
-  - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'webOS Browser'
 
   # LuaKit has no version info.
@@ -243,20 +250,20 @@
   - regex: 'Gecko/\d+ (Lightning)/(\d+)\.(\d+)\.?((?:[ab]?\d+[a-z]*)|(?:\d*))'
 
   # Swiftfox
-  - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre)?) \(Swiftfox\)'
+  - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre|)) \(Swiftfox\)'
     family_replacement: 'Swiftfox'
-  - regex: '(Firefox)/(\d+)\.(\d+)([ab]\d+[a-z]*)? \(Swiftfox\)'
+  - regex: '(Firefox)/(\d+)\.(\d+)([ab]\d+[a-z]*|) \(Swiftfox\)'
     family_replacement: 'Swiftfox'
 
   # Rekonq
-  - regex: '(rekonq)/(\d+)\.(\d+)\.?(\d+)? Safari'
+  - regex: '(rekonq)/(\d+)\.(\d+)(?:\.(\d+)|) Safari'
     family_replacement: 'Rekonq'
   - regex: 'rekonq'
     family_replacement: 'Rekonq'
 
   # Conkeror lowercase/uppercase
   # http://conkeror.org/
-  - regex: '(conkeror|Conkeror)/(\d+)\.(\d+)\.?(\d+)?'
+  - regex: '(conkeror|Conkeror)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Conkeror'
 
   # catches lower case konqueror
@@ -285,11 +292,11 @@
     family_replacement: 'NetFront NX'
 
   # Amazon Silk, should go before Safari and Chrome Mobile
-  - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?'
+  - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|)'
     family_replacement: 'Amazon Silk'
 
   # @ref: http://www.puffinbrowser.com
-  - regex: '(Puffin)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Puffin)/(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Edge Mobile
   - regex: 'Windows Phone .*(Edge)/(\d+)\.(\d+)'
@@ -300,26 +307,43 @@
     family_replacement: 'Samsung Internet'
 
   # Seznam.cz browser (based on WebKit)
-  - regex: '(SznProhlizec)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(SznProhlizec)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Seznam prohlížeč'
 
   # Coc Coc browser, based on Chrome (used in Vietnam)
-  - regex: '(coc_coc_browser)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(coc_coc_browser)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Coc Coc'
 
   # Baidu Browsers (desktop spoofs chrome & IE, explorer is mobile)
-  - regex: '(baidubrowser)[/\s](\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: '(baidubrowser)[/\s](\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
     family_replacement: 'Baidu Browser'
   - regex: '(FlyFlow)/(\d+)\.(\d+)'
     family_replacement: 'Baidu Explorer'
 
   # MxBrowser is Maxthon. Must go before Mobile Chrome for Android
-  - regex: '(MxBrowser)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(MxBrowser)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Maxthon'
 
   # Crosswalk must go before Mobile Chrome for Android
   - regex: '(Crosswalk)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
 
+  # LINE https://line.me/en/
+  # Must go before Mobile Chrome for Android
+  - regex: '(Line)/(\d+)\.(\d+)\.(\d+)'
+    family_replacement: 'LINE'
+
+  # MiuiBrowser should got before Mobile Chrome for Android
+  - regex: '(MiuiBrowser)/(\d+)\.(\d+)\.(\d+)'
+    family_replacement: 'MiuiBrowser'
+  
+  # Mint Browser should got before Mobile Chrome for Android
+  - regex: '(Mint Browser)/(\d+)\.(\d+)\.(\d+)'
+    family_replacement: 'Mint Browser'
+
+  # Google Search App on Android, eg:
+  - regex: 'Mozilla.+Android.+(GSA)/(\d+)\.(\d+)\.(\d+)'
+    family_replacement: 'Google'
+
   # Chrome Mobile
   - regex: 'Version/.+(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
     family_replacement: 'Chrome Mobile WebView'
@@ -347,11 +371,11 @@
     family_replacement: 'Sogou Explorer'
 
   # QQ Browsers
-  - regex: '(MQQBrowser/Mini)(?:(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: '(MQQBrowser/Mini)(?:(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
     family_replacement: 'QQ Browser Mini'
-  - regex: '(MQQBrowser)(?:/(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: '(MQQBrowser)(?:/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
     family_replacement: 'QQ Browser Mobile'
-  - regex: '(QQBrowser)(?:/(\d+)(?:\.(\d+)\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: '(QQBrowser)(?:/(\d+)(?:\.(\d+)\.(\d+)(?:\.(\d+)|)|)|)'
     family_replacement: 'QQ Browser'
 
   # Rackspace Monitoring
@@ -373,7 +397,7 @@
   - regex: '(AOL) (\d+)\.(\d+); AOLBuild (\d+)'
 
   # Podcast catcher Applications using iTunes
-  - regex: '(PodCruncher|Downcast)[ /]?(\d+)\.?(\d+)?\.?(\d+)?\.?(\d+)?'
+  - regex: '(PodCruncher|Downcast)[ 
/]?(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|)'
 
   # Box Notes https://www.box.com/resources/downloads
   # Must be before Electron
@@ -397,7 +421,7 @@
 
   # HipChat provides a version on Mac, but not on Windows.
   # Needs to be before Chrome on Windows, and AppleMail on Mac.
-  - regex: '(HipChat)/?(\d+)?'
+  - regex: '(HipChat)/?(\d+|)'
     family_replacement: 'HipChat Desktop Client'
 
   # Browser/major_version.minor_version.beta_version
@@ -423,15 +447,18 @@
     family_replacement: 'Outlook'
     v1_replacement: '2016'
 
+  # Word 2014
+  - regex: 'Microsoft Office (Word) 2014'
+
   # Windows Live Mail
   - regex: 'Outlook-Express\/7\.0.*'
     family_replacement: 'Windows Live Mail'
 
   # Apple Air Mail
-  - regex: '(Airmail) (\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Airmail) (\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Thunderbird
-  - regex: '(Thunderbird)/(\d+)\.(\d+)(?:\.(\d+(?:pre)?))?'
+  - regex: '(Thunderbird)/(\d+)\.(\d+)(?:\.(\d+(?:pre|))|)'
     family_replacement: 'Thunderbird'
 
   # Postbox
@@ -439,18 +466,18 @@
     family_replacement: 'Postbox'
 
   # Barca
-  - regex: '(Barca(?:Pro)?)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Barca(?:Pro)?)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Barca'
 
   # Lotus Notes
-  - regex: '(Lotus-Notes)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Lotus-Notes)/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Lotus Notes'
 
   # Vivaldi uses "Vivaldi"
   - regex: '(Vivaldi)/(\d+)\.(\d+)\.(\d+)'
 
   # Edge/major_version.minor_version
-  - regex: '(Edge)/(\d+)(?:\.(\d+))?'
+  - regex: '(Edge)/(\d+)(?:\.(\d+)|)'
 
   # Brave Browser https://brave.com/
   - regex: '(brave)/(\d+)\.(\d+)\.(\d+) Chrome'
@@ -462,23 +489,23 @@
 
   # Dolphin Browser
   # @ref: http://www.dolphin.com
-  - regex: '\b(Dolphin)(?: |HDCN/|/INT\-)(\d+)\.(\d+)\.?(\d+)?'
+  - regex: '\b(Dolphin)(?: |HDCN/|/INT\-)(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Headless Chrome
   # https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
-  - regex: '(HeadlessChrome)(?:/(\d+)\.(\d+)\.(\d+))?'
+  - regex: '(HeadlessChrome)(?:/(\d+)\.(\d+)\.(\d+)|)'
 
   # Evolution Mail CardDav/CalDav integration
   - regex: '(Evolution)/(\d+)\.(\d+)\.(\d+\.\d+)'
 
   # Roundcube Mail CardDav plugin
-  - regex: '(RCM CardDAV plugin)/(\d+)\.(\d+)\.(\d+(?:-dev)?)'
+  - regex: '(RCM CardDAV plugin)/(\d+)\.(\d+)\.(\d+(?:-dev|))'
 
   # Browser/major_version.minor_version
-  - regex: 
'(bingbot|Bolt|AdobeAIR|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera
 
Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|iTunes|MacAppStore|NetNewsWire|Space
 Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen 
Browser|Polaris|Abrowser|Planetweb|ICE 
Browser|mDolphin|qutebrowser|Otter|QupZilla|MailBar|kmail2|YahooMobileMail|ExchangeWebServices|ExchangeServicesClient|Dragon|Outlook-iOS-Android)/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: 
'(bingbot|Bolt|AdobeAIR|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera
 
Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|iTunes|MacAppStore|NetNewsWire|Space
 Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen 
Browser|Polaris|Abrowser|Planetweb|ICE 
Browser|mDolphin|qutebrowser|Otter|QupZilla|MailBar|kmail2|YahooMobileMail|ExchangeWebServices|ExchangeServicesClient|Dragon|Outlook-iOS-Android)/(\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Chrome/Chromium/major_version.minor_version
-  - regex: '(Chromium|Chrome)/(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?'
+  - regex: '(Chromium|Chrome)/(\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
 
   ##########
   # IE Mobile needs to happen before Android to catch cases such as:
@@ -498,8 +525,8 @@
   # Podcast catchers
   - regex: '^(bPod|Pocket Casts|Player FM)$'
   - regex: '^(AlexaMediaPlayer|VLC)/(\d+)\.(\d+)\.([^.\s]+)'
-  - regex: 
'^(AntennaPod|WMPlayer|Zune|Podkicker|Radio|ExoPlayerDemo|Overcast|PocketTunes|NSPlayer|okhttp|DoggCatcher|QuickNews|QuickTime|Peapod|Podcasts|GoldenPod|VLC|Spotify|Miro|MediaGo|Juice|iPodder|gPodder|Banshee)/(\d+)\.(\d+)\.?(\d+)?\.?(\d+)?'
-  - regex: '^(Peapod|Liferea)/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
+  - regex: 
'^(AntennaPod|WMPlayer|Zune|Podkicker|Radio|ExoPlayerDemo|Overcast|PocketTunes|NSPlayer|okhttp|DoggCatcher|QuickNews|QuickTime|Peapod|Podcasts|GoldenPod|VLC|Spotify|Miro|MediaGo|Juice|iPodder|gPodder|Banshee)/(\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
+  - regex: '^(Peapod|Liferea)/([^.\s]+)\.([^.\s]+|)\.?([^.\s]+|)'
   - regex: '^(bPod|Player FM) BMID/(\S+)'
   - regex: '^(Podcast ?Addict)/v(\d+) '
   - regex: '^(Podcast ?Addict) '
@@ -509,8 +536,8 @@
   - regex: '(CITA) RSS Aggregator/(\d+)\.(\d+)'
   - regex: '(Pocket Casts)$'
   - regex: '(Player FM)$'
-  - regex: '(LG Player|Doppler|FancyMusic|MediaMonkey|Clementine) 
(\d+)\.(\d+)\.?([^.\s]+)?\.?([^.\s]+)?'
-  - regex: '(philpodder)/(\d+)\.(\d+)\.?([^.\s]+)?\.?([^.\s]+)?'
+  - regex: '(LG Player|Doppler|FancyMusic|MediaMonkey|Clementine) 
(\d+)\.(\d+)\.?([^.\s]+|)\.?([^.\s]+|)'
+  - regex: '(philpodder)/(\d+)\.(\d+)\.?([^.\s]+|)\.?([^.\s]+|)'
   - regex: '(Player FM|Pocket 
Casts|DoggCatcher|Spotify|MediaMonkey|MediaGo|BashPodder)'
   - regex: '(QuickTime)\.(\d+)\.(\d+)\.(\d+)'
   - regex: '(Kinoma)(\d+)'
@@ -518,35 +545,35 @@
     family_replacement: 'FancyMusic'
   - regex: 'EspnDownloadManager'
     family_replacement: 'ESPN'
-  - regex: '(ESPN) Radio (\d+)\.(\d+)\.?(\d+)? ?(?:rv:(\d+))? '
-  - regex: '(podracer|jPodder) v ?(\d+)\.(\d+)\.?(\d+)?'
+  - regex: '(ESPN) Radio (\d+)\.(\d+)(?:\.(\d+)|) ?(?:rv:(\d+)|) '
+  - regex: '(podracer|jPodder) v ?(\d+)\.(\d+)(?:\.(\d+)|)'
   - regex: '(ZDM)/(\d+)\.(\d+)[; ]?'
-  - regex: '(Zune|BeyondPod) (\d+)\.?(\d+)?[\);]'
+  - regex: '(Zune|BeyondPod) (\d+)(?:\.(\d+)|)[\);]'
   - regex: '(WMPlayer)/(\d+)\.(\d+)\.(\d+)\.(\d+)'
   - regex: '^(Lavf)'
     family_replacement: 'WMPlayer'
-  - regex: '^(RSSRadio)[ /]?(\d+)?'
+  - regex: '^(RSSRadio)[ /]?(\d+|)'
   - regex: '(RSS_Radio) (\d+)\.(\d+)'
     family_replacement: 'RSSRadio'
   - regex: '(Podkicker) \S+/(\d+)\.(\d+)\.(\d+)'
     family_replacement: 'Podkicker'
-  - regex: '^(HTC) Streaming Player \S+ / \S+ / \S+ / (\d+)\.(\d+)\.?(\d+)?'
+  - regex: '^(HTC) Streaming Player \S+ / \S+ / \S+ / (\d+)\.(\d+)(?:\.(\d+)|)'
   - regex: '^(Stitcher)/iOS'
   - regex: '^(Stitcher)/Android'
   - regex: '^(VLC) .*version (\d+)\.(\d+)\.(\d+)'
   - regex: ' (VLC) for'
   - regex: '(vlc)/(\d+)\.(\d+)\.(\d+)'
     family_replacement: 'VLC'
-  - regex: '^(foobar)\S+/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
-  - regex: '^(Clementine)\S+ ([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
-  - regex: '(amarok)/([^.\s]+)\.([^.\s]+)?\.?([^.\s]+)?'
+  - regex: '^(foobar)\S+/([^.\s]+)\.([^.\s]+|)\.?([^.\s]+|)'
+  - regex: '^(Clementine)\S+ ([^.\s]+)\.([^.\s]+|)\.?([^.\s]+|)'
+  - regex: '(amarok)/([^.\s]+)\.([^.\s]+|)\.?([^.\s]+|)'
     family_replacement: 'Amarok'
   - regex: '(Custom)-Feed Reader'
 
   # Browser major_version.minor_version.beta_version (space instead of slash)
   - regex: '(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo 
Browser) (\d+)\.(\d+)\.(\d+)'
   # Browser major_version.minor_version (space instead of slash)
-  - regex: '(iCab|Lunascape|Opera|Android|Jasmine|Polaris|Microsoft 
SkyDriveSync|The Bat!) (\d+)\.(\d+)\.?(\d+)?'
+  - regex: '(iCab|Lunascape|Opera|Android|Jasmine|Polaris|Microsoft 
SkyDriveSync|The Bat!) (\d+)\.(\d+)(?:\.(\d+)|)'
 
   # Kindle WebKit
   - regex: '(Kindle)/(\d+)\.(\d+)'
@@ -586,12 +613,16 @@
   - regex: '(ownCloud-android)/(\d+)\.(\d+)\.(\d+)'
     family_replacement: 'Owncloud'
 
+  # Skype for Business
+  - regex: '(OC)/(\d+)\.(\d+)\.(\d+)\.(\d+) \(Skype for Business\)'
+    family_replacement: 'Skype'
+
   #### END MAIN CASES ####
 
   #### SPECIAL CASES ####
   - regex: '(Obigo)InternetBrowser'
   - regex: '(Obigo)\-Browser'
-  - regex: '(Obigo|OBIGO)[^\d]*(\d+)(?:.(\d+))?'
+  - regex: '(Obigo|OBIGO)[^\d]*(\d+)(?:.(\d+)|)'
     family_replacement: 'Obigo'
 
   - regex: '(MAXTHON|Maxthon) (\d+)\.(\d+)'
@@ -610,21 +641,21 @@
   - regex: '(Embider)/(\d+)\.(\d+)'
     family_replacement: 'Polaris'
 
-  - regex: '(BonEcho)/(\d+)\.(\d+)\.?([ab]?\d+)?'
+  - regex: '(BonEcho)/(\d+)\.(\d+)\.?([ab]?\d+|)'
     family_replacement: 'Bon Echo'
 
   # @note: iOS / OSX Applications
   - regex: '(iPod|iPhone|iPad).+GSA/(\d+)\.(\d+)\.(\d+) Mobile'
     family_replacement: 'Google'
-  - regex: '(iPod|iPhone|iPad).+Version/(\d+)\.(\d+)(?:\.(\d+))?.*[ +]Safari'
+  - regex: '(iPod|iPhone|iPad).+Version/(\d+)\.(\d+)(?:\.(\d+)|).*[ +]Safari'
     family_replacement: 'Mobile Safari'
-  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+))?.* AppleNews\/\d+\.\d+\.\d+?'
+  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+)|).* AppleNews\/\d+\.\d+\.\d+?'
     family_replacement: 'Mobile Safari UI/WKWebView'
-  - regex: '(iPod|iPhone|iPad).+Version/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(iPod|iPhone|iPad).+Version/(\d+)\.(\d+)(?:\.(\d+)|)'
     family_replacement: 'Mobile Safari UI/WKWebView'
-  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+))?.*Mobile.*[ +]Safari'
+  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+)|).*Mobile.*[ +]Safari'
     family_replacement: 'Mobile Safari'
-  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+))?.*Mobile'
+  - regex: '(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ 
+](\d+)_(\d+)(?:_(\d+)|).*Mobile'
     family_replacement: 'Mobile Safari UI/WKWebView'
   - regex: '(iPod|iPhone|iPad).* Safari'
     family_replacement: 'Mobile Safari'
@@ -697,18 +728,18 @@
 
   - regex: '(QtWeb) Internet Browser/(\d+)\.(\d+)'
 
-  #- regex: '\(iPad;.+(Version)/(\d+)\.(\d+)(?:\.(\d+))?.*Safari/'
+  #- regex: '\(iPad;.+(Version)/(\d+)\.(\d+)(?:\.(\d+)|).*Safari/'
   #  family_replacement: 'iPad'
 
   # Phantomjs, should go before Safari
   - regex: '(PhantomJS)/(\d+)\.(\d+)\.(\d+)'
 
   # WebKit Nightly
-  - regex: '(AppleWebKit)/(\d+)\.?(\d+)?\+ .* Safari'
+  - regex: '(AppleWebKit)/(\d+)(?:\.(\d+)|)\+ .* Safari'
     family_replacement: 'WebKit Nightly'
 
   # Safari
-  - regex: '(Version)/(\d+)\.(\d+)(?:\.(\d+))?.*Safari/'
+  - regex: '(Version)/(\d+)\.(\d+)(?:\.(\d+)|).*Safari/'
     family_replacement: 'Safari'
   # Safari didn't provide "Version/d.d.d" prior to 3.0
   - regex: '(Safari)/\d+'
@@ -743,7 +774,7 @@
     v1_replacement: '8'
 
   # Espial
-  - regex: '(Espial)/(\d+)(?:\.(\d+))?(?:\.(\d+))?'
+  - regex: '(Espial)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
 
  # Apple Mail
 
@@ -755,7 +786,7 @@
   # AFTER IE11
   # BEFORE all other IE
   - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)'
-  - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?'
+  - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*|)'
 
   - regex: '([MS]?IE) (\d+)\.(\d+)'
     family_replacement: 'IE'
@@ -764,13 +795,13 @@
     family_replacement: 'Python Requests'
 
   # headless user-agents
-  - regex: 
'\b(Windows-Update-Agent|Microsoft-CryptoAPI|SophosUpdateManager|SophosAgent|Debian
 APT-HTTP|Ubuntu 
APT-HTTP|libcurl-agent|libwww-perl|urlgrabber|curl|PycURL|Wget|aria2|Axel|OpenBSD
 ftp|lftp|jupdate|insomnia)(?:[ /](\d+)(?:\.(\d+)(?:\.(\d+))?)?)?'
+  - regex: 
'\b(Windows-Update-Agent|Microsoft-CryptoAPI|SophosUpdateManager|SophosAgent|Debian
 APT-HTTP|Ubuntu 
APT-HTTP|libcurl-agent|libwww-perl|urlgrabber|curl|PycURL|Wget|aria2|Axel|OpenBSD
 ftp|lftp|jupdate|insomnia)(?:[ /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)'
 
-  - regex: '(Java)[/ ]{0,1}\d+\.(\d+)\.(\d+)[_-]*([a-zA-Z0-9]+)*'
+  - regex: '(Java)[/ ]{0,1}\d+\.(\d+)\.(\d+)[_-]*([a-zA-Z0-9]+|)'
 
   # Cloud Storage Clients
-  - regex: '^(Cyberduck)/(\d+)\.(\d+)\.(\d+)(?:\.\d+)?'
-  - regex: '^(S3 Browser) (\d+)-(\d+)-(\d+)(?:\s*http://s3browser\.com)?'
+  - regex: '^(Cyberduck)/(\d+)\.(\d+)\.(\d+)(?:\.\d+|)'
+  - regex: '^(S3 Browser) (\d+)-(\d+)-(\d+)(?:\s*http://s3browser\.com|)'
   # rclone - rsync for cloud storage - https://rclone.org/
   - regex: '^(rclone)/v(\d+)\.(\d+)'
 
@@ -784,6 +815,10 @@
   # Box Drive and Box Sync https://www.box.com/resources/downloads
   - regex: '^(Box(?: Sync)?)/(\d+)\.(\d+)\.(\d+)'
 
+  # ViaFree streaming app https://www.viafree.{dk|se|no}
+  - regex: '^(ViaFree|Viafree)-(?:tvOS-)?[A-Z]{2}/(\d+)\.(\d+)\.(\d+)'
+    family_replacement: 'ViaFree'
+
 os_parsers:
   ##########
   # HbbTV vendors
@@ -829,11 +864,11 @@
   # Philips : not found any other way than a manual mapping
   # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 
NETTV/4.1.3 PHILIPSTV/1.1.1; en) Presto/2.10.250 Version/11.60
   # Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 
NETTV/3.2.1; en) Presto/2.6.33 Version/10.70
-  - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/4'
+  - regex: 'HbbTV/1\.1\.1 \(; (Philips);.*NETTV/4'
     os_v1_replacement: '2013'
-  - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/3'
+  - regex: 'HbbTV/1\.1\.1 \(; (Philips);.*NETTV/3'
     os_v1_replacement: '2012'
-  - regex: 'HbbTV/1.1.1 \(; (Philips);.*NETTV/2'
+  - regex: 'HbbTV/1\.1\.1 \(; (Philips);.*NETTV/2'
     os_v1_replacement: '2011'
 
   # the HbbTV emulator developers use HbbTV/1.1.1 (;;;;;) 
firetv-firefox-plugin 1.1.20
@@ -854,14 +889,14 @@
   - regex: '(Windows Phone) (?:OS[ /])?(\d+)\.(\d+)'
 
   # Again a MS-special one: iPhone.*Outlook-iOS-Android/x.x is erroneously 
detected as Android
-  - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone)[ 
+]+(\d+)[_\.](\d+)(?:[_\.](\d+))?.*Outlook-iOS-Android'
+  - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone)[ 
+]+(\d+)[_\.](\d+)(?:[_\.](\d+)|).*Outlook-iOS-Android'
     os_replacement: 'iOS'
 
   ##########
   # Android
   # can actually detect rooted android os. do we care?
   ##########
-  - regex: '(Android)[ \-/](\d+)\.?(\d+)?(?:[.\-]([a-z0-9]+))?'
+  - regex: '(Android)[ \-/](\d+)(?:\.(\d+)|)(?:[.\-]([a-z0-9]+)|)'
 
   - regex: '(Android) Donut'
     os_v1_replacement: '1'
@@ -883,18 +918,18 @@
     os_v1_replacement: '3'
 
   # UCWEB
-  - regex: '^UCWEB.*; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?;'
+  - regex: '^UCWEB.*; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]+)|);'
     os_replacement: 'Android'
-  - regex: '^UCWEB.*; (iPad|iPh|iPd) OS (\d+)_(\d+)(?:_(\d+))?;'
+  - regex: '^UCWEB.*; (iPad|iPh|iPd) OS (\d+)_(\d+)(?:_(\d+)|);'
     os_replacement: 'iOS'
-  - regex: '^UCWEB.*; (wds) (\d+)\.(\d+)(?:\.(\d+))?;'
+  - regex: '^UCWEB.*; (wds) (\d+)\.(\d+)(?:\.(\d+)|);'
     os_replacement: 'Windows Phone'
   # JUC
-  - regex: '^(JUC).*; ?U; ?(?:Android)?(\d+)\.(\d+)(?:[\.\-]([a-z0-9]+))?'
+  - regex: '^(JUC).*; ?U; ?(?:Android|)(\d+)\.(\d+)(?:[\.\-]([a-z0-9]+)|)'
     os_replacement: 'Android'
 
   # Salesforce
-  - regex: '(android)\s(?:mobile\/)(\d+)(?:\.?(\d+))?(?:\.?(\d+))?'
+  - regex: '(android)\s(?:mobile\/)(\d+)(?:\.(\d+)(?:\.(\d+)|)|)'
     os_replacement: 'Android'
 
   ##########
@@ -908,7 +943,7 @@
   # properly identify as Chrome OS
   #
   # ex: Mozilla/5.0 (X11; Windows aarch64 10718.88.2) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/68.0.3440.118 Safari/537.36 CitrixChromeApp
-  - regex: '(x86_64|aarch64)\ 
(\d+)+\.(\d+)+\.(\d+)+.*Chrome.*(?:CitrixChromeApp)$'
+  - regex: '(x86_64|aarch64)\ 
(\d+)\.(\d+)\.(\d+).*Chrome.*(?:CitrixChromeApp)$'
     os_replacement: 'Chrome OS'
 
   ##########
@@ -945,8 +980,6 @@
     os_replacement: 'Windows'
     os_v1_replacement: 'ME'
 
-  - regex: '(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 
7|Windows NT 4\.0|Windows Vista|Windows 2000|Windows 3.1)'
-
   - regex: '(Windows NT 6\.2; ARM;)'
     os_replacement: 'Windows'
     os_v1_replacement: 'RT'
@@ -989,7 +1022,7 @@
     os_replacement: 'Windows'
     os_v1_replacement: 'CE'
 
-  - regex: 'Win ?(95|98|3.1|NT|ME|2000)'
+  - regex: 'Win(?:dows)? ?(95|98|3.1|NT|ME|2000|XP|Vista|7|CE)'
     os_replacement: 'Windows'
     os_v1_replacement: '$1'
 
@@ -1017,13 +1050,13 @@
   # @ref: http://en.wikipedia.org/wiki/Mac_OS_X#Versions
   # @ref: http://www.puredarwin.org/curious/versions
   ##########
-  - regex: '((?:Mac[ +]?|; )OS[ 
+]X)[\s+/](?:(\d+)[_.](\d+)(?:[_.](\d+))?|Mach-O)'
+  - regex: '((?:Mac[ +]?|; )OS[ 
+]X)[\s+/](?:(\d+)[_.](\d+)(?:[_.](\d+)|)|Mach-O)'
     os_replacement: 'Mac OS X'
-  - regex: '(\w+\s+Mac OS X\s+\w+\s+(\d+).(\d+).(\d+).*)'
+  - regex: '\w+\s+Mac OS X\s+\w+\s+(\d+).(\d+).(\d+).*'
     os_replacement: 'Mac OS X'
-    os_v1_replacement: '$2'
-    os_v2_replacement: '$3'
-    os_v3_replacement: '$4'
+    os_v1_replacement: '$1'
+    os_v2_replacement: '$2'
+    os_v3_replacement: '$3'
   # Leopard
   - regex: ' (Dar)(win)/(9).(\d+).*\((?:i386|x86_64|Power Macintosh)\)'
     os_replacement: 'Mac OS X'
@@ -1062,7 +1095,7 @@
   - regex: '(?:PPC|Intel) (Mac OS X)'
 
   # Box Drive and Box Sync on Mac OS X use OSX version numbers, not Darwin
-  - regex: '^Box.*;(Darwin)/(10)\.(1\d)(?:\.(\d+))?'
+  - regex: '^Box.*;(Darwin)/(10)\.(1\d)(?:\.(\d+)|)'
     os_replacement: 'Mac OS X'
 
   ##########
@@ -1070,10 +1103,10 @@
   # http://en.wikipedia.org/wiki/IOS_version_history
   ##########
   # keep this above generic iOS, since AppleTV UAs contain 'CPU OS'
-  - regex: '(Apple\s?TV)(?:/(\d+)\.(\d+))?'
+  - regex: '(Apple\s?TV)(?:/(\d+)\.(\d+)|)'
     os_replacement: 'ATV OS X'
 
-  - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ 
+]+(\d+)[_\.](\d+)(?:[_\.](\d+))?'
+  - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ 
+]+(\d+)[_\.](\d+)(?:[_\.](\d+)|)'
     os_replacement: 'iOS'
 
   # remaining cases are mostly only opera uas, so catch opera as to not catch 
iphone spoofs
@@ -1255,7 +1288,7 @@
     os_replacement: 'iOS'
 
   # iOS Apps
-  - regex: '\b(iOS[ /]|iOS; |iPhone(?:/| v|[ _]OS[/,]|; | OS : |\d,\d/|\d,\d; 
)|iPad/)(\d{1,2})[_\.](\d{1,2})(?:[_\.](\d+))?'
+  - regex: '\b(iOS[ /]|iOS; |iPhone(?:/| v|[ _]OS[/,]|; | OS : |\d,\d/|\d,\d; 
)|iPad/)(\d{1,2})[_\.](\d{1,2})(?:[_\.](\d+)|)'
     os_replacement: 'iOS'
   - regex: '\((iOS);'
 
@@ -1264,10 +1297,16 @@
   ##########################
   - regex: 'Outlook-(iOS)/\d+\.\d+\.prod\.iphone'
 
+  ##########################
+  # iOS devices, the same regex matches mobile safari webviews
+  ##########################
+  - regex: '(iPod|iPhone|iPad)'
+    os_replacement: 'iOS'
+
   ##########
   # Apple TV
   ##########
-  - regex: '(tvOS)/(\d+).(\d+)'
+  - regex: '(tvOS)[/ ](\d+)\.(\d+)(?:\.(\d+)|)'
     os_replacement: 'tvOS'
 
   ##########
@@ -1276,7 +1315,7 @@
   # http://code.google.com/p/chromium-os/issues/detail?id=11573
   # http://code.google.com/p/chromium-os/issues/detail?id=13790
   ##########
-  - regex: '(CrOS) [a-z0-9_]+ (\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(CrOS) [a-z0-9_]+ (\d+)\.(\d+)(?:\.(\d+)|)'
     os_replacement: 'Chrome OS'
 
   ##########
@@ -1284,8 +1323,8 @@
   ##########
   - regex: '([Dd]ebian)'
     os_replacement: 'Debian'
-  - regex: '(Linux Mint)(?:/(\d+))?'
-  - regex: '(Mandriva)(?: Linux)?/(?:[\d.-]+m[a-z]{2}(\d+).(\d))?'
+  - regex: '(Linux Mint)(?:/(\d+)|)'
+  - regex: '(Mandriva)(?: Linux|)/(?:[\d.-]+m[a-z]{2}(\d+).(\d)|)'
 
   ##########
   # Symbian + Symbian OS
@@ -1314,9 +1353,9 @@
   ##########
   - regex: '(BB10);.+Version/(\d+)\.(\d+)\.(\d+)'
     os_replacement: 'BlackBerry OS'
-  - regex: '(Black[Bb]erry)[0-9a-z]+/(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Black[Bb]erry)[0-9a-z]+/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)'
     os_replacement: 'BlackBerry OS'
-  - regex: '(Black[Bb]erry).+Version/(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(Black[Bb]erry).+Version/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)'
     os_replacement: 'BlackBerry OS'
   - regex: '(RIM Tablet OS) (\d+)\.(\d+)\.(\d+)'
     os_replacement: 'BlackBerry Tablet OS'
@@ -1383,20 +1422,20 @@
   ##########
   # Google TV
   ##########
-  - regex: '(GoogleTV)(?: (\d+)\.(\d+)(?:\.(\d+))?|/[\da-z]+)'
+  - regex: '(GoogleTV)(?: (\d+)\.(\d+)(?:\.(\d+)|)|/[\da-z]+)'
 
   - regex: '(WebTV)/(\d+).(\d+)'
 
   ##########
   # Chromecast
   ##########
-  - regex: '(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+))?)?'
+  - regex: '(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+)|)|)'
     os_replacement: 'Chromecast'
 
   ##########
   # Misc mobile
   ##########
-  - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+))?'
+  - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|)'
     os_replacement: 'webOS'
   - regex: '(VRE);'
 
@@ -1404,10 +1443,10 @@
   # Generic patterns
   # since the majority of os cases are very specific, these go last
   ##########
-  - regex: '(Fedora|Red 
Hat|PCLinuxOS|Puppy|Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Slackware|(?:Free|Open|Net|\b)BSD)[/
 ](\d+)\.(\d+)(?:\.(\d+)(?:\.(\d+))?)?'
+  - regex: '(Fedora|Red 
Hat|PCLinuxOS|Puppy|Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Slackware|(?:Free|Open|Net|\b)BSD)[/
 ](\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|)'
 
   # Gentoo Linux + Kernel Version
-  - regex: '(Linux)[ /](\d+)\.(\d+)(?:\.(\d+))?.*gentoo'
+  - regex: '(Linux)[ /](\d+)\.(\d+)(?:\.(\d+)|).*gentoo'
     os_replacement: 'Gentoo'
 
   # Opera Mini Bada
@@ -1417,7 +1456,7 @@
   - regex: '(Windows|Android|WeTab|Maemo|Web0S)'
   - regex: '(Ubuntu|Kubuntu|Arch 
Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red 
Hat|Fedora|PCLinuxOS|Mageia|(?:Free|Open|Net|\b)BSD)'
   # Linux + Kernel Version
-  - regex: '(Linux)(?:[ /](\d+)\.(\d+)(?:\.(\d+))?)?'
+  - regex: '(Linux)(?:[ /](\d+)\.(\d+)(?:\.(\d+)|)|)'
   - regex: 'SunOS'
     os_replacement: 'Solaris'
   # Wget/x.x.x (linux-gnu)
@@ -1448,6 +1487,16 @@
     brand_replacement: 'Spider'
     model_replacement: 'Feature Phone'
 
+  # PTST / WebPageTest.org crawlers
+  - regex: ' PTST/\d+\.\d+$'
+    device_replacement: 'Spider'
+    brand_replacement: 'Spider'
+
+  # Datanyze.com spider
+  - regex: 'X11; Datanyze; Linux'
+    device_replacement: 'Spider'
+    brand_replacement: 'Spider'
+
   #########
   # WebBrowser for SmartWatch
   # @ref: 
https://play.google.com/store/apps/details?id=se.vaggan.webbrowser&hl=en
@@ -1464,7 +1513,7 @@
   ######################################################################
 
   # Android Application
-  - regex: 'Android Application[^\-]+ - (Sony) ?(Ericsson)? (.+) \w+ - '
+  - regex: 'Android Application[^\-]+ - (Sony) ?(Ericsson|) (.+) \w+ - '
     device_replacement: '$1 $2'
     brand_replacement: '$1$2'
     model_replacement: '$3'
@@ -1495,7 +1544,7 @@
   # Acer
   # @ref: http://us.acer.com/ac/en/US/content/group/tablets
   #########
-  - regex: 'Android [34].*; 
*(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700(?: Lite| 
3G)?|A701|B1-A71|A1-\d{3}|B1-\d{3}|V360|V370|W500|W500P|W501|W501P|W510|W511|W700|Slider
 SL101|DA22[^;/]+) Build'
+  - regex: 'Android [34].*; 
*(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700(?: Lite| 
3G|)|A701|B1-A71|A1-\d{3}|B1-\d{3}|V360|V370|W500|W500P|W501|W501P|W510|W511|W700|Slider
 SL101|DA22[^;/]+) Build'
     device_replacement: '$1'
     brand_replacement: 'Acer'
     model_replacement: '$1'
@@ -1518,7 +1567,7 @@
   # @note: VegaBean and VegaComb (names derived from jellybean, honeycomb) are
   #   custom ROM builds for Vega
   #########
-  - regex: '; *(Advent )?(Vega(?:Bean|Comb)?).* Build'
+  - regex: '; *(Advent |)(Vega(?:Bean|Comb|)).* Build'
     device_replacement: '$1$2'
     brand_replacement: 'Advent'
     model_replacement: '$2'
@@ -1527,7 +1576,7 @@
   # Ainol
   # @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product
   #########
-  - regex: '; *(Ainol )?((?:NOVO|[Nn]ovo)[^;/]+) Build'
+  - regex: '; *(Ainol |)((?:NOVO|[Nn]ovo)[^;/]+) Build'
     device_replacement: '$1$2'
     brand_replacement: 'Ainol'
     model_replacement: '$2'
@@ -1564,7 +1613,7 @@
     device_replacement: 'Alcatel One Touch $2'
     brand_replacement: 'Alcatel'
     model_replacement: 'One Touch $2'
-  - regex: '; *(?:alcatel[ _])?(?:(?:one[ _]?touch[ _])|ot[ \-])([^;/]+);? 
Build'
+  - regex: '; *(?:alcatel[ _]|)(?:(?:one[ _]?touch[ _])|ot[ \-])([^;/]+);? 
Build'
     regex_flag: 'i'
     device_replacement: 'Alcatel One Touch $1'
     brand_replacement: 'Alcatel'
@@ -1604,7 +1653,7 @@
     device_replacement: '$1$2'
     brand_replacement: 'Allview'
     model_replacement: '$2'
-  - regex: '; *(ALLVIEW[ _]?|Allview[ _]?)?(AX1_Shine|AX2_Frenzy) Build'
+  - regex: '; *(ALLVIEW[ _]?|Allview[ _]?|)(AX1_Shine|AX2_Frenzy) Build'
     device_replacement: '$1$2'
     brand_replacement: 'Allview'
     model_replacement: '$2'
@@ -1664,7 +1713,7 @@
   # @ref: http://www.luckystar.com.cn/en/mobiletel.aspx?page=1
   # @note: brand owned by luckystar
   #########
-  - regex: '; 
*(G7|M1013|M1015G|M11[CG]?|M-?12[B]?|M15|M19[G]?|M30[ACQ]?|M31[GQ]|M32|M33[GQ]|M36|M37|M38|M701T|M710|M712B|M713|M715G|M716G|M71(?:G|GS|T)?|M72[T]?|M73[T]?|M75[GT]?|M77G|M79T|M7L|M7LN|M81|M810|M81T|M82|M92|M92KS|M92S|M717G|M721|M722G|M723|M725G|M739|M785|M791|M92SK|M93D)
 Build'
+  - regex: '; 
*(G7|M1013|M1015G|M11[CG]?|M-?12[B]?|M15|M19[G]?|M30[ACQ]?|M31[GQ]|M32|M33[GQ]|M36|M37|M38|M701T|M710|M712B|M713|M715G|M716G|M71(?:G|GS|T|)|M72[T]?|M73[T]?|M75[GT]?|M77G|M79T|M7L|M7LN|M81|M810|M81T|M82|M92|M92KS|M92S|M717G|M721|M722G|M723|M725G|M739|M785|M791|M92SK|M93D)
 Build'
     device_replacement: 'Aoson $1'
     brand_replacement: 'Aoson'
     model_replacement: '$1'
@@ -1739,7 +1788,7 @@
   # Assistant
   # @ref: http://www.assistant.ua
   #########
-  - regex: '; *(?:ASSISTANT )?(AP)-?([1789]\d{2}[A-Z]{0,2}|80104) Build'
+  - regex: '; *(?:ASSISTANT |)(AP)-?([1789]\d{2}[A-Z]{0,2}|80104) Build'
     device_replacement: 'Assistant $1-$2'
     brand_replacement: 'Assistant'
     model_replacement: '$1-$2'
@@ -1748,7 +1797,7 @@
   # Asus
   # @ref: http://www.asus.com/uk/Tablets_Mobile/
   #########
-  - regex: '; *(ME17\d[^;/]*|ME3\d{2}[^;/]+|K00[A-Z]|Nexus 10|Nexus 7(?: 
2013)?|PadFone[^;/]*|Transformer[^;/]*|TF\d{3}[^;/]*|eeepc) Build'
+  - regex: '; *(ME17\d[^;/]*|ME3\d{2}[^;/]+|K00[A-Z]|Nexus 10|Nexus 7(?: 
2013|)|PadFone[^;/]*|Transformer[^;/]*|TF\d{3}[^;/]*|eeepc) Build'
     device_replacement: 'Asus $1'
     brand_replacement: 'Asus'
     model_replacement: '$1'
@@ -2296,7 +2345,7 @@
   # Gionee
   # @ref: http://www.gionee.com/
   #########
-  - regex: '; *(Gionee)[ _\-]([^;/]+)(?:/[^;/]+)? Build'
+  - regex: '; *(Gionee)[ _\-]([^;/]+)(?:/[^;/]+|) Build'
     regex_flag: 'i'
     device_replacement: '$1 $2'
     brand_replacement: 'Gionee'
@@ -2460,7 +2509,7 @@
   # @ref: http://www.huaweidevice.com
   # @note: Needs to be before HTC due to Desire HD Build on U8815
   #########
-  - regex: '; *(HUAWEI |Huawei-)?([UY][^;/]+) 
Build/(?:Huawei|HUAWEI)([UY][^\);]+)\)'
+  - regex: '; *(HUAWEI |Huawei-|)([UY][^;/]+) 
Build/(?:Huawei|HUAWEI)([UY][^\);]+)\)'
     device_replacement: '$1$2'
     brand_replacement: 'Huawei'
     model_replacement: '$2'
@@ -2476,7 +2525,7 @@
     device_replacement: '$1$2'
     brand_replacement: 'Huawei'
     model_replacement: '$2'
-  - regex: '; *((?:HUAWEI[ _]?|Huawei[ _])?Ascend[ _])([^;/]+) Build'
+  - regex: '; *((?:HUAWEI[ _]?|Huawei[ _]|)Ascend[ _])([^;/]+) Build'
     device_replacement: '$1$2'
     brand_replacement: 'Huawei'
     model_replacement: '$2'
@@ -2531,33 +2580,33 @@
     device_replacement: 'HTC $1'
     brand_replacement: 'HTC'
     model_replacement: '$1'
-  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+))?(?:[/\\]1\.0 | V|/| 
+)\d+\.\d[\d\.]*(?: *Build|\))'
+  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)|)(?:[/\\]1\.0 | V|/| 
+)\d+\.\d[\d\.]*(?: *Build|\))'
     device_replacement: 'HTC $1 $2'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2'
-  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ 
_/]+))?)?(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: *Build|\))'
+  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ 
_/]+)|)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: *Build|\))'
     device_replacement: 'HTC $1 $2 $3'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2 $3'
-  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)(?:[ 
_/]([^ _/]+))?)?)?(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: *Build|\))'
+  - regex: '; *(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)(?:[ 
_/]([^ _/]+)|)|)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: *Build|\))'
     device_replacement: 'HTC $1 $2 $3 $4'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2 $3 $4'
 
   # Android HTC without Version Number matcher
-  - regex: '; *(?:(?:HTC|htc)(?:_blocked)*[ _/])+([^ _/;]+)(?: *Build|[;\)]| - 
)'
+  - regex: '; *(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/;]+)(?: *Build|[;\)]| - 
)'
     device_replacement: 'HTC $1'
     brand_replacement: 'HTC'
     model_replacement: '$1'
-  - regex: '; *(?:(?:HTC|htc)(?:_blocked)*[ _/])+([^ _/]+)(?:[ _/]([^ 
_/;\)]+))?(?: *Build|[;\)]| - )'
+  - regex: '; *(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ 
_/;\)]+)|)(?: *Build|[;\)]| - )'
     device_replacement: 'HTC $1 $2'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2'
-  - regex: '; *(?:(?:HTC|htc)(?:_blocked)*[ _/])+([^ _/]+)(?:[ _/]([^ 
_/]+)(?:[ _/]([^ _/;\)]+))?)?(?: *Build|[;\)]| - )'
+  - regex: '; *(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ 
_/]+)(?:[ _/]([^ _/;\)]+)|)|)(?: *Build|[;\)]| - )'
     device_replacement: 'HTC $1 $2 $3'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2 $3'
-  - regex: '; *(?:(?:HTC|htc)(?:_blocked)*[ _/])+([^ _/]+)(?:[ _/]([^ 
_/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ /;]+))?)?)?(?: *Build|[;\)]| - )'
+  - regex: '; *(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ 
_/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ /;]+)|)|)|)(?: *Build|[;\)]| - )'
     device_replacement: 'HTC $1 $2 $3 $4'
     brand_replacement: 'HTC'
     model_replacement: '$1 $2 $3 $4'
@@ -2568,7 +2617,7 @@
     brand_replacement: 'HTC'
     model_replacement: '$1'
   # general matcher for anything else
-  - regex: '(?:[;,] *|^)(?:htccn_chs-)?HTC[ _-]?([^;]+?)(?: 
*Build|clay|Android|-?Mozilla| Opera| Profile| UNTRUSTED|[;/\(\)]|$)'
+  - regex: '(?:[;,] *|^)(?:htccn_chs-|)HTC[ _-]?([^;]+?)(?: 
*Build|clay|Android|-?Mozilla| Opera| Profile| UNTRUSTED|[;/\(\)]|$)'
     regex_flag: 'i'
     device_replacement: 'HTC $1'
     brand_replacement: 'HTC'
@@ -2607,12 +2656,12 @@
   # iBall
   # @ref: http://www.iball.co.in/Category/Mobiles/22
   #########
-  - regex: '; *(?:iBall[ _\-])?(Andi)[ _]?(\d[^;/]*) Build'
+  - regex: '; *(?:iBall[ _\-]|)(Andi)[ _]?(\d[^;/]*) Build'
     regex_flag: 'i'
     device_replacement: '$1 $2'
     brand_replacement: 'iBall'
     model_replacement: '$1 $2'
-  - regex: '; *(IBall)(?:[ _]([^;/]+))? Build'
+  - regex: '; *(IBall)(?:[ _]([^;/]+)|) Build'
     regex_flag: 'i'
     device_replacement: '$1 $2'
     brand_replacement: 'iBall'
@@ -2622,7 +2671,7 @@
   # IconBIT
   # @ref: http://www.iconbit.com/catalog/tablets/
   #########
-  - regex: '; *(NT-\d+[^ ;/]*|Net[Tt]AB [^;/]+|Mercury [A-Z]+|iconBIT)(?: 
S/N:[^;/]+)? Build'
+  - regex: '; *(NT-\d+[^ ;/]*|Net[Tt]AB [^;/]+|Mercury [A-Z]+|iconBIT)(?: 
S/N:[^;/]+|) Build'
     device_replacement: '$1'
     brand_replacement: 'IconBIT'
     model_replacement: '$1'
@@ -2695,17 +2744,17 @@
   # @note: Zync also offers a "Cloud Z5" device
   #########
   # smartphones
-  - regex: '; *(?:Intex[ _])?(AQUA|Aqua)([ _\.\-])([^;/]+) *(?:Build|;)'
+  - regex: '; *(?:Intex[ _]|)(AQUA|Aqua)([ _\.\-])([^;/]+) *(?:Build|;)'
     device_replacement: '$1$2$3'
     brand_replacement: 'Intex'
     model_replacement: '$1 $3'
   # matches "INTEX CLOUD X1"
-  - regex: '; *(?:INTEX|Intex)(?:[_ ]([^\ _;/]+))(?:[_ ]([^\ _;/]+))? 
*(?:Build|;)'
+  - regex: '; *(?:INTEX|Intex)(?:[_ ]([^\ _;/]+))(?:[_ ]([^\ _;/]+)|) 
*(?:Build|;)'
     device_replacement: '$1 $2'
     brand_replacement: 'Intex'
     model_replacement: '$1 $2'
   # tablets
-  - regex: '; *([iI]Buddy)[ _]?(Connect)(?:_|\?_| )?([^;/]*) *(?:Build|;)'
+  - regex: '; *([iI]Buddy)[ _]?(Connect)(?:_|\?_| |)([^;/]*) *(?:Build|;)'
     device_replacement: '$1 $2 $3'
     brand_replacement: 'Intex'
     model_replacement: 'iBuddy $2 $3'
@@ -2728,7 +2777,7 @@
   # i.onik
   # @ref: http://www.i-onik.de/
   #########
-  - regex: '; *(TP\d+(?:\.\d+)?\-\d[^;/]+) Build'
+  - regex: '; *(TP\d+(?:\.\d+|)\-\d[^;/]+) Build'
     device_replacement: 'ionik $1'
     brand_replacement: 'ionik'
     model_replacement: '$1'
@@ -2944,7 +2993,7 @@
   # Lava
   # @ref: http://www.lavamobiles.com/
   #########
-  - regex: '; *(?:LAVA[ _])?IRIS[ _\-]?([^/;\)]+) *(?:;|\)|Build)'
+  - regex: '; *(?:LAVA[ _]|)IRIS[ _\-]?([^/;\)]+) *(?:;|\)|Build)'
     regex_flag: 'i'
     device_replacement: 'Iris $1'
     brand_replacement: 'Lava'
@@ -2996,15 +3045,15 @@
     device_replacement: 'Lenovo $1 $2'
     brand_replacement: 'Lenovo'
     model_replacement: '$1 $2'
-  - regex: '; *(?:LNV-)?(?:=?[Ll]enovo[ _\-]?|LENOVO[ 
_])+(.+?)(?:Build|[;/\)])'
+  - regex: '; *(?:LNV-|)(?:=?[Ll]enovo[ _\-]?|LENOVO[ _])(.+?)(?:Build|[;/\)])'
     device_replacement: 'Lenovo $1'
     brand_replacement: 'Lenovo'
     model_replacement: '$1'
-  - regex: '[;,] (?:Vodafone )?(SmartTab) ?(II) ?(\d+) Build/'
+  - regex: '[;,] (?:Vodafone |)(SmartTab) ?(II) ?(\d+) Build/'
     device_replacement: 'Lenovo $1 $2 $3'
     brand_replacement: 'Lenovo'
     model_replacement: '$1 $2 $3'
-  - regex: '; *(?:Ideapad )?K1 Build/'
+  - regex: '; *(?:Ideapad |)K1 Build/'
     device_replacement: 'Lenovo Ideapad K1'
     brand_replacement: 'Lenovo'
     model_replacement: 'Ideapad K1'
@@ -3034,7 +3083,7 @@
     device_replacement: '$1'
     brand_replacement: 'LG'
     model_replacement: '$1'
-  - regex: '[;:] *(L-\d+[A-Z]|LGL\d+[A-Z]?)(?:/V\d+)? *(?:Build|[;\)])'
+  - regex: '[;:] *(L-\d+[A-Z]|LGL\d+[A-Z]?)(?:/V\d+|) *(?:Build|[;\)])'
     device_replacement: '$1'
     brand_replacement: 'LG'
     model_replacement: '$1'
@@ -3117,7 +3166,7 @@
   # Medion
   # @ref: http://www.medion.com/en/
   #########
-  - regex: '; *(?:MD_)?LIFETAB[ _]([^;/]+) Build'
+  - regex: '; *(?:MD_|)LIFETAB[ _]([^;/]+) Build'
     regex_flag: 'i'
     device_replacement: 'Medion Lifetab $1'
     brand_replacement: 'Medion'
@@ -3195,7 +3244,7 @@
   # Modecom
   # @ref: http://www.modecom.eu/tablets/portal/
   #########
-  - regex: '; *(MODECOM )?(FreeTab) ?([^;/]+) Build'
+  - regex: '; *(MODECOM |)(FreeTab) ?([^;/]+) Build'
     regex_flag: 'i'
     device_replacement: '$1$2 $3'
     brand_replacement: 'Modecom'
@@ -3253,7 +3302,7 @@
   # MSI
   # @ref: http://www.msi.com/product/windpad/
   #########
-  - regex: '; *(?:MSI[ _])?(Primo\d+|Enjoy[ _\-][^;/]+) Build'
+  - regex: '; *(?:MSI[ _]|)(Primo\d+|Enjoy[ _\-][^;/]+) Build'
     regex_flag: 'i'
     device_replacement: '$1'
     brand_replacement: 'Msi'
@@ -3280,7 +3329,7 @@
     device_replacement: '$1$2 $3'
     brand_replacement: 'MyPhone'
     model_replacement: '$3'
-  - regex: '; *(A\d+)[ _](Duo)? Build'
+  - regex: '; *(A\d+)[ _](Duo|) Build'
     regex_flag: 'i'
     device_replacement: '$1 $2'
     brand_replacement: 'MyPhone'
@@ -3349,7 +3398,7 @@
     device_replacement: '$1$2'
     brand_replacement: 'Nook'
     model_replacement: '$2'
-  - regex: '; *(NOOK 
)?(BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2) Build'
+  - regex: '; *(NOOK 
|)(BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2) Build'
     device_replacement: '$1$2'
     brand_replacement: 'Nook'
     model_replacement: '$2'
@@ -3484,11 +3533,11 @@
   # @href: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA
   # @models: ADR8995, ADR910L, ADR930VW, C790, CDM8992, CDM8999, IS06, IS11PT, 
P2000, P2020, P2030, P4100, P5000, P6010, P6020, P6030, P7000, P7040, P8000, 
P8010, P9020, P9050, P9060, P9070, P9090, PT001, PT002, PT003, TXT8040, 
TXT8045, VEGA PTL21
   #########
-  - regex: '; *(SKY[ _])?(IM\-[AT]\d{3}[^;/]+).* Build/'
+  - regex: '; *(SKY[ _]|)(IM\-[AT]\d{3}[^;/]+).* Build/'
     device_replacement: 'Pantech $1$2'
     brand_replacement: 'Pantech'
     model_replacement: '$1$2'
-  - regex: '; *((?:ADR8995|ADR910L|ADR930L|ADR930VW|PTL21|P8000)(?: 4G)?) 
Build/'
+  - regex: '; *((?:ADR8995|ADR910L|ADR930L|ADR930VW|PTL21|P8000)(?: 4G|)) 
Build/'
     device_replacement: '$1'
     brand_replacement: 'Pantech'
     model_replacement: '$1'
@@ -3571,7 +3620,7 @@
   # Polaroid/ Acho
   # @ref: 
http://polaroidstore.com/store/start.asp?category_id=382&category_id2=0&order=title&filter1=&filter2=&filter3=&view=all
   #########
-  - regex: '; *(?:Polaroid[ 
_])?((?:MIDC\d{3,}|PMID\d{2,}|PTAB\d{3,})[^;/]*)(\/[^;/]*)? Build/'
+  - regex: '; *(?:Polaroid[ 
_]|)((?:MIDC\d{3,}|PMID\d{2,}|PTAB\d{3,})[^;/]*)(\/[^;/]*|) Build/'
     device_replacement: '$1'
     brand_replacement: 'Polaroid'
     model_replacement: '$1'
@@ -3598,7 +3647,7 @@
     device_replacement: '$1'
     brand_replacement: 'Positivo'
     model_replacement: '$1'
-  - regex: '; *(?:Positivo )?((?:YPY|Ypy)[^;/]+) Build/'
+  - regex: '; *(?:Positivo |)((?:YPY|Ypy)[^;/]+) Build/'
     device_replacement: '$1'
     brand_replacement: 'Positivo'
     model_replacement: '$1'
@@ -3626,7 +3675,7 @@
   # @ref: http://www.prestigio.com/catalogue/MultiPhones
   # @ref: http://www.prestigio.com/catalogue/MultiPads
   #########
-  - regex: '; *(?:Prestigio )?((?:PAP|PMP)\d[^;/]+) Build/'
+  - regex: '; *(?:Prestigio |)((?:PAP|PMP)\d[^;/]+) Build/'
     device_replacement: 'Prestigio $1'
     brand_replacement: 'Prestigio'
     model_replacement: '$1'
@@ -3644,7 +3693,7 @@
   # QMobile
   # @ref: http://www.qmobile.com.pk/
   #########
-  - regex: '; *(A2|A5|A8|A900)_?(Classic)? Build'
+  - regex: '; *(A2|A5|A8|A900)_?(Classic|) Build'
     device_replacement: '$1 $2'
     brand_replacement: 'Qmobile'
     model_replacement: '$1 $2'
@@ -3710,11 +3759,11 @@
   # Samsung Android Devices
   # @ref: http://www.samsung.com/us/mobile/cell-phones/all-products
   #########
-  - regex: '; *(SAMSUNG |Samsung )?((?:Galaxy (?:Note 
II|S\d)|GT-I9082|GT-I9205|GT-N7\d{3}|SM-N9005)[^;/]*)\/?[^;/]* Build/'
+  - regex: '; *(SAMSUNG |Samsung |)((?:Galaxy (?:Note 
II|S\d)|GT-I9082|GT-I9205|GT-N7\d{3}|SM-N9005)[^;/]*)\/?[^;/]* Build/'
     device_replacement: 'Samsung $1$2'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
-  - regex: '; *(Google )?(Nexus [Ss](?: 4G)?) Build/'
+  - regex: '; *(Google |)(Nexus [Ss](?: 4G|)) Build/'
     device_replacement: 'Samsung $1$2'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
@@ -3722,15 +3771,15 @@
     device_replacement: 'Samsung $2'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
-  - regex: '; *(Galaxy(?: Ace| Nexus| S ?II+|Nexus S| with MCR 1.2| Mini Plus 
4G)?) Build/'
+  - regex: '; *(Galaxy(?: Ace| Nexus| S ?II+|Nexus S| with MCR 1.2| Mini Plus 
4G|)) Build/'
     device_replacement: 'Samsung $1'
     brand_replacement: 'Samsung'
     model_replacement: '$1'
-  - regex: '; *(SAMSUNG[ _\-] *)+([^;/]+) Build'
+  - regex: '; *(SAMSUNG[ _\-]|)(?:SAMSUNG[ _\-])([^;/]+) Build'
     device_replacement: 'Samsung $2'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
-  - regex: '; *(SAMSUNG-)?(GT\-[BINPS]\d{4}[^\/]*)(\/[^ ]*) Build'
+  - regex: '; *(SAMSUNG-|)(GT\-[BINPS]\d{4}[^\/]*)(\/[^ ]*) Build'
     device_replacement: 'Samsung $1$2$3'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
@@ -3742,11 +3791,11 @@
     device_replacement: 'Samsung $1$2'
     brand_replacement: 'Samsung'
     model_replacement: '$2'
-  - regex: '; *((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9 ]+)(/?[^ ]*)? Build'
+  - regex: '; *((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9 ]+)(/?[^ ]*|) Build'
     device_replacement: 'Samsung $1'
     brand_replacement: 'Samsung'
     model_replacement: '$1'
-  - regex: ' ((?:SCH)\-[A-Za-z0-9 ]+)(/?[^ ]*)? Build'
+  - regex: ' ((?:SCH)\-[A-Za-z0-9 ]+)(/?[^ ]*|) Build'
     device_replacement: 'Samsung $1'
     brand_replacement: 'Samsung'
     model_replacement: '$1'
@@ -3883,7 +3932,7 @@
     device_replacement: '$1$2'
     brand_replacement: 'SonyEricsson'
     model_replacement: '$2'
-  - regex: '; *((?:SK|ST|E|X|LT|MK|MT|WT)\d{2}[a-z0-9]*(?:-o)?|R800i|U20i) 
Build'
+  - regex: '; *((?:SK|ST|E|X|LT|MK|MT|WT)\d{2}[a-z0-9]*(?:-o|)|R800i|U20i) 
Build'
     device_replacement: '$1'
     brand_replacement: 'SonyEricsson'
     model_replacement: '$1'
@@ -3947,7 +3996,7 @@
   # Spice
   # @ref: http://www.spicemobilephones.co.in/
   #########
-  - regex: '; *((?:CSL_Spice|Spice|SPICE|CSL)[ _\-]?)?([Mm][Ii])([ 
_\-])?(\d{3}[^;/]*) Build/'
+  - regex: '; *((?:CSL_Spice|Spice|SPICE|CSL)[ _\-]?|)([Mm][Ii])([ 
_\-]|)(\d{3}[^;/]*) Build/'
     device_replacement: '$1$2$3$4'
     brand_replacement: 'Spice'
     model_replacement: 'Mi$4'
@@ -4086,7 +4135,7 @@
     device_replacement: '$1'
     brand_replacement: 'HTC'
     model_replacement: 'Dream'
-  - regex: '\b(T-Mobile ?)?(myTouch)[ _]?([34]G)[ _]?([^\/]*) 
(?:Mozilla|Build)'
+  - regex: '\b(T-Mobile ?|)(myTouch)[ _]?([34]G)[ _]?([^\/]*) 
(?:Mozilla|Build)'
     device_replacement: '$1$2 $3 $4'
     brand_replacement: 'HTC'
     model_replacement: '$2 $3 $4'
@@ -4131,7 +4180,7 @@
     device_replacement: '$1'
     brand_replacement: 'Toshiba'
     model_replacement: 'Folio 100'
-  - regex: '; 
*(AT[0-9]{2,3}(?:\-A|LE\-A|PE\-A|SE|a)?|AT7-A|AT1S0|Hikari-iFrame/WDPF-[^;/]+|THRiVE|Thrive)
 Build/'
+  - regex: '; 
*(AT[0-9]{2,3}(?:\-A|LE\-A|PE\-A|SE|a|)|AT7-A|AT1S0|Hikari-iFrame/WDPF-[^;/]+|THRiVE|Thrive)
 Build/'
     device_replacement: 'Toshiba $1'
     brand_replacement: 'Toshiba'
     model_replacement: '$1'
@@ -4251,7 +4300,7 @@
   # Walton
   # @ref: http://www.waltonbd.com/
   #########
-  - regex: '; *(?:Walton[ _\-])?(Primo[ _\-][^;/]+) Build'
+  - regex: '; *(?:Walton[ _\-]|)(Primo[ _\-][^;/]+) Build'
     regex_flag: 'i'
     device_replacement: 'Walton $1'
     brand_replacement: 'Walton'
@@ -4261,7 +4310,7 @@
   # Wiko
   # @ref: http://fr.wikomobile.com/collection.php?s=Smartphones
   #########
-  - regex: '; *(?:WIKO[ 
\-])?(CINK\+?|BARRY|BLOOM|DARKFULL|DARKMOON|DARKNIGHT|DARKSIDE|FIZZ|HIGHWAY|IGGY|OZZY|RAINBOW|STAIRWAY|SUBLIM|WAX|CINK
 [^;/]+) Build/'
+  - regex: '; *(?:WIKO[ 
\-]|)(CINK\+?|BARRY|BLOOM|DARKFULL|DARKMOON|DARKNIGHT|DARKSIDE|FIZZ|HIGHWAY|IGGY|OZZY|RAINBOW|STAIRWAY|SUBLIM|WAX|CINK
 [^;/]+) Build/'
     regex_flag: 'i'
     device_replacement: 'Wiko $1'
     brand_replacement: 'Wiko'
@@ -4307,7 +4356,7 @@
   # Yarvik Zania
   # @ref: http://yarvik.com
   #########
-  - regex: '; *(?:Xenta |Luna 
)?(TAB[234][0-9]{2}|TAB0[78]-\d{3}|TAB0?9-\d{3}|TAB1[03]-\d{3}|SMP\d{2}-\d{3}) 
Build/'
+  - regex: '; *(?:Xenta |Luna 
|)(TAB[234][0-9]{2}|TAB0[78]-\d{3}|TAB0?9-\d{3}|TAB1[03]-\d{3}|SMP\d{2}-\d{3}) 
Build/'
     device_replacement: 'Yarvik $1'
     brand_replacement: 'Yarvik'
     model_replacement: '$1'
@@ -4330,7 +4379,7 @@
   # XiaoMi
   # @ref: http://www.xiaomi.com/event/buyphone
   #########
-  - regex: '; *((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note )?[^;/]*) (Build|MIUI)/'
+  - regex: '; *((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note |)[^;/]*) (Build|MIUI)/'
     device_replacement: 'XiaoMi $1'
     brand_replacement: 'XiaoMi'
     model_replacement: '$1'
@@ -4496,7 +4545,7 @@
     device_replacement: 'Kindle'
     brand_replacement: 'Amazon'
     model_replacement: 'Kindle'
-  - regex: '; ?(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))? Build\b'
+  - regex: '; ?(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|) Build\b'
     device_replacement: 'Kindle Fire'
     brand_replacement: 'Amazon'
     model_replacement: 'Kindle Fire$2'
@@ -4548,7 +4597,7 @@
   #########
   # Alcatel Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:ALCATEL)[^;]*; *([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:ALCATEL)[^;]*; *([^;,\)]+)'
     device_replacement: 'Alcatel $1'
     brand_replacement: 'Alcatel'
     model_replacement: '$1'
@@ -4556,8 +4605,8 @@
   #########
   # Asus Windows Phones
   #########
-  #~ - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?(?:ASUS|Asus)[^;]*; *([^;,\)]+)'
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?(?:ASUS|Asus)[^;]*; *([^;,\)]+)'
+  #~ - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)(?:ASUS|Asus)[^;]*; *([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)(?:ASUS|Asus)[^;]*; *([^;,\)]+)'
     device_replacement: 'Asus $1'
     brand_replacement: 'Asus'
     model_replacement: '$1'
@@ -4565,7 +4614,7 @@
   #########
   # Dell Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:DELL|Dell)[^;]*; *([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:DELL|Dell)[^;]*; *([^;,\)]+)'
     device_replacement: 'Dell $1'
     brand_replacement: 'Dell'
     model_replacement: '$1'
@@ -4573,7 +4622,7 @@
   #########
   # HTC Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?(?:HTC|Htc|HTC_blocked[^;]*)[^;]*; 
*(?:HTC)?([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)(?:HTC|Htc|HTC_blocked[^;]*)[^;]*; 
*(?:HTC|)([^;,\)]+)'
     device_replacement: 'HTC $1'
     brand_replacement: 'HTC'
     model_replacement: '$1'
@@ -4581,7 +4630,7 @@
   #########
   # Huawei Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:HUAWEI)[^;]*; *(?:HUAWEI )?([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:HUAWEI)[^;]*; *(?:HUAWEI |)([^;,\)]+)'
     device_replacement: 'Huawei $1'
     brand_replacement: 'Huawei'
     model_replacement: '$1'
@@ -4589,7 +4638,7 @@
   #########
   # LG Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:LG|Lg)[^;]*; *(?:LG[ \-])?([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:LG|Lg)[^;]*; *(?:LG[ \-]|)([^;,\)]+)'
     device_replacement: 'LG $1'
     brand_replacement: 'LG'
     model_replacement: '$1'
@@ -4597,15 +4646,15 @@
   #########
   # Noka Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:rv:11; )?(?:NOKIA|Nokia)[^;]*; *(?:NOKIA ?|Nokia ?|LUMIA 
?|[Ll]umia ?)*(\d{3,}[^;\)]*)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:rv:11; |)(?:NOKIA|Nokia)[^;]*; *(?:NOKIA ?|Nokia ?|LUMIA 
?|[Ll]umia ?|)(\d{3,10}[^;\)]*)'
     device_replacement: 'Lumia $1'
     brand_replacement: 'Nokia'
     model_replacement: 'Lumia $1'
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:NOKIA|Nokia)[^;]*; *(RM-\d{3,})'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:NOKIA|Nokia)[^;]*; *(RM-\d{3,})'
     device_replacement: 'Nokia $1'
     brand_replacement: 'Nokia'
     model_replacement: '$1'
-  - regex: '(?:Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)]|WPDesktop;) 
?(?:ARM; ?Touch; ?|Touch; ?)?(?:NOKIA|Nokia)[^;]*; *(?:NOKIA ?|Nokia ?|LUMIA 
?|[Ll]umia ?)*([^;\)]+)'
+  - regex: '(?:Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)]|WPDesktop;) 
?(?:ARM; ?Touch; ?|Touch; ?|)(?:NOKIA|Nokia)[^;]*; *(?:NOKIA ?|Nokia ?|LUMIA 
?|[Ll]umia ?|)([^;\)]+)'
     device_replacement: 'Nokia $1'
     brand_replacement: 'Nokia'
     model_replacement: '$1'
@@ -4613,7 +4662,7 @@
   #########
   # Microsoft Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?)?(?:Microsoft(?: Corporation)?)[^;]*; *([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|)(?:Microsoft(?: Corporation|))[^;]*; *([^;,\)]+)'
     device_replacement: 'Microsoft $1'
     brand_replacement: 'Microsoft'
     model_replacement: '$1'
@@ -4621,7 +4670,7 @@
   #########
   # Samsung Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?(?:SAMSUNG)[^;]*; *(?:SAMSUNG )?([^;,\.\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)(?:SAMSUNG)[^;]*; *(?:SAMSUNG |)([^;,\.\)]+)'
     device_replacement: 'Samsung $1'
     brand_replacement: 'Samsung'
     model_replacement: '$1'
@@ -4629,7 +4678,7 @@
   #########
   # Toshiba Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?(?:TOSHIBA|FujitsuToshibaMobileCommun)[^;]*; 
*([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)(?:TOSHIBA|FujitsuToshibaMobileCommun)[^;]*; 
*([^;,\)]+)'
     device_replacement: 'Toshiba $1'
     brand_replacement: 'Toshiba'
     model_replacement: '$1'
@@ -4637,7 +4686,7 @@
   #########
   # Generic Windows Phones
   #########
-  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?)?([^;]+); *([^;,\)]+)'
+  - regex: 'Windows Phone [^;]+; .*?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; 
?|Touch; ?|WpsLondonTest; ?|)([^;]+); *([^;,\)]+)'
     device_replacement: '$1 $2'
     brand_replacement: '$1'
     model_replacement: '$2'
@@ -4657,7 +4706,7 @@
   #########
   # Firefox OS
   #########
-  - regex: '\(Mobile; ALCATEL ?(One|ONE) ?(Touch|TOUCH) ?([^;/]+)(?:/[^;]+)?; 
rv:[^\)]+\) Gecko/[^\/]+ Firefox/'
+  - regex: '\(Mobile; ALCATEL ?(One|ONE) ?(Touch|TOUCH) ?([^;/]+)(?:/[^;]+|); 
rv:[^\)]+\) Gecko/[^\/]+ Firefox/'
     device_replacement: 'Alcatel $1 $2 $3'
     brand_replacement: 'Alcatel'
     model_replacement: 'One Touch $3'
@@ -4688,7 +4737,7 @@
     brand_replacement: '$1'
     model_replacement: '$2'
   # Nokia Symbian
-  - regex: '\(Symbian(?:/3)?; U; ([^;]+);'
+  - regex: '\(Symbian(?:/3|); U; ([^;]+);'
     device_replacement: 'Nokia $1'
     brand_replacement: 'Nokia'
     model_replacement: '$1'
@@ -4733,7 +4782,7 @@
     device_replacement: 'Palm Treo $1'
     brand_replacement: 'Palm'
     model_replacement: 'Treo $1'
-  - regex: 'webOS.*(P160U(?:NA)?)/(\d+).(\d+)'
+  - regex: 'webOS.*(P160U(?:NA|))/(\d+).(\d+)'
     device_replacement: 'HP Veer'
     brand_replacement: 'HP'
     model_replacement: 'Veer'
@@ -4860,7 +4909,7 @@
     device_replacement: 'Asus $1'
     brand_replacement: 'Asus'
     model_replacement: '$1'
-  - regex: '(?:asus.*?ASUS|Asus|ASUS|asus)[\- ;]*((?:Transformer (?:Pad|Prime) 
|Transformer |Padfone |Nexus[ _])?[A-Za-z0-9]+)'
+  - regex: '(?:asus.*?ASUS|Asus|ASUS|asus)[\- ;]*((?:Transformer (?:Pad|Prime) 
|Transformer |Padfone |Nexus[ _]|)[A-Za-z0-9]+)'
     device_replacement: 'Asus $1'
     brand_replacement: 'Asus'
     model_replacement: '$1'
@@ -4901,7 +4950,7 @@
   ##########
   # htc
   ##########
-  - regex: '\b(?:HTC/|HTC/[a-z0-9]+/)?HTC[ _\-;]? 
*(.*?)(?:-?Mozilla|fingerPrint|[;/\(\)]|$)'
+  - regex: '\b(?:HTC/|HTC/[a-z0-9]+/|)HTC[ _\-;]? 
*(.*?)(?:-?Mozilla|fingerPrint|[;/\(\)]|$)'
     device_replacement: 'HTC $1'
     brand_replacement: 'HTC'
     model_replacement: '$1'
@@ -4958,11 +5007,11 @@
     device_replacement: '$1'
     brand_replacement: '$2'
     model_replacement: '$3'
-  - regex: 
'(HbbTV)/1\.1\.1.*CE-HTML/1\.\d;(Vendor/)*(THOM[^;]*?)[;\s](?:.*SW-Version/.*)*(LF[^;]+);?'
+  - regex: 
'(HbbTV)/1\.1\.1.*CE-HTML/1\.\d;(Vendor/|)(THOM[^;]*?)[;\s].{0,30}(LF[^;]+);?'
     device_replacement: '$1'
     brand_replacement: 'Thomson'
     model_replacement: '$4'
-  - regex: '(HbbTV)(?:/1\.1\.1)?(?: ?\(;;;;;\))?; *CE-HTML(?:/1\.\d)?; *([^ 
]+) ([^;]+);'
+  - regex: '(HbbTV)(?:/1\.1\.1|) ?(?: \(;;;;;\)|); *CE-HTML(?:/1\.\d|); *([^ 
]+) ([^;]+);'
     device_replacement: '$1'
     brand_replacement: '$2'
     model_replacement: '$3'
@@ -4979,7 +5028,7 @@
   ##########
   # LGE NetCast TV
   ##########
-  - regex: 'LGE; (?:Media\/)?([^;]*);[^;]*;[^;]*;?\); "?LG 
NetCast(\.TV|\.Media)?-\d+'
+  - regex: 'LGE; (?:Media\/|)([^;]*);[^;]*;[^;]*;?\); "?LG 
NetCast(\.TV|\.Media|)-\d+'
     device_replacement: 'NetCast$2'
     brand_replacement: 'LG'
     model_replacement: '$1'
@@ -5008,7 +5057,7 @@
     brand_replacement: '$1'
     model_replacement: '$2'
   # other LG phones
-  - regex: '\b(?:LGE[ \-]LG\-(?:AX)?|LGE |LGE?-LG|LGE?[ \-]|LG[ 
/\-]|lg[\-])([A-Za-z0-9]+)\b'
+  - regex: '\b(?:LGE[ \-]LG\-(?:AX|)|LGE |LGE?-LG|LGE?[ \-]|LG[ 
/\-]|lg[\-])([A-Za-z0-9]+)\b'
     device_replacement: 'LG $1'
     brand_replacement: 'LG'
     model_replacement: '$1'
@@ -5153,7 +5202,7 @@
     device_replacement: '$2 $1'
     brand_replacement: '$2'
     model_replacement: '$1'
-  - regex: '(Sony)(?:BDP\/|\/)?([^ /;\)]+)[ /;\)]'
+  - regex: '(Sony)(?:BDP\/|\/|)([^ /;\)]+)[ /;\)]'
     device_replacement: '$1 $2'
     brand_replacement: '$1'
     model_replacement: '$2'
@@ -5189,21 +5238,21 @@
   - regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{0,2} *; 
*(.+?) Build[/ ]'
     brand_replacement: 'Generic_Android'
     model_replacement: '$1'
-  - regex: 'Android[\- ][\d]+(?:\.[\d]+){1,2}; 
*[A-Za-z]{2}[_\-][A-Za-z]{0,2}\-? *; *(.+?) Build[/ ]'
+  - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); 
*[A-Za-z]{2}[_\-][A-Za-z]{0,2}\-? *; *(.+?) Build[/ ]'
     brand_replacement: 'Generic_Android'
     model_replacement: '$1'
-  - regex: 'Android[\- ][\d]+(?:\.[\d]+){1,2}; *[A-Za-z]{0,2}\- *; *(.+?) 
Build[/ ]'
+  - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); *[A-Za-z]{0,2}\- *; 
*(.+?) Build[/ ]'
     brand_replacement: 'Generic_Android'
     model_replacement: '$1'
   # No build info at all - "Build" follows locale immediately
-  - regex: 'Android[\- ][\d]+(?:\.[\d]+){1,2}; 
*[a-z]{0,2}[_\-]?[A-Za-z]{0,2};? Build[/ ]'
+  - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); 
*[a-z]{0,2}[_\-]?[A-Za-z]{0,2};? Build[/ ]'
     device_replacement: 'Generic Smartphone'
     brand_replacement: 'Generic'
     model_replacement: 'Smartphone'
-  - regex: 'Android[\- ][\d]+(?:\.[\d]+){1,2}; *\-?[A-Za-z]{2}; *(.+?) Build[/ 
]'
+  - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); *\-?[A-Za-z]{2}; *(.+?) 
Build[/ ]'
     brand_replacement: 'Generic_Android'
     model_replacement: '$1'
-  - regex: 'Android[\- ][\d]+(?:\.[\d]+){1,2}(?:;.*)?; *(.+?) Build[/ ]'
+  - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|)(?:;.*|); *(.+?) Build[/ ]'
     brand_replacement: 'Generic_Android'
     model_replacement: '$1'
 
diff -Nru uap-core-20181019/test_resources/pgts_browser_list.yaml 
uap-core-20190213/test_resources/pgts_browser_list.yaml
--- uap-core-20181019/test_resources/pgts_browser_list.yaml     2018-10-19 
17:08:22.000000000 +0100
+++ uap-core-20190213/test_resources/pgts_browser_list.yaml     2019-02-13 
17:27:26.000000000 +0000
@@ -39415,9 +39415,9 @@
     patch:
 
   - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; 
3COM U.S. Robotics)'
-    family: 'Robotics'
-    major:
-    minor:
+    family: 'IE'
+    major: '6'
+    minor: '0'
     patch:
 
   - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; ABN 
AMRO)'
@@ -63409,7 +63409,7 @@
     patch:
 
   - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows XP 
Professional Bot v.5.)'
-    family: 'XP Professional Bot'
+    family: 'Windows XP Professional Bot'
     major:
     minor:
     patch:
diff -Nru uap-core-20181019/tests/mocha.opts uap-core-20190213/tests/mocha.opts
--- uap-core-20181019/tests/mocha.opts  1970-01-01 01:00:00.000000000 +0100
+++ uap-core-20190213/tests/mocha.opts  2019-02-13 17:27:26.000000000 +0000
@@ -0,0 +1,3 @@
+--ui tdd
+--reporter min
+--check-leaks
diff -Nru uap-core-20181019/tests/regexes.js uap-core-20190213/tests/regexes.js
--- uap-core-20181019/tests/regexes.js  1970-01-01 01:00:00.000000000 +0100
+++ uap-core-20190213/tests/regexes.js  2019-02-13 17:27:26.000000000 +0000
@@ -0,0 +1,36 @@
+'use strict'
+
+var assert = require('assert')
+var path = require('path')
+var fs = require('fs')
+var yaml = require('yamlparser')
+var regexes = readYAML('../regexes.yaml')
+var safe = require('safe-regex')
+var refImpl = require('uap-ref-impl')
+
+function readYAML (fileName) {
+  var file = path.join(__dirname, fileName)
+  var data = fs.readFileSync(file, 'utf8')
+  return yaml.eval(data)
+}
+
+suite('regexes', function () {
+  Object.keys(regexes).forEach(function (parser) {
+    suite(parser, function () {
+      regexes[parser].forEach(function(item) {
+        test(item.regex, function () {
+          assert.ok(safe(item.regex))
+        })
+      })
+    })
+  })
+
+  test('should not backtrack', function () {
+    var parse = refImpl(regexes).parse
+    var ua = Array(3200).fill('a').join('')
+    var start = Date.now()
+    parse(ua)
+    var diff = Date.now() - start
+    assert.ok(diff < 500, diff)
+  })
+})
diff -Nru uap-core-20181019/tests/test_device.yaml 
uap-core-20190213/tests/test_device.yaml
--- uap-core-20181019/tests/test_device.yaml    2018-10-19 17:08:22.000000000 
+0100
+++ uap-core-20190213/tests/test_device.yaml    2019-02-13 17:27:26.000000000 
+0000
@@ -650,6 +650,26 @@
     brand: 'Spider'
     model: 'Desktop'
 
+  - user_agent_string: 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; 
rv:11.0) like Gecko PTST/1.0'
+    family: 'Spider'
+    brand: 'Spider'
+    model:
+
+  - user_agent_string: 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/64.0.3282.0 Safari/537.36 PTST/1.0'
+    family: 'Spider'
+    brand: 'Spider'
+    model:
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4) 
Build/MPJ24.139-64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 
Mobile Safari/537.36 PTST/180521.140508'
+    family: 'Spider'
+    brand: 'Spider'
+    model:
+
+  - user_agent_string: 'Mozilla/5.0 (X11; Datanyze; Linux x86_64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
+    family: 'Spider'
+    brand: 'Spider'
+    model:
+
   - user_agent_string: 'Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 
(KHTML, like Gecko) PingdomTMS/0.8.5 Safari/534.34'
     family: 'Spider'
     brand: 'Spider'
diff -Nru uap-core-20181019/tests/test_os.yaml 
uap-core-20190213/tests/test_os.yaml
--- uap-core-20181019/tests/test_os.yaml        2018-10-19 17:08:22.000000000 
+0100
+++ uap-core-20190213/tests/test_os.yaml        2019-02-13 17:27:26.000000000 
+0000
@@ -427,6 +427,13 @@
     patch:
     patch_minor:
 
+  - user_agent_string: 'Mozilla/5.0 (X11; Datanyze; Linux x86_64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
+    family: 'Linux'
+    major:
+    minor:
+    patch:
+    patch_minor:
+
   - user_agent_string: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 
(KHTML, like Gecko; Google Web Preview) Chrome/27.0 .1453 Safari/537.36.'
     family: 'Linux'
     major:
@@ -736,15 +743,15 @@
     patch_minor:
 
   - user_agent_string: 'ICE Browser/5.05 (Java 1.4.0; Windows 2000 5.0 x86)'
-    family: 'Windows 2000'
-    major:
+    family: 'Windows'
+    major: '2000'
     minor:
     patch:
     patch_minor:
 
   - user_agent_string: 'NCSA_Mosaic/2.0 (Windows 3.1)'
-    family: 'Windows 3.1'
-    major:
+    family: 'Windows'
+    major: '3.1'
     minor:
     patch:
     patch_minor:
@@ -2419,6 +2426,13 @@
     patch: '4'
     patch_minor:
 
+  - user_agent_string: 'Zendesk for iPhone 1.2.1 (4395)'
+    family: 'iOS'
+    major:
+    minor:
+    patch:
+    patch_minor:
+
   - user_agent_string: 
'Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_11_6)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/52.0.2743.116+Safari/537.36'
     family: 'Mac OS X'
     major: '10'
@@ -2580,21 +2594,21 @@
     minor: '2'
     patch: '5'
     patch_minor:
- 
+
   - user_agent_string: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_6 like Mac OS 
X) AppleWebKit/604.5.6 (KHTML, like Gecko) Mobile/15D100 Flipboard/4.2.2'
     family: 'iOS'
     major: '11'
     minor: '2'
     patch: '6'
     patch_minor:
-    
+
   - user_agent_string: 'Mozilla/5.0 (Linux; Android 7.0; SM-G610F 
Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/63.0.3239.111 Mobile Safari/537.36 Flipboard/4.1.9/4323,4.1.9.4323'
     family: 'Android'
     major: '7'
     minor: '0'
     patch:
     patch_minor:
-    
+
   - user_agent_string: 'Mozilla/5.0 (Linux; Android 7.0; SM-G930F 
Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/64.0.3282.137 Mobile Safari/537.36 Onefootball/Android/9.10.6'
     family: 'Android'
     major: '7'
@@ -2608,7 +2622,7 @@
     minor: '0'
     patch:
     patch_minor:
-    
+
   - user_agent_string: 'Wget/1.18 (linux-gnu)'
     family: 'Linux'
     major:
@@ -2635,28 +2649,28 @@
     major: '8'
     minor: '0'
     patch: '0'
-    patch_minor: 
+    patch_minor:
 
   - user_agent_string: 'SalesforceMobileSDK/5.3.0 android mobile/7.0 
(SM-G955U) Salesforce1/15.2 Native uid_4ec4068eddf27447 ftr_ Cordova/6.2.3'
     family: 'Android'
     major: '7'
     minor: '0'
-    patch: 
-    patch_minor: 
-    
+    patch:
+    patch_minor:
+
   - user_agent_string: 'SalesforceMobileSDK/5.3.0 android mobile/9 (SM-G955U) 
Salesforce1/15.2 Native uid_4ec4068eddf27447 ftr_ Cordova/6.2.3'
     family: 'Android'
     major: '9'
     minor:
-    patch: 
-    patch_minor: 
+    patch:
+    patch_minor:
 
   - user_agent_string: 'Mozilla/5.0 (Linux; Android 9; Pixel 
Build/PPP3.180510.008) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/67.0.3396.81 Mobile Safari/537.36'
     family: 'Android'
     major: '9'
     minor:
-    patch: 
-    patch_minor: 
+    patch:
+    patch_minor:
 
   - user_agent_string: 'Mozilla/5.0 (X11; Windows aarch64 10718.88.2) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.118 Safari/537.36 
CitrixChromeApp'
     family: 'Chrome OS'
@@ -2679,3 +2693,86 @@
     patch:
     patch_minor:
 
+  - user_agent_string: 'ViaFree-DK/3.8.3 (com.MTGx.ViaFree.dk; build:7383; iOS 
12.1.0) Alamofire/4.7.0'
+    family: 'iOS'
+    major: '12'
+    minor: '1'
+    patch: '0'
+    patch_minor:
+
+  - user_agent_string: 'Viafree-tvOS-DK/3.7.1 (com.MTGx.ViaFree.dk; 
build:7341; tvOS 12.1.0) Alamofire/4.7.0'
+    family: 'tvOS'
+    major: '12'
+    minor: '1'
+    patch: '0'
+    patch_minor:
+
+  - user_agent_string: 'iTunes/12.7.1 (Windows; Microsoft Windows 7 Ultimate 
Edition Service Pack 1 (Build 7601)) AppleWebKit/7604.3005.2001.1'
+    family: 'Windows'
+    major: '7'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'iTunes/12.1.3 (Windows; Microsoft Windows XP 
Professional Service Pack 3 (Build 2600)) AppleWebKit/7600.1017.9000.3'
+    family: 'Windows'
+    major: 'XP'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'iTunes/12.1.3 (Windows; Microsoft Windows Vista 
Business Edition Service Pack 2 (Build 6002)) AppleWebKit/7600.1017.9000.3  '
+    family: 'Windows'
+    major: 'Vista'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 
3.3.8-3.3) [Netgem; 7.7.01-51; i-Player; netbox; sezmi_totalgem]'
+    family: 'Windows'
+    major: '98'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/2.0 (compatible; MSIE 3.0; Windows 3.1)'
+    family: 'Windows'
+    major: '3.1'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/5.0 (Windows NT 4.0; rv:52.0) Gecko/20100101 
Firefox/52.0'
+    family: 'Windows'
+    major: 'NT'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 
5.11 [de]'
+    family: 'Windows'
+    major: 'ME'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Microsoft Internet Explorer/1.0 (Windows 95)'
+    family: 'Windows'
+    major: '95'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows 
CE,BrailleNote; IEMobile 7.11)'
+    family: 'Windows'
+    major: 'CE'
+    minor:
+    patch:
+    patch_minor:
+
+  - user_agent_string: 'Mozilla/5.0 (Windows 2000; U) Opera 7.0 [en]'
+    family: 'Windows'
+    major: '2000'
+    minor:
+    patch:
+    patch_minor:
diff -Nru uap-core-20181019/tests/test_ua.yaml 
uap-core-20190213/tests/test_ua.yaml
--- uap-core-20181019/tests/test_ua.yaml        2018-10-19 17:08:22.000000000 
+0100
+++ uap-core-20190213/tests/test_ua.yaml        2019-02-13 17:27:26.000000000 
+0000
@@ -1797,6 +1797,30 @@
     minor: '0'
     patch: '1'
 
+  - user_agent_string: 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; 
rv:11.0) like Gecko PTST/1.0'
+    family: 'WebPageTest.org bot'
+    major: '1'
+    minor: '0'
+    patch: 
+
+  - user_agent_string: 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/64.0.3282.0 Safari/537.36 PTST/1.0'
+    family: 'WebPageTest.org bot'
+    major: '1'
+    minor: '0'
+    patch:
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4) 
Build/MPJ24.139-64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 
Mobile Safari/537.36 PTST/180521.140508'
+    family: 'WebPageTest.org bot'
+    major: '180521'
+    minor: '140508'
+    patch:
+
+  - user_agent_string: 'Mozilla/5.0 (X11; Datanyze; Linux x86_64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
+    family: 'Datanyze'
+    major:
+    minor:
+    patch:
+
   - user_agent_string: 'CazoodleBot/CazoodleBot-0.1 (CazoodleBot Crawler; 
http://www.cazoodle.com/cazoodlebot; cazoodle...@cazoodle.com)'
     family: 'CazoodleBot'
     major: '0'
@@ -4741,7 +4765,7 @@
     patch:
 
   - user_agent_string: 'FAST-mSEARCH Crawler 0.1 (ber...@fast.no)'
-    family: 'mSEARCH Crawler'
+    family: 'FAST-mSEARCH Crawler'
     major: '0'
     minor: '1'
     patch:
@@ -6908,6 +6932,18 @@
     minor: '45'
     patch: '2454'
 
+  - user_agent_string: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) 
AppleWebKit/604.1.38 (KHTML, like Gecko) Mobile/15A372 Safari Line/7.12.0'
+    family: 'LINE'
+    major: '7'
+    minor: '12'
+    patch: '0'
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 5.1; FTJ152B Build/LMY47D; 
wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 
Mobile Safari/537.36 Line/6.4.1'
+    family: 'LINE'
+    major: '6'
+    minor: '4'
+    patch: '1'
+
   - user_agent_string: 'Mozilla/5.0 (Linux; Android 4.1.2; GT-S7710 
Build/JZO54K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 
Mobile'
     family: 'Chrome Mobile'
     major: '18'
@@ -6929,6 +6965,18 @@
     patch: '0'
     patch_minor: '0'
 
+  - user_agent_string: 'Mozilla/5.0 (Linux; U; Android 6.0.1; ru-ru; Redmi 4 
Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.3.6-g'
+    family: 'MiuiBrowser'
+    major: '10'
+    minor: '3'
+    patch: '6'
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; U; Android 7.1.2; ru-ru; Redmi 4A 
Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/Mint Browser/1.3.3'
+    family: 'Mint Browser'
+    major: '1'
+    minor: '3'
+    patch: '3'
+
   - user_agent_string: 'Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 
(KHTML, like Gecko) Large Screen WebAppManager Safari/537.41'
     family: 'Safari'
     major:
@@ -7724,3 +7772,45 @@
     minor: '0'
     patch: '169645775'
 
+  - user_agent_string: 'ViaFree-DK/3.8.3 (com.MTGx.ViaFree.dk; build:7383; iOS 
12.1.0) Alamofire/4.7.0'
+    family: 'ViaFree'
+    major: '3'
+    minor: '8'
+    patch: '3'
+
+  - user_agent_string: 'Viafree-tvOS-DK/3.7.1 (com.MTGx.ViaFree.dk; 
build:7341; tvOS 12.1.0) Alamofire/4.7.0'
+    family: 'ViaFree'
+    major: '3'
+    minor: '7'
+    patch: '1'
+
+  - user_agent_string: 'OC/15.0.5071.1000 (Skype for Business)'
+    family: 'Skype'
+    major: '15'
+    minor: '0'
+    patch: '5071'
+    patch_minor: '1000'
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 8.1.0; TA-1024 
Build/OPR1.170623.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/71.0.3578.99 Mobile Safari/537.36 GSA/8.65.5.21.arm64'
+    family: 'Google'
+    major: '8'
+    minor: '65'
+    patch: '5'
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F 
Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/71.0.3578.99 Mobile Safari/537.36 GSA/8.65.5.21.arm64'
+    family: 'Google'
+    major: '8'
+    minor: '65'
+    patch: '5'
+
+  - user_agent_string: 'Mozilla/5.0 (Linux; Android 9; Pixel 3 
Build/PQ1A.181205.006; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 
Chrome/71.0.3578.99 Mobile Safari/537.36 GSA/8.65.5.21.arm64'
+    family: 'Google'
+    major: '8'
+    minor: '65'
+    patch: '5'
+
+  - user_agent_string: 'Microsoft Office Word 2014'
+    family: 'Word'
+    major:
+    minor:
+    patch:
diff -Nru uap-core-20181019/.travis.yml uap-core-20190213/.travis.yml
--- uap-core-20181019/.travis.yml       2018-10-19 17:08:22.000000000 +0100
+++ uap-core-20190213/.travis.yml       2019-02-13 17:27:26.000000000 +0000
@@ -1,14 +1,13 @@
 sudo: false
 language: node_js
 node_js:
-  - 4
-  - 6
   - 8
+  - 10
   - node
 
 script:
   - "npm test"
-  
+
 notifications:
   irc: "chat.freenode.net#ua-parser"
 

--- End Message ---
--- Begin Message ---
Edward Betts:
> Package: release.debian.org
> Severity: normal
> User: release.debian....@packages.debian.org
> Usertags: unblock
> 
> Dear Release Team,
> 
> Please consider unblocking package uap-core
> 
> This is a new release that fixes a A Regular Expression Denial of
> Service (ReDoS) bug: CVE-2018-20164.
> 
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=922717
> 
> I've attached the output from debdiff between the versions in testing
> and unstable.
> 
> Thanks,
> 
> Edward Betts
> 
> unblock uap-core/20190213-2
> 

Unblocked, thanks.
~Niels

--- End Message ---

Reply via email to