diff --git a/tools/test_user_agent_parsing.py b/tools/test_user_agent_parsing.py new file mode 100755 index 0000000000..01bddb6c68 --- /dev/null +++ b/tools/test_user_agent_parsing.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +import re +from collections import defaultdict +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + +from zerver.lib.user_agent import parse_user_agent + +user_agents_parsed = defaultdict(int) +user_agents_path = os.path.join(os.path.dirname(__file__), "user_agents_unique") +parse_errors = 0 +for line in file(user_agents_path).readlines(): + line = line.strip() + match = re.match('^(?P[0-9]+) "(?P.*)"$', line) + if match is None: + print line + continue + groupdict = match.groupdict() + count = groupdict["count"] + user_agent = groupdict["user_agent"] + ret = parse_user_agent(user_agent) + if ret is None: + print "parse error", line + parse_errors += 1 + continue + user_agents_parsed[ret["name"]] += int(count) + +for key in user_agents_parsed: + print " ", key, user_agents_parsed[key] + +print "%s parse errors!" % (parse_errors,) diff --git a/tools/user_agents_unique b/tools/user_agents_unique new file mode 100644 index 0000000000..7673c174e2 --- /dev/null +++ b/tools/user_agents_unique @@ -0,0 +1,1904 @@ + 7 "-" + 2 "1PasswordThumbs/1 CFNetwork/454.12.4 Darwin/10.8.0 (i386) (MacBookPro5%2C5)" + 4 "1PasswordThumbs/1 CFNetwork/454.12.4 Darwin/10.8.0 (i386) (Macmini2%2C1)" + 4 "1PasswordThumbs/1 CFNetwork/520.5.1 Darwin/11.4.2 (x86_64) (MacBookAir3%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/520.5.1 Darwin/11.4.2 (x86_64) (MacBookAir5%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/520.5.1 Darwin/11.4.2 (x86_64) (MacBookPro6%2C2)" + 4 "1PasswordThumbs/1 CFNetwork/596.2.3 Darwin/12.2.1 (x86_64) (MacBookPro10%2C2)" + 4 "1PasswordThumbs/1 CFNetwork/596.4.3 Darwin/12.4.0 (x86_64) (MacBookAir4%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/596.4.3 Darwin/12.4.0 (x86_64) (MacBookAir5%2C1)" + 2 "1PasswordThumbs/1 CFNetwork/596.4.3 Darwin/12.4.0 (x86_64) (MacBookPro10%2C1)" + 4 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (iMac12%2C2)" + 4 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir4%2C1)" + 8 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir4%2C2)" + 8 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir5%2C2)" + 6 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir6%2C2)" + 16 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookPro10%2C1)" + 4 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookPro10%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookPro6%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookPro9%2C1)" + 2 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookPro9%2C2)" + 2 "1PasswordThumbs/1 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacPro5%2C1)" + 2 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (iMac12%2C1)" + 4 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookAir4%2C2)" + 4 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookAir6%2C2)" + 12 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookPro10%2C1)" + 4 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookPro9%2C1)" + 2 "1PasswordThumbs/1 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookPro9%2C2)" + 1 "-" + 3 "ZulipMobile/0.6.0" + 3 "ZulipMobile/0.7.1" + 4 "AdnormCrawler www.adnorm.com/crawler" + 10 "Airmail 1.0.5 rv:192 (Macintosh; Mac OS X 10.8.4; en_US)" + 30 "Airmail 1.0.5 rv:192 (Macintosh; Mac OS X 10.8.5; en_US)" + 8 "Airmail 1.0.5 rv:192 (Macintosh; Mac OS X 10.9.0; en_US)" + 8 "Airmail 1.1 rv:205 (Macintosh; Mac OS X 10.7.5; en_US)" + 20 "Airmail 1.1 rv:205 (Macintosh; Mac OS X 10.8.5; en_AU)" + 10 "Airmail 1.2 rv:209 (Macintosh; Mac OS X 10.8.5; en_AU)" + 8 "Airmail 1.2 rv:209 (Macintosh; Mac OS X 10.9.0; en_AU)" + 10 "Airmail 1.2 rv:210 (Macintosh; Mac OS X 10.8.5; en_AU)" + 10 "Airmail 1.2 rv:211 (Macintosh; Mac OS X 10.8.5; en_US)" + 8 "Airmail 1.2 rv:211 (Macintosh; Mac OS X 10.9.0; en_GB)" + 8 "Airmail 1.2 rv:211 (Macintosh; Mac OS X 10.9.0; en_HR)" + 8 "Airmail 1.2 rv:211 (Macintosh; Mac OS X 10.9.0; en_IS)" + 64 "Airmail 1.2 rv:211 (Macintosh; Mac OS X 10.9.0; en_US)" + 8 "Airmail 1.2 rv:213 (Macintosh; Mac OS X 10.9.0; en_AU)" + 8 "Airmail 1.3 rv:215 (Macintosh; Mac OS X 10.9.0; en_US)" + 19 "Apache-HttpClient/4.3 (java 1.5)" + 16 "AppEngine-Google; (+http://code.google.com/appengine; appid: s~getfavicon27)" + 4 "AppFresh/1.0.4 (908) (Mac OS X)" + 1 "AppFresh/(null) ((null)) (Mac OS X)" + 4 "AppleCoreMedia/1.0.0.10A403 (iPad; U; CPU OS 6_0 like Mac OS X; en_us)" + 14 "AppleCoreMedia/1.0.0.10A523 (iPad; U; CPU OS 6_0_1 like Mac OS X; en_us)" + 8 "AppleCoreMedia/1.0.0.10A551 (iPhone; U; CPU OS 6_0_2 like Mac OS X; en_us)" + 2 "AppleCoreMedia/1.0.0.10B146 (iPad; U; CPU OS 6_1_2 like Mac OS X; en_us)" + 36 "AppleCoreMedia/1.0.0.10B329 (iPad; U; CPU OS 6_1_3 like Mac OS X; en_us)" + 2 "AppleCoreMedia/1.0.0.10B329 (iPhone; U; CPU OS 6_1_3 like Mac OS X; en_gb)" + 16 "AppleCoreMedia/1.0.0.10B329 (iPhone; U; CPU OS 6_1_3 like Mac OS X; en_us)" + 2 "AppleCoreMedia/1.0.0.10B329 (iPod; U; CPU OS 6_1_3 like Mac OS X; en_us)" + 40 "AppleCoreMedia/1.0.0.10B350 (iPhone; U; CPU OS 6_1_4 like Mac OS X; en_us)" + 10 "AppleCoreMedia/1.0.0.11A4449d (iPhone; U; CPU OS 7_0 like Mac OS X; en_gb)" + 2 "AppleCoreMedia/1.0.0.11A4449d (iPhone; U; CPU OS 7_0 like Mac OS X; en_us)" + 150 "AppleCoreMedia/1.0.0.11A465 (iPad; U; CPU OS 7_0 like Mac OS X; en_us)" + 4 "AppleCoreMedia/1.0.0.11A465 (iPhone; U; CPU OS 7_0 like Mac OS X; de_de)" + 30 "AppleCoreMedia/1.0.0.11A465 (iPhone; U; CPU OS 7_0 like Mac OS X; en_us)" + 4 "AppleCoreMedia/1.0.0.11A465 (iPod touch; U; CPU OS 7_0 like Mac OS X; en_us)" + 10 "AppleCoreMedia/1.0.0.11A466 (iPhone; U; CPU OS 7_0 like Mac OS X; en_us)" + 4 "AppleCoreMedia/1.0.0.11A470a (iPhone; U; CPU OS 7_0_1 like Mac OS X; en_us)" + 56 "AppleCoreMedia/1.0.0.11A501 (iPad; U; CPU OS 7_0_2 like Mac OS X; en_us)" + 8 "AppleCoreMedia/1.0.0.11A501 (iPhone; U; CPU OS 7_0_2 like Mac OS X; de_de)" + 6 "AppleCoreMedia/1.0.0.11A501 (iPhone; U; CPU OS 7_0_2 like Mac OS X; en_gb)" + 82 "AppleCoreMedia/1.0.0.11A501 (iPhone; U; CPU OS 7_0_2 like Mac OS X; en_us)" + 8 "AppleCoreMedia/1.0.0.11A501 (iPod touch; U; CPU OS 7_0_2 like Mac OS X; en_us)" + 16 "AppleCoreMedia/1.0.0.11B511 (iPad; U; CPU OS 7_0_3 like Mac OS X; de_de)" + 20 "AppleCoreMedia/1.0.0.11B511 (iPad; U; CPU OS 7_0_3 like Mac OS X; en_us)" + 78 "AppleCoreMedia/1.0.0.11B511 (iPhone; U; CPU OS 7_0_3 like Mac OS X; en_us)" + 4 "AppleCoreMedia/1.0.0.11B511 (iPod touch; U; CPU OS 7_0_3 like Mac OS X; en_us)" + 28 "AppleCoreMedia/1.0.0.11B554a (iPad; U; CPU OS 7_0_4 like Mac OS X; en_us)" + 18 "AppleCoreMedia/1.0.0.11B554a (iPhone; U; CPU OS 7_0_4 like Mac OS X; en_us)" + 6 "AppleCoreMedia/1.0.0.11B554a (iPod touch; U; CPU OS 7_0_4 like Mac OS X; en_us)" + 26 "AppleCoreMedia/1.0.0.11G63b (Macintosh; U; Intel Mac OS X 10_7_5; en_us)" + 4 "AppleCoreMedia/1.0.0.11G63b (Macintosh; U; Intel Mac OS X 10_7_5; is_is)" + 153 "AppleCoreMedia/1.0.0.11G63 (Macintosh; U; Intel Mac OS X 10_7_5; en_us)" + 9 "AppleCoreMedia/1.0.0.13A603 (Macintosh; U; Intel Mac OS X 10_9; en_us)" + 12 "AppleCoreMedia/1.0.0.8L1 (iPad; U; CPU OS 4_3_5 like Mac OS X; en_us)" + 2 "AppleCoreMedia/1.0.0.9B206 (iPad; U; CPU OS 5_1_1 like Mac OS X; de_de)" + 14 "AppleCoreMedia/1.0.0.9B206 (iPad; U; CPU OS 5_1_1 like Mac OS X; en_us)" + 10 "AppleCoreMedia/1.0.0.9B206 (iPhone; U; CPU OS 5_1_1 like Mac OS X)" + 66 "AppleCoreMedia/1.0.0.9B206 (iPhone; U; CPU OS 5_1_1 like Mac OS X; en_us)" + 65 "Apple Mac OS X v10.6.8 CoreMedia v1.0.0.10K549" + 10622 "Atlassian HttpClient 0.16.10 / JIRA-6.2-OD-01 (6204) / Default" + 583 "Atlassian HttpClient 0.16.6 / JIRA-6.1-OD-06-1 (6139) / Default" + 101 "Atlassian HttpClient 0.16.6 / JIRA-6.1-OD-06 (6139) / Default" + 584 "Atlassian HttpClient 0.16.7 / JIRA-6.1-OD-08 (6143) / Default" + 8070 "Atlassian HttpClient 0.16.7 / JIRA-6.1-OD-09-WN (6144) / Default" + 3334 "Atlassian HttpClient 0.17.1 / JIRA-6.2-OD-01 (6204) / Default" + 11096 "Atlassian HttpClient 0.17.1 / JIRA-6.2-OD-03 (6206) / Default" + 16799 "Atlassian-Webhooks-Plugin" + 78 "beanstalkapp.com" + 1549 "Bitbucket.org" + 6338 "Bitbucket.org" + 11 "BlackBerry9000/4.6.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 ips-agent" + 4 "blogtop.us crawler - http://blogtop.us/" + 20 "bot-pge.chlooe.com/1.0.0 (+http://www.chlooe.com/)" + 8 "bot.wsowner.com/1.0.0 (+http://wsowner.com/)" + 1 "BufferBot" + 890 "Camo Asset Proxy 1.1.1" + 1 " infernal_edition:goto-hell) Firefox/666" + 1 "Mozilla/6.0 (compatible; MSIE 7.0a1; Windows NT 5.2; SV1)" + 2 "NextGenSearchBot 1 (for information visit http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx)" + 4 "NING/1.0" + 6 "NIS Nutch Spider/Nutch-1.7" + 20 "nutch-1.4/Nutch-1.4" + 48 "okwc/3.1.16.0" + 2 "Opera/9.00 (Windows NT 5.0; U; en)" + 2 "Opera/9.00 (Windows NT 5.1; U; en)" + 1 "Opera/9.13 (Windows NT 5.1; U; en) Presto/2.8.64 Version/10.63" + 1 "Opera/9.63 (Windows NT 5.1; U; en) Presto/2.4.51 Version/10.79" + 63 "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.10" + 14 "Opera/9.80 (J2ME/MIDP; Opera Mini/4.5.33893/32.1382; U; en) Presto/2.8.119 Version/11.10" + 10 "Opera/9.80 (Series 60; Opera Mini/7.1.32444/32.952; U; en) Presto/2.8.119 Version/11.10" + 18 "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.8.131 Version/11.10" + 1 "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16" + 5134 "Opera/9.80 (X11; Linux x86_64; Edition Linux Mint) Presto/2.12.388 Version/12.16" + 28 "Opera/9.80 (X11; Linux x86_64; Edition Next) Presto/2.12.388 Version/12.16" + 2379 "Opera/9.80 (X11; Linux x86_64) Presto/2.12.388 Version/12.16" + 28 "Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.9.168 Version/11.50" + 3 "Outlook-Express/7.0 (MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; .NET CLR 1.1.4322; TmstmpExt)" + 6 "PagesInventory (robot http://www.pagesinvenotry.com)" + 6 "PagesInventory (robot +http://www.pagesinventory.com)" + 95 "panscient.com" + 3 "pip/1.4.1 CPython/2.7.5+ Linux/3.11.0-12-generic" + 1 "pip/1.4 CPython/2.7.3 Linux/3.5.0-43-generic" +20707581 "python-requests/0.12.1" + 7381 "python-requests/0.13.1" + 35 "python-requests/0.13.8 CPython/2.7.2 Darwin/12.4.0" + 1 "python-requests/0.14.1 CPython/2.6.5 Linux/2.6.32-28-server" +2378614 "python-requests/0.14.1 CPython/2.6.6 Linux/2.6.32-5-xen-amd64" + 48263 "python-requests/0.14.1 CPython/2.7.3 Linux/3.2.0-31-generic" + 1 "python-requests/0.14.1 CPython/2.7.3 Linux/3.2.0-4-amd64" + 1 "python-requests/0.14.1 CPython/2.7.3 Linux/3.5.0-39-generic" + 218 "python-requests/0.14.1 CPython/2.7.4 Linux/3.8.0-30-generic" + 24 "python-requests/0.14.1 CPython/2.7.4 Linux/3.8.0-32-generic" + 42 "python-requests/0.14.1 CPython/2.7.4 Linux/3.8.0-33-generic" + 1874 "python-requests/0.14.1 CPython/2.7.4 Linux/3.8.0-34-generic" + 3679 "python-requests/0.14.2 CPython/2.6.6 Linux/2.6.32-358.6.2.el6.x86_64" + 3 "python-requests/1.1.0 CPython/2.7.2 Darwin/12.4.0" + 28 "python-requests/1.1.0 CPython/2.7.2 Darwin/12.5.0" + 3 "python-requests/1.1.0 CPython/2.7.2 FreeBSD/9.1-RELEASE-p7" + 1 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-52-generic" + 13 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-53-generic" + 50 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-54-generic" + 110 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-55-generic" + 42 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-56-generic" + 2 "python-requests/1.1.0 CPython/2.7.3 Linux/3.2.0-57-generic" + 142431 "python-requests/1.1.0 CPython/2.7.3 Linux/3.9.10-100.fc17.x86_64" + 22 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-27-generic" + 131 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-29-generic" + 18 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-30-generic" + 6 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-31-generic" + 10 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-32-generic" + 13 "python-requests/1.1.0 CPython/2.7.4 Linux/3.8.0-33-generic" + 2 "python-requests/1.1.0 CPython/2.7.5 Linux/3.11.6-200.fc19.x86_64" + 172 "python-requests/1.2.0 CPython/2.7.3 Darwin/12.5.0" + 60 "python-requests/1.2.0 CPython/2.7.4 Linux/3.8.11-ec2" + 7473 "python-requests/1.2.3 CPython/2.6.6 Linux/2.6.32-5-amd64" + 2 "python-requests/1.2.3 CPython/2.6.8 Linux/3.4.43-43.43.amzn1.x86_64" + 97230 "python-requests/1.2.3 CPython/2.6.8 Linux/3.4.57-48.42.amzn1.x86_64" + 1057 "python-requests/1.2.3 CPython/2.7.1 Darwin/11.4.2" + 32 "python-requests/1.2.3 CPython/2.7.2 Darwin/12.5.0" + 142 "python-requests/1.2.3 CPython/2.7.3 Darwin/12.2.1" + 5241 "python-requests/1.2.3 CPython/2.7.3 Linux/3.2.0-24-virtual" + 425 "python-requests/1.2.3 CPython/2.7.3 Linux/3.2.0-40-virtual" + 111728 "python-requests/1.2.3 CPython/2.7.3 Linux/3.2.0-45-generic" + 2148 "python-requests/1.2.3 CPython/2.7.3 Linux/3.2.0-4-amd64" + 36 "python-requests/1.2.3 CPython/2.7.3 Linux/3.5.0-23-generic" + 87 "python-requests/1.2.3 CPython/2.7.5 Darwin/12.4.0" + 871 "python-requests/1.2.3 CPython/2.7.5 Darwin/13.0.0" + 216 "python-requests/1.2.3 CPython/2.7.5+ Linux/3.11.0-13-generic" + 899 "python-requests/1.2.3 CPython/2.7.5 Windows/7" + 669 "python-requests/2.0.0 CPython/2.6.2 Linux/2.6.32.26-175.fc12.i686.PAE" + 10 "python-requests/2.0.0 CPython/2.6.6 Linux/2.6.32-5-amd64" + 43608 "python-requests/2.0.0 CPython/2.7.2 Darwin/12.3.0" + 28 "python-requests/2.0.0 CPython/2.7.2 Darwin/12.4.0" + 49 "python-requests/2.0.0 CPython/2.7.3 Darwin/12.2.1" + 113 "python-requests/2.0.0 CPython/2.7.3 Darwin/12.5.0" + 80 "python-requests/2.0.0 CPython/2.7.3 Darwin/13.0.0" + 26 "python-requests/2.0.0 CPython/2.7.3 Linux/2.6.32-5-xen-amd64" + 2 "python-requests/2.0.0 CPython/2.7.3 Linux/3.10.12-100.fc18.i686.PAE" + 32 "python-requests/2.0.0 CPython/2.7.3 Linux/3.10.14-100.fc18.i686.PAE" + 1 "python-requests/2.0.0 CPython/2.7.3 Linux/3.11.4-101.fc18.i686.PAE" + 773 "python-requests/2.0.0 CPython/2.7.3 Linux/3.2.0-31-generic" + 407 "python-requests/2.0.0 CPython/2.7.3 Linux/3.2.0-40-virtual" + 13950 "python-requests/2.0.0 CPython/2.7.3 Linux/3.5.0-37-generic" + 181 "python-requests/2.0.0 CPython/2.7.3 Linux/3.5.0-43-generic" + 379 "python-requests/2.0.0 CPython/2.7.3 Linux/3.8.11-ec2" + 234130 "python-requests/2.0.0 CPython/2.7.4 Linux/3.5.2-linode45" + 105 "python-requests/2.0.0 CPython/2.7.4 Linux/3.8.0-31-generic" + 1945 "python-requests/2.0.0 CPython/2.7.4 Linux/3.8.0-32-generic" + 17 "python-requests/2.0.0 CPython/2.7.4 Linux/3.8.0-34-generic" + 184 "python-requests/2.0.1 CPython/2.6.5 Linux/2.6.32-52-generic" + 1 "python-requests/2.0.1 CPython/2.7.3 Darwin/11.4.2" + 60 "python-requests/2.0.1 CPython/2.7.3 Darwin/13.0.0" + 18 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-40-virtual" + 23363 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-54-virtual" + 23 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-55-virtual" + 174 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-56-generic" + 23 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-56-virtual" + 10 "python-requests/2.0.1 CPython/2.7.3 Linux/3.2.0-57-generic" + 236 "python-requests/2.0.1 CPython/2.7.4 Linux/3.8.0-32-generic" + 1803 "python-requests/2.0.1 CPython/2.7.5 Darwin/11.4.2" + 188 "python-requests/2.0.1 CPython/2.7.5 Darwin/13.0.0" + 14374 "python-requests/2.0.1 CPython/2.7.5 Linux/2.6.18-308.20.1.el5" + 61250 "python-requests/2.0.1 CPython/2.7.5 Linux/2.6.18-308.24.1.el5" + 2 "python-requests/2.0.1 CPython/2.7.5 Linux/3.11.6-200.fc19.x86_64" + 2757 "python-requests/2.0.1 CPython/2.7.5 Linux/3.2.11" + 91 "python-requests/2.0.1 CPython/2.7.6 Darwin/13.0.0" + 56 "Python-urllib/1.17" + 66 "Python-urllib/2.6" + 110 "Python-urllib/2.7" + 3 "Python-urllib/2.7 distribute/0.6.24dev-r0" + 1 "Python-urllib/2.7 distribute/0.6.28" + 1 "Python-urllib/2.7 setuptools/0.6c11" + 1 "QuerySeekerSpider ( http://queryseeker.com/bot.html )" + 1 "QuickTime/7.4.1 (qtver=7.4.1;cpu=IA32;os=Mac 10.5.8)" + 1 "QuickTime/7.6.2 (qtver=7.6.2;cpu=PPC;os=Mac 10.5.8)" + 5 "QuickTime/7.6.6 (qtver=7.6.6;cpu=IA32;os=Mac 10.6.8)" + 2 "QuickTime/7.7.1 (qtver=7.7.1;cpu=IA32;os=Mac 10.7.5)" + 89 "Restler for node.js" + 3 "rogerbot/1.0 (http://moz.com/help/pro/what-is-rogerbot-, rogerbot-crawler+shiny@moz.com)" + 2964 "Ruby" + 8 "SEOstats 2.1.0" + 16 "SeznamBot/3.0 (+http://fulltext.sblog.cz/)" + 2 "ShowyouBot (http://showyou.com/crawler)" + 3 "SiteCheck - http://downforeveryoneorjustme.com" + 11 "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)" + 1 "SonyC6903 Build/14.1.G.2.257 stagefright/1.2 (Linux;Android 4.2.2)" + 8 "Sosospider+(+help.soso.com/webspider.htm)" + 36 "spyder/Nutch-2.1 (just another internet crawler; http://www.paloaltonetworks.com/products/features/url-filtering.html; ghalevy@paloaltonetworks.com)" + 2 "stagefright/1.1 (Linux;Android 4.0.4)" + 3 "stagefright/1.2 (Linux;Android 4.0.3)" + 30 "stagefright/1.2 (Linux;Android 4.0.4)" + 6 "stagefright/1.2 (Linux;Android 4.1.1)" + 38 "stagefright/1.2 (Linux;Android 4.1.2)" + 1 "stagefright/1.2 (Linux;Android 4.1.2;motorola DROID RAZR HD Build/9.8.1Q-79)" + 13 "stagefright/1.2 (Linux;Android 4.1.2;motorola XT907 Build/9.8.1Q-78)" + 5 "stagefright/1.2 (Linux;Android 4.2.1)" + 27 "stagefright/1.2 (Linux;Android 4.2.2)" + 312 "stagefright/1.2 (Linux;Android 4.3)" + 9 "stagefright/1.2 (Linux;Android 4.3.1)" + 47 "stagefright/1.2 (Linux;Android 4.4)" + 14 "Stash 2.8.2" + 6 "test" + 2 "ThumbnailService/39600.038 CFNetwork/520.5.1 Darwin/11.4.2 (x86_64) (MacBookAir4%2C2)" + 4 "ThumbnailService/39600.038 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir5%2C1)" + 4 "ThumbnailService/39600.038 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (MacBookAir6%2C2)" + 2 "Time%20Butler/5 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookAir4%2C1)" + 72 "Twitterbot/1.0" + 70 "URL/Emacs" + 1 "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.2.28) Gecko/20120306 Firefox/3.6.28 GTB7.1" + 20 "User-Agent\x09Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" + 5 "W3C_Validator/1.3 http://validator.w3.org/services" + 1 "webcollage/1.135a" + 7 "Wget/1.11.4 Red Hat modified" + 5 "Wget/1.12 (darwin10.4.0)" + 10 "Wget/1.12 (linux-gnu)" + 75256 "Wget/1.13.4 (linux-gnu)" + 4 "Wget/1.14 (darwin11.4.2)" + 6 "Wget/1.14 (darwin12.2.1)" + 10 "Wget/1.14 (linux-gnu)" + 2 "Wget/1.9+cvs-stable (Red Hat modified)" + 1 "WhatWeb/0.4.8-dev" + 4 "Who.is Bot" + 41 "Wotbox/2.01 (+http://www.wotbox.com/bot/)" + 2 "\xE7\xA6\x81\xE5\x89\x87\xE4\xBA\x8B\xE9\xA0\x85\xE3\x81\xA7\xE3\x81\x99" + 9 "xmlset_roodkcableoj28840ybtide" + 6 "YisouSpider" + 1 "yoono/1.0 web-crawler/1.0" + 3150 "ZmEu" + 5 "Zollard" + 4662 "Zulip/0.3.10 Sparkle/0ed83cf" + 1 "Zulip/0.3.11 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookAir5%2C2)" + 362 "Zulip/0.3.11 Sparkle/0ed83cf" + 1 "Zulip/0.3.4 CFNetwork/596.5 Darwin/12.5.0 (x86_64) (Macmini6%2C1)" + 58 "Zulip/0.3.4 Sparkle/0ed83cf" + 1 "Zulip/0.3.4 Sparkle/313" + 50 "Zulip/0.3.5 Sparkle/0ed83cf" + 1 "Zulip/0.3.6 CFNetwork/596.4.3 Darwin/12.4.0 (x86_64) (MacBookPro9%2C2)" + 968 "Zulip/0.3.6 Sparkle/0ed83cf" + 440 "Zulip/0.3.7 Sparkle/0ed83cf" + 13 "Zulip/0.3.8 CFNetwork/673.0.3 Darwin/13.0.0 (x86_64) (MacBookPro10%2C1)" + 2 "Zulip/0.3.8 Sparkle/?" + 5810 "Zulip/0.3.8 Sparkle/0ed83cf" + 1215 "Zulip/0.3.9 Sparkle/0ed83cf" + 1631 "Zulip/0.4.0 Sparkle/0ed83cf" + 416 "Zulip/0.4.1 Sparkle/0ed83cf" + 1234 "Zulip/1.3 (iPhone; iOS 6.1.3; Scale/2.00)" + 90 "Zulip/1 (iPad; iOS 6.1.3; Scale/2.00)" + 7 "Zulip/1 (iPad; iOS 7.0; Scale/2.00)" + 84 "Zulip/1 (iPad Simulator; iOS 6.1; Scale/1.00)" + 8 "Zulip/1 (iPad Simulator; iOS 6.1; Scale/2.00)" + 403 "Zulip/1 (iPad Simulator; iOS 7.0; Scale/1.00)" + 22 "Zulip/1 (iPad Simulator; iOS 7.0; Scale/2.00)" + 115 "Zulip/1 (iPhone; iOS 6.0.1; Scale/2.00)" + 2408 "Zulip/1 (iPhone; iOS 6.1.2; Scale/2.00)" + 560 "Zulip/1 (iPhone; iOS 6.1.3; Scale/1.00)" + 100 "Zulip/1 (iPhone; iOS 6.1.3; Scale/2.00)" + 1652 "Zulip/1 (iPhone; iOS 6.1.4; Scale/2.00)" + 1988 "Zulip/1 (iPhone; iOS 7.0.2; Scale/2.00)" + 36 "Zulip/1 (iPhone; iOS 7.0.3; Scale/2.00)" + 4218 "Zulip/1 (iPhone; iOS 7.0; Scale/2.00)" + 531 "Zulip/1 (iPhone Simulator; iOS 6.1; Scale/1.00)" + 9490 "Zulip/1 (iPhone Simulator; iOS 6.1; Scale/2.00)" + 61 "Zulip/1 (iPhone Simulator; iOS 7.0.3; Scale/2.00)" + 26222 "Zulip/1 (iPhone Simulator; iOS 7.0; Scale/2.00)" + 1595 "Zulip/1 (iPod touch; iOS 7.0.2; Scale/2.00)" + 75 "Zulip/1 (iPod touch; iOS 7.0.3; Scale/2.00)" + 573 "Zulip/1 (iPod touch; iOS 7.0; Scale/2.00)" + 59 "Zulip/2 (iPad; iOS 6.1.3; Scale/1.00)" + 21 "Zulip/2 (iPad; iOS 6.1.3; Scale/2.00)" + 4 "Zulip/2 (iPad; iOS 6.1; Scale/1.00)" + 662 "Zulip/2 (iPad; iOS 7.0.2; Scale/1.00)" + 355 "Zulip/2 (iPad; iOS 7.0.2; Scale/2.00)" + 903 "Zulip/2 (iPad; iOS 7.0.3; Scale/1.00)" + 1663 "Zulip/2 (iPad; iOS 7.0.3; Scale/2.00)" + 973 "Zulip/2 (iPad; iOS 7.0.4; Scale/1.00)" + 1917 "Zulip/2 (iPad; iOS 7.0.4; Scale/2.00)" + 342 "Zulip/2 (iPad; iOS 7.0; Scale/1.00)" + 68 "Zulip/2 (iPad; iOS 7.0; Scale/2.00)" + 47 "Zulip/2 (iPad Simulator; iOS 7.0; Scale/2.00)" + 8803 "Zulip/2 (iPhone; iOS 6.1.3; Scale/1.00)" + 3686 "Zulip/2 (iPhone; iOS 6.1.3; Scale/2.00)" + 9235 "Zulip/2 (iPhone; iOS 6.1.4; Scale/2.00)" + 966 "Zulip/2 (iPhone; iOS 6.1; Scale/2.00)" + 418 "Zulip/2 (iPhone; iOS 7.0.1; Scale/2.00)" + 44035 "Zulip/2 (iPhone; iOS 7.0.2; Scale/2.00)" + 56446 "Zulip/2 (iPhone; iOS 7.0.3; Scale/2.00)" + 33814 "Zulip/2 (iPhone; iOS 7.0.4; Scale/2.00)" + 7018 "Zulip/2 (iPhone; iOS 7.0; Scale/2.00)" + 102 "Zulip/2 (iPhone; iOS 7.1; Scale/2.00)" + 455 "Zulip/2 (iPhone Simulator; iOS 7.0; Scale/2.00)" + 37 "Zulip/2 (iPod touch; iOS 7.0.2; Scale/2.00)" + 1701 "Zulip/3 (iPhone; iOS 6.1.3; Scale/2.00)" + 734 "Zulip/3 (iPhone; iOS 6.1.4; Scale/2.00)" + 119 "Zulip/3 (iPhone; iOS 7.0; Scale/2.00)" + 42 "Zulip/4 (iPhone; iOS 6.1.3; Scale/2.00)" + 221 "Zulip/4 (iPhone; iOS 6.1.4; Scale/2.00)" + 220 "Zulip/4 (iPhone; iOS 6.1; Scale/2.00)" + 454 "Zulip/4 (iPhone; iOS 7.0.2; Scale/2.00)" + 253 "Zulip/4 (iPhone; iOS 7.0; Scale/2.00)" + 2854 "Zulip/4 (iPod touch; iOS 6.1.3; Scale/2.00)" + 942 "Zulip/5 (iPad; iOS 7.0; Scale/1.00)" + 24 "Zulip/5 (iPad Simulator; iOS 6.1; Scale/1.00)" + 8 "Zulip/5 (iPad Simulator; iOS 6.1; Scale/2.00)" + 40 "Zulip/5 (iPad Simulator; iOS 7.0; Scale/1.00)" + 23 "Zulip/5 (iPad Simulator; iOS 7.0; Scale/2.00)" + 50 "Zulip/5 (iPhone; iOS 6.1; Scale/2.00)" + 1413 "Zulip/5 (iPhone; iOS 7.0.2; Scale/2.00)" + 1469 "Zulip/5 (iPhone; iOS 7.0; Scale/2.00)" + 33 "Zulip/5 (iPhone Simulator; iOS 6.1; Scale/1.00)" + 25 "Zulip/5 (iPhone Simulator; iOS 6.1; Scale/2.00)" + 239 "Zulip/5 (iPhone Simulator; iOS 7.0; Scale/2.00)" + 1032 "Zulip/5 (iPod touch; iOS 7.0; Scale/2.00)" + 7492 "Zulip/alpha1 (iPhone Simulator; iOS 6.1; Scale/1.00)" + 1533 "Zulip/alpha1 (iPhone Simulator; iOS 7.0; Scale/2.00)" + 1121 "Zulip/alpha1 (iPod touch; iOS 7.0; Scale/2.00)" + 51712 "ZulipApple/1.5/7.0" + 2806 "ZulipApple/1.5/7.0.2" + 1657 "ZulipApple/1.5/7.0.3" + 2519 "ZulipApple/1.5/7.0.4" + 2 "ZulipMobile/0.6.0" + 125887 "ZulipMobile/0.6.0" + 1486 "ZulipMobile/0.7.0" + 1 "ZulipMobile/0.7.1" + 5726 "ZulipMobile/0.7.1" + 3265 "ZulipMobile/0.7.2" + 16628 "ZulipMobile/0.7.3" + 232703 "ZulipMobile/0.7.4" + 1186 "ZulipMobile/0.8-devel" diff --git a/zerver/lib/user_agent.py b/zerver/lib/user_agent.py new file mode 100644 index 0000000000..63e7904b67 --- /dev/null +++ b/zerver/lib/user_agent.py @@ -0,0 +1,10 @@ +import re + +# Warning: If you change this parsing, please test using +# tools/test_user_agent_parsing.py +# And extend tools/user_agents_unique with any new test cases +def parse_user_agent(user_agent): + match = re.match("^(?P[^/ ]*[^0-9/(]*)(/(?P[^/ ]*))?([ /].*)?$", user_agent) + if match is None: + return None + return match.groupdict()