diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69aad48aa9..dcb63746a5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,3 +50,10 @@ Following environment variables can be set to configure orion core service: ### HTTP server * **DEFGUARD_WEB_PORT**: web services bind port, default = `8000` + + +### User agents YAML update + +``` +curl -Lf https://raw.githubusercontent.com/ua-parser/uap-core/master/regexes.yaml | yq -y '.' > user_agent_header_regexes.yaml +``` diff --git a/Cargo.lock b/Cargo.lock index 336392acf0..8053b412f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -112,33 +112,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -235,18 +235,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -266,7 +266,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -288,7 +288,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -314,9 +314,9 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.4.0", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -375,7 +375,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -399,7 +399,7 @@ dependencies = [ "futures-util", "headers", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -431,12 +431,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - [[package]] name = "base64" version = "0.13.1" @@ -530,9 +524,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "serde", @@ -558,18 +552,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.104" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" [[package]] name = "cfg-if" @@ -645,9 +639,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.8" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" dependencies = [ "clap_builder", "clap_derive", @@ -655,9 +649,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -667,27 +661,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "compact_jwt" @@ -806,9 +800,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" @@ -939,14 +933,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -954,27 +948,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -1009,7 +1003,6 @@ dependencies = [ "mime_guess", "model_derive", "openidconnect", - "otpauth", "prost", "prost-build", "pulldown-cmark", @@ -1040,6 +1033,7 @@ dependencies = [ "tonic", "tonic-build", "tonic-health", + "totp-lite", "tower-http", "tracing", "tracing-subscriber", @@ -1096,7 +1090,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -1109,7 +1103,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -1138,7 +1132,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -1242,9 +1236,9 @@ dependencies = [ [[package]] name = "email_address" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1019fa28f600f5b581b7a603d515c3f1635da041ca211b5055804788673abfe" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" [[package]] name = "encoding_rs" @@ -1405,9 +1399,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -1421,7 +1415,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -1537,7 +1531,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -1666,7 +1660,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -1828,9 +1822,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -1845,7 +1839,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1884,9 +1878,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -1908,15 +1902,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -1934,7 +1928,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.30", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -1948,9 +1942,9 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.0", + "hyper 1.4.1", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -1964,7 +1958,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.29", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -1977,7 +1971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.29", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", @@ -1985,16 +1979,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.4.0", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -2119,9 +2113,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -2154,9 +2148,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -2200,7 +2194,7 @@ dependencies = [ "base64 0.21.7", "js-sys", "pem", - "ring 0.17.8", + "ring", "serde", "serde_json", "simple_asn1", @@ -2234,7 +2228,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -2423,13 +2417,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2437,7 +2432,7 @@ name = "model_derive" version = "0.1.2" dependencies = [ "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -2563,35 +2558,25 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -2616,9 +2601,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -2703,9 +2688,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -2724,7 +2709,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -2735,9 +2720,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -2764,17 +2749,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "otpauth" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca79a3dc8a04388203b57a706221f2d98b5be8ad85db486e6f995777c35ae25" -dependencies = [ - "base32", - "byteorder", - "ring 0.16.20", -] - [[package]] name = "overload" version = "0.1.1" @@ -2863,7 +2837,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.3", "smallvec", "windows-targets 0.52.6", ] @@ -2950,7 +2924,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -2971,7 +2945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.3.0", ] [[package]] @@ -3029,7 +3003,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -3091,9 +3065,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" @@ -3102,7 +3079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -3213,7 +3190,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.68", + "syn 2.0.74", "tempfile", ] @@ -3227,7 +3204,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -3285,16 +3262,17 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", + "socket2", "thiserror", "tokio", "tracing", @@ -3302,15 +3280,15 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" dependencies = [ "bytes", "rand", - "ring 0.17.8", + "ring", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "slab", "thiserror", "tinyvec", @@ -3319,9 +3297,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", @@ -3341,9 +3319,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0" +checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" [[package]] name = "radium" @@ -3401,18 +3379,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -3468,7 +3446,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-rustls 0.24.2", "hyper-tls", "ipnet", @@ -3513,9 +3491,9 @@ dependencies = [ "futures-core", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.4.0", + "hyper 1.4.1", "hyper-rustls 0.27.2", "hyper-util", "ipnet", @@ -3526,8 +3504,8 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.11", - "rustls-pemfile 2.1.2", + "rustls 0.23.12", + "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", "serde_json", @@ -3554,21 +3532,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -3579,8 +3542,8 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -3629,9 +3592,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -3640,22 +3603,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.68", + "syn 2.0.74", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ "globset", "sha2", @@ -3680,9 +3643,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc-hex" @@ -3728,7 +3691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki 0.101.7", "sct", ] @@ -3740,23 +3703,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "once_cell", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] @@ -3768,7 +3731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.1.3", "rustls-pki-types", "schannel", "security-framework", @@ -3785,9 +3748,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64 0.22.1", "rustls-pki-types", @@ -3795,9 +3758,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -3805,19 +3768,19 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -3886,8 +3849,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3935,9 +3898,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", "core-foundation", @@ -3948,9 +3911,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -3964,9 +3927,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] @@ -4002,22 +3965,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -4066,15 +4030,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.3" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73139bc5ec2d45e6c5fd85be5a46949c1c39a4c18e56915f5eb4c12f975e377" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_derive", "serde_json", @@ -4084,14 +4048,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.3" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b80d3d6b56b64335c0180e5ffde23b3c5e08c14c585b51a15bd0e95393f46703" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4100,7 +4064,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", "ryu", "serde", @@ -4222,12 +4186,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -4292,7 +4250,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.6", + "indexmap 2.3.0", "ipnetwork", "log", "memchr", @@ -4541,22 +4499,22 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "struct-patch" -version = "0.4.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c52ef523e89b3172242bbabefd8a92493ae5571224c29ed2f00185c39b395c2" +checksum = "084489a427e3470993d4008c935a3d3f10936d520c5b2a527da392bb1e604eee" dependencies = [ "struct-patch-derive", ] [[package]] name = "struct-patch-derive" -version = "0.4.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f14a349c27ebe59faba22f933c9c734d428da7231e88a247e9d8c61eea964ddb" +checksum = "5e542f637a488f779cf52b27208dbc425dbb858a6ddbc9e77087d268f72494b3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4578,7 +4536,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4600,9 +4558,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -4662,14 +4620,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4696,22 +4655,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4766,9 +4725,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4781,20 +4740,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4809,13 +4767,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4855,7 +4813,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] @@ -4887,9 +4845,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -4897,7 +4855,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow", ] @@ -4917,13 +4875,13 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", "prost", "rustls-native-certs", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.1.3", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -4944,7 +4902,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -4960,6 +4918,18 @@ dependencies = [ "tonic", ] +[[package]] +name = "totp-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8e43134db17199f7f721803383ac5854edd0d3d523cc34dba321d6acfbe76c3" +dependencies = [ + "digest", + "hmac", + "sha1", + "sha2", +] + [[package]] name = "tower" version = "0.4.13" @@ -4990,7 +4960,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "http-range-header", "httpdate", @@ -5037,7 +5007,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -5255,12 +5225,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -5297,7 +5261,7 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_json", "utoipa-gen", @@ -5313,7 +5277,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -5336,9 +5300,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "serde", @@ -5358,9 +5322,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -5414,7 +5378,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", "wasm-bindgen-shared", ] @@ -5448,7 +5412,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5623,11 +5587,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5673,6 +5637,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -5868,6 +5841,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -5879,7 +5853,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -5899,7 +5873,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.74", ] [[package]] @@ -5913,7 +5887,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.2.6", + "indexmap 2.3.0", "num_enum", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 6549b8b09f..681ce8f56b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,6 @@ model_derive = { path = "model-derive" } openidconnect = { version = "3.5", default-features = false, optional = true, features = [ "reqwest", ] } -otpauth = "0.4" prost = "0.12" pulldown-cmark = "0.11" rand = "0.8" @@ -50,7 +49,7 @@ rand_core = { version = "0.6", default-features = false, features = [ # TODO: update reqwest when openidconnect also depends on http >= 1.0. reqwest = { version = "0.11", features = ["json"] } rsa = { version = "0.9", features = ["pem"] } -rust-embed = { version = "8.4", features = ["include-exclude"] } +rust-embed = { version = "8.5", features = ["include-exclude"] } rust-ini = "0.20" secp256k1 = { version = "0.29", features = [ "recovery", @@ -64,7 +63,7 @@ serde_cbor = { version = "0.12.0-dev", package = "serde_cbor_2" } serde_json = "1.0" serde_urlencoded = "0.7" sha-1 = "0.10" -sqlx = { version = "0.7.4", features = [ +sqlx = { version = "0.7", features = [ "chrono", "ipnetwork", "runtime-tokio-native-tls", @@ -72,7 +71,7 @@ sqlx = { version = "0.7.4", features = [ "uuid", ] } ssh-key = "0.6" -struct-patch = "0.4" +struct-patch = "0.7" tera = "1.20" thiserror = "1.0" # match axum-extra -> cookies @@ -88,6 +87,7 @@ tokio = { version = "1", features = [ ] } tokio-stream = "0.1" tonic = { version = "0.11", features = ["gzip", "tls", "tls-roots"] } +totp-lite = { version = "2.0" } tower-http = { version = "0.5", features = ["fs", "trace"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/drop_test_dbs.sh b/drop_test_dbs.sh index f991182145..f4fa228fe0 100755 --- a/drop_test_dbs.sh +++ b/drop_test_dbs.sh @@ -4,14 +4,13 @@ set -eo pipefail -if [ -f .env ] -then - export $(cat .env | sed 's/#.*//g'| xargs) +if [ -f .env ]; then + export $(sed -e 's/#.*//g' .env | xargs) fi if ! [ -x "$(command -v psql)" ]; then - echo >&2 "Error: psql is not installed." - exit 1 + echo >&2 "Error: psql is not installed." + exit 1 fi if [ -z "${DATABASE_URL}" ]; then @@ -19,7 +18,7 @@ if [ -z "${DATABASE_URL}" ]; then exit 1 fi -PATTERN="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" +PATTERN='[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' echo "Dropping test databases" diff --git a/src/auth/mod.rs b/src/auth/mod.rs index c5ea796f22..9fdc7f679a 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -28,7 +28,6 @@ pub static JWT_ISSUER: &str = "DefGuard"; pub static AUTH_SECRET_ENV: &str = "DEFGUARD_AUTH_SECRET"; pub static GATEWAY_SECRET_ENV: &str = "DEFGUARD_GATEWAY_SECRET"; pub static YUBIBRIDGE_SECRET_ENV: &str = "DEFGUARD_YUBIBRIDGE_SECRET"; -pub const TOTP_CODE_VALIDITY_PERIOD: u64 = 30; #[derive(Clone, Copy, Default)] pub enum ClaimsType { diff --git a/src/bin/defguard.rs b/src/bin/defguard.rs index d663f2b81b..749ca40010 100644 --- a/src/bin/defguard.rs +++ b/src/bin/defguard.rs @@ -35,7 +35,7 @@ async fn main() -> Result<(), anyhow::Error> { tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| format!("{}", config.log_level).into()), + .unwrap_or_else(|_| config.log_level.clone().into()), ) .with(tracing_subscriber::fmt::layer()) .init(); diff --git a/src/db/models/settings.rs b/src/db/models/settings.rs index 8f0d343f06..edaa4b366d 100644 --- a/src/db/models/settings.rs +++ b/src/db/models/settings.rs @@ -16,7 +16,7 @@ pub enum SmtpEncryption { } #[derive(Debug, Clone, Model, Serialize, Deserialize, PartialEq, Patch)] -#[patch_derive(Serialize, Deserialize)] +#[patch(attribute(derive(Serialize, Deserialize)))] pub struct Settings { #[serde(skip)] pub id: Option, diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 773c87b3af..76257d191b 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -9,8 +9,8 @@ use argon2::{ }; use axum::http::StatusCode; use model_derive::Model; -use otpauth::TOTP; use sqlx::{query, query_as, query_scalar, Error as SqlxError, PgExecutor, Type}; +use totp_lite::{totp, totp_custom, Sha1}; use super::{ device::{Device, UserDevice}, @@ -20,14 +20,15 @@ use super::{ DbPool, MFAInfo, OAuth2AuthorizedAppInfo, SecurityKey, WalletInfo, }; use crate::{ - auth::TOTP_CODE_VALIDITY_PERIOD, db::Session, error::WebError, + hex::to_lower_hex, random::{gen_alphanumeric, gen_totp_secret}, server_config, }; const RECOVERY_CODES_COUNT: usize = 8; +const EMAIL_CODE_DIGITS: u32 = 6; #[derive(Clone, Deserialize, Serialize, PartialEq, Type, Debug)] #[sqlx(type_name = "mfa_method", rename_all = "snake_case")] @@ -160,6 +161,7 @@ impl User { /// Check if user is enrolled. /// We assume the user is enrolled if they have a password set /// or they have logged in using an external OIDC. + #[must_use] pub fn is_enrolled(&self) -> bool { self.password_hash.is_some() || self.openid_login } @@ -179,7 +181,7 @@ impl User { .execute(executor) .await?; } - let secret_base32 = TOTP::from_bytes(&secret).base32_secret(); + let secret_base32 = to_lower_hex(&secret); self.totp_secret = Some(secret); Ok(secret_base32) } @@ -509,43 +511,75 @@ impl User { /// Check if TOTP `code` is valid. #[must_use] - pub fn verify_totp_code(&self, code: u32) -> bool { + pub fn verify_totp_code(&self, code: &str) -> bool { if let Some(totp_secret) = &self.totp_secret { - let totp = TOTP::from_bytes(totp_secret); if let Ok(timestamp) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { - return totp.verify(code, TOTP_CODE_VALIDITY_PERIOD, timestamp.as_secs()); + let expected_code = totp::(totp_secret, timestamp.as_secs()); + eprintln!("{expected_code} ?? {code}"); + return code == expected_code; } } false } - pub fn generate_email_mfa_code(&self) -> Result { - match &self.email_mfa_secret { - Some(email_mfa_secret) => { - let auth = TOTP::from_bytes(email_mfa_secret); - let timeout = &server_config().mfa_code_timeout; - let timestamp = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs(); - let code = auth.generate(timeout.as_secs(), timestamp); + /// Generate MFA code for email verification. + /// + /// NOTE: This code will be valid for two time frames. See comment for verify_email_mfa_code(). + pub fn generate_email_mfa_code(&self) -> Result { + if let Some(email_mfa_secret) = &self.email_mfa_secret { + let timeout = &server_config().mfa_code_timeout; + if let Ok(timestamp) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { + let code = totp_custom::( + timeout.as_secs(), + EMAIL_CODE_DIGITS, + email_mfa_secret, + timestamp.as_secs(), + ); Ok(code) + } else { + Err(WebError::EmailMfa("SystemTime before UNIX epoch".into())) } - None => Err(WebError::EmailMfa(format!( + } else { + Err(WebError::EmailMfa(format!( "Email MFA secret not configured for user {}", self.username - ))), + ))) } } /// Check if email MFA `code` is valid. + /// + /// IMPORTANT: because current implementation uses TOTP for email verification, + /// allow the code for the previous time frame. This approach pretends the code is valid + /// for a certain *period of time* (as opposed to a TOTP code which is valid for a certain time *frame*). + /// + /// ```text + /// |<---- frame #0 ---->|<---- frame #1 ---->|<---- frame #2 ---->| + /// |................[*]email sent.................................| + /// |......................[*]email code verified..................| + /// ``` #[must_use] - pub fn verify_email_mfa_code(&self, code: u32) -> bool { + pub fn verify_email_mfa_code(&self, code: &str) -> bool { if let Some(email_mfa_secret) = &self.email_mfa_secret { - let totp = TOTP::from_bytes(email_mfa_secret); - let timeout = &server_config().mfa_code_timeout; + let timeout = server_config().mfa_code_timeout.as_secs(); if let Ok(timestamp) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { - return totp.verify(code, timeout.as_secs(), timestamp.as_secs()); + let expected_code = totp_custom::( + timeout, + EMAIL_CODE_DIGITS, + email_mfa_secret, + timestamp.as_secs(), + ); + if code == expected_code { + return true; + } + + let previous_code = totp_custom::( + timeout, + EMAIL_CODE_DIGITS, + email_mfa_secret, + timestamp.as_secs() - timeout, + ); + return code == previous_code; } } false @@ -827,6 +861,30 @@ impl User { #[cfg(test)] mod test { use super::*; + use crate::{config::DefGuardConfig, SERVER_CONFIG}; + + #[sqlx::test] + async fn test_mfa_code(pool: DbPool) { + let config = DefGuardConfig::new_test_config(); + let _ = SERVER_CONFIG.set(config.clone()); + + let mut user = User::new( + "hpotter", + Some("pass123"), + "Potter", + "Harry", + "h.potter@hogwart.edu.uk", + None, + ); + user.new_email_secret(&pool).await.unwrap(); + assert!(user.email_mfa_secret.is_some()); + let code = user.generate_email_mfa_code().unwrap(); + assert!( + user.verify_email_mfa_code(&code), + "code={code}, secret={:?}", + user.email_mfa_secret.unwrap() + ); + } #[sqlx::test] async fn test_user(pool: DbPool) { diff --git a/src/enterprise/handlers/openid_login.rs b/src/enterprise/handlers/openid_login.rs index 5a81583633..b052f7ae1a 100644 --- a/src/enterprise/handlers/openid_login.rs +++ b/src/enterprise/handlers/openid_login.rs @@ -55,16 +55,20 @@ async fn get_provider_metadata(url: &str) -> Result { // Discover the provider metadata based on a known base issuer URL // The url should be in the form of e.g. https://accounts.google.com // The url shouldn't contain a .well-known part, it will be added automatically - let provider_metadata = - match CoreProviderMetadata::discover_async(issuer_url, async_http_client).await { - Ok(metadata) => metadata, - Err(_) => { - return Err(WebError::Authorization(format!( - "Failed to discover provider metadata, make sure the providers' url is correct: {}", - url + let provider_metadata = match CoreProviderMetadata::discover_async( + issuer_url, + async_http_client, + ) + .await + { + Ok(metadata) => metadata, + Err(_) => { + return Err(WebError::Authorization(format!( + "Failed to discover provider metadata, make sure the providers' url is correct: {url}", + ))); - } - }; + } + }; Ok(provider_metadata) } @@ -218,8 +222,7 @@ pub async fn auth_callback( Ok(claims) => claims, Err(error) => { return Err(WebError::Authorization(format!( - "Failed to verify ID token, error: {:?}", - error + "Failed to verify ID token, error: {error:?}", ))); } }; diff --git a/src/grpc/desktop_client_mfa.rs b/src/grpc/desktop_client_mfa.rs index 107ff5d31a..3d7eb091d6 100644 --- a/src/grpc/desktop_client_mfa.rs +++ b/src/grpc/desktop_client_mfa.rs @@ -202,13 +202,13 @@ impl ClientMfaServer { // validate code match method { MfaMethod::Totp => { - if !user.verify_totp_code(request.code) { + if !user.verify_totp_code(&request.code.to_string()) { error!("Provided TOTP code is not valid"); return Err(Status::unauthenticated("unauthorized")); } } MfaMethod::Email => { - if !user.verify_email_mfa_code(request.code) { + if !user.verify_email_mfa_code(&request.code.to_string()) { error!("Provided email code is not valid"); return Err(Status::unauthenticated("unauthorized")); } diff --git a/src/handlers/auth.rs b/src/handlers/auth.rs index 088ffdf453..1c4860638c 100644 --- a/src/handlers/auth.rs +++ b/src/handlers/auth.rs @@ -474,7 +474,7 @@ pub async fn totp_enable( ) -> ApiResult { let mut user = session.user; debug!("Enabling TOTP for user {}", user.username); - if user.verify_totp_code(data.code) { + if user.verify_totp_code(&data.code) { let recovery_codes = RecoveryCodes::new(user.get_recovery_codes(&appstate.pool).await?); user.enable_totp(&appstate.pool).await?; if user.mfa_method == MFAMethod::None { @@ -518,7 +518,7 @@ pub async fn totp_code( if let Some(user) = User::find_by_id(&appstate.pool, session.user_id).await? { let username = user.username.clone(); debug!("Verifying TOTP for user {}", username); - if user.totp_enabled && user.verify_totp_code(data.code) { + if user.totp_enabled && user.verify_totp_code(&data.code) { session .set_state(&appstate.pool, SessionState::MultiFactorVerified) .await?; @@ -587,7 +587,7 @@ pub async fn email_mfa_enable( ) -> ApiResult { let mut user = session.user; debug!("Enabling email MFA for user {}", user.username); - if user.verify_email_mfa_code(data.code) { + if user.verify_email_mfa_code(&data.code) { let recovery_codes = RecoveryCodes::new(user.get_recovery_codes(&appstate.pool).await?); user.enable_email_mfa(&appstate.pool).await?; if user.mfa_method == MFAMethod::None { @@ -653,7 +653,7 @@ pub async fn email_mfa_code( if let Some(user) = User::find_by_id(&appstate.pool, session.user_id).await? { let username = user.username.clone(); debug!("Verifying email MFA code for user {}", username); - if user.email_mfa_enabled && user.verify_email_mfa_code(data.code) { + if user.email_mfa_enabled && user.verify_email_mfa_code(&data.code) { session .set_state(&appstate.pool, SessionState::MultiFactorVerified) .await?; diff --git a/src/handlers/mail.rs b/src/handlers/mail.rs index a687ca7450..3c413291b1 100644 --- a/src/handlers/mail.rs +++ b/src/handlers/mail.rs @@ -356,7 +356,7 @@ pub fn send_email_mfa_activation_email( let mail = Mail { to: user.email.clone(), subject: EMAIL_MFA_ACTIVATION_EMAIL_SUBJECT.into(), - content: templates::email_mfa_activation_mail(code, session)?, + content: templates::email_mfa_activation_mail(&code, session)?, attachments: Vec::new(), result_tx: None, }; @@ -391,7 +391,7 @@ pub fn send_email_mfa_code_email( let mail = Mail { to: user.email.clone(), subject: EMAIL_MFA_CODE_EMAIL_SUBJECT.into(), - content: templates::email_mfa_code_mail(code, session)?, + content: templates::email_mfa_code_mail(&code, session)?, attachments: Vec::new(), result_tx: None, }; diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 0612666d9a..91362446d4 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -162,13 +162,13 @@ impl AuthTotp { #[derive(Deserialize, Serialize)] pub struct AuthCode { - code: u32, + code: String, } impl AuthCode { #[must_use] - pub fn new(code: u32) -> Self { - Self { code } + pub fn new>(code: S) -> Self { + Self { code: code.into() } } } diff --git a/src/headers.rs b/src/headers.rs index e20a816bc0..4e1b843695 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -13,11 +13,7 @@ use crate::{ #[must_use] pub fn create_user_agent_parser() -> Arc { let regexes = include_bytes!("../user_agent_header_regexes.yaml"); - Arc::new( - UserAgentParser::builder() - .build_from_bytes(regexes) - .expect("Parser creation failed"), - ) + Arc::new(UserAgentParser::from_bytes(regexes).expect("Parser creation failed")) } #[must_use] diff --git a/src/templates.rs b/src/templates.rs index 4d803d43bb..1702cb61c0 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -249,22 +249,20 @@ pub fn gateway_disconnected_mail( Ok(tera.render("mail_gateway_disconnected", &context)?) } -pub fn email_mfa_activation_mail(code: u32, session: &Session) -> Result { +pub fn email_mfa_activation_mail(code: &str, session: &Session) -> Result { let (mut tera, mut context) = get_base_tera(None, Some(session), None, None)?; let timeout = server_config().mfa_code_timeout; - // zero-pad code to make sure it's always 6 digits long - context.insert("code", &format!("{code:0>6}")); + context.insert("code", code); context.insert("timeout", &timeout.to_string()); tera.add_raw_template("mail_email_mfa_activation", MAIL_EMAIL_MFA_ACTIVATION)?; Ok(tera.render("mail_email_mfa_activation", &context)?) } -pub fn email_mfa_code_mail(code: u32, session: Option<&Session>) -> Result { +pub fn email_mfa_code_mail(code: &str, session: Option<&Session>) -> Result { let (mut tera, mut context) = get_base_tera(None, session, None, None)?; let timeout = server_config().mfa_code_timeout; - // zero-pad code to make sure it's always 6 digits long - context.insert("code", &format!("{code:0>6}")); + context.insert("code", code); context.insert("timeout", &timeout.to_string()); tera.add_raw_template("mail_email_mfa_code", MAIL_EMAIL_MFA_CODE)?; @@ -351,7 +349,7 @@ mod test { #[test] fn test_enrollment_start_mail() { - SERVER_CONFIG.set(DefGuardConfig::default()).unwrap(); + let _ = SERVER_CONFIG.set(DefGuardConfig::default()); assert_ok!(enrollment_start_mail( Context::new(), Url::parse("http://localhost:8080").unwrap(), diff --git a/tests/auth.rs b/tests/auth.rs index 8267e1ac85..c19f2c83df 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -6,21 +6,20 @@ use chrono::NaiveDateTime; use claims::assert_err; use common::fetch_user_details; use defguard::{ - auth::TOTP_CODE_VALIDITY_PERIOD, db::{ models::wallet::keccak256, DbPool, MFAInfo, MFAMethod, Settings, User, UserDetails, Wallet, }, handlers::{Auth, AuthCode, AuthResponse, AuthTotp, WalletChallenge}, - hex::to_lower_hex, + hex::{hex_decode, to_lower_hex}, secret::SecretString, }; use ethers_core::types::transaction::eip712::{Eip712, TypedData}; -use otpauth::TOTP; use reqwest::{header::USER_AGENT, StatusCode}; use secp256k1::{rand::rngs::OsRng, All, Message, Secp256k1, SecretKey}; use serde::Deserialize; use serde_json::json; use sqlx::query; +use totp_lite::{totp, Sha1}; use webauthn_authenticator_rs::{prelude::Url, softpasskey::SoftPasskey, WebauthnAuthenticator}; use webauthn_rs::prelude::{CreationChallengeResponse, RequestChallengeResponse}; @@ -188,12 +187,12 @@ async fn test_cannot_enable_mfa() { } fn totp_code(auth_totp: &AuthTotp) -> AuthCode { - let auth = TOTP::from_base32(auth_totp.secret.clone()).unwrap(); let timestamp = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs(); - AuthCode::new(auth.generate(TOTP_CODE_VALIDITY_PERIOD, timestamp)) + .unwrap(); + let secret = hex_decode(&auth_totp.secret).unwrap(); + let code = totp::(&secret, timestamp.as_secs()); + AuthCode::new(code) } #[tokio::test] @@ -232,7 +231,7 @@ async fn test_totp() { assert_eq!(response.status(), StatusCode::UNAUTHORIZED); // provide wrong TOTP code - let code = AuthCode::new(0); + let code = AuthCode::new("0"); let response = client .post("/api/v1/auth/totp/verify") .json(&code) @@ -306,10 +305,10 @@ async fn test_totp() { } static EMAIL_CODE_REGEX: &str = r"(?\d{6})"; -fn extract_email_code(content: &str) -> u32 { +fn extract_email_code(content: &str) -> &str { let re = regex::Regex::new(EMAIL_CODE_REGEX).unwrap(); let code = re.captures(content).unwrap().name("code").unwrap().as_str(); - code.parse().unwrap() + code } #[tokio::test] @@ -390,7 +389,7 @@ async fn test_email_mfa() { assert_eq!(response.status(), StatusCode::UNAUTHORIZED); // provide wrong code - let code = AuthCode::new(0); + let code = AuthCode::new("0"); let response = client .post("/api/v1/auth/email/verify") .json(&code) diff --git a/user_agent_header_regexes.yaml b/user_agent_header_regexes.yaml index a8f8e09758..5609618af7 100644 --- a/user_agent_header_regexes.yaml +++ b/user_agent_header_regexes.yaml @@ -1,5863 +1,3875 @@ user_agent_parsers: - #### SPECIAL CASES TOP #### - - # ESRI Server products - - regex: '(GeoEvent Server) (\d+)(?:\.(\d+)(?:\.(\d+)|)|)' - - # ESRI ArcGIS Desktop Products + - regex: (GeoEvent Server) (\d+)(?:\.(\d+)(?:\.(\d+)|)|) - regex: '(ArcGIS Pro)(?: (\d+)\.(\d+)\.([^ ]+)|)' - - - regex: 'ArcGIS Client Using WinInet' - family_replacement: 'ArcMap' - - - regex: '(OperationsDashboard)-(?:Windows)-(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Operations Dashboard for ArcGIS' - - - regex: '(arcgisearth)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'ArcGIS Earth' - - - regex: 'com.esri.(earth).phone/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'ArcGIS Earth' - - # ESRI ArcGIS Mobile Products - - regex: '(arcgis-explorer)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Explorer for ArcGIS' - - - regex: 'arcgis-(collector|aurora)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Collector for ArcGIS' - - - regex: '(arcgis-workforce)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Workforce for ArcGIS' - - - regex: '(Collector|Explorer|Workforce)-(?:Android|iOS)-(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: '$1 for ArcGIS' - - - regex: '(Explorer|Collector)/(\d+) CFNetwork' - family_replacement: '$1 for ArcGIS' - - # ESRI ArcGIS Runtimes - - regex: 'ArcGISRuntime-(Android|iOS|NET|Qt)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'ArcGIS Runtime SDK for $1' - - - regex: 'ArcGIS\.?(iOS|Android|NET|Qt)(?:-|\.)(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'ArcGIS Runtime SDK for $1' - - - regex: 'ArcGIS\.Runtime\.(Qt)\.(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'ArcGIS Runtime SDK for $1' - - # CFNetwork Podcast catcher Applications - - regex: '^(Luminary)[Stage]+/(\d+) CFNetwork' - - regex: '(ESPN)[%20| ]+Radio/(\d+)\.(\d+)\.(\d+) CFNetwork' - - regex: '(Antenna)/(\d+) CFNetwork' - family_replacement: 'AntennaPod' - - regex: '(TopPodcasts)Pro/(\d+) CFNetwork' - - regex: '(MusicDownloader)Lite/(\d+)\.(\d+)\.(\d+) CFNetwork' - - regex: '^(.{0,200})-iPad\/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork' - - regex: '^(.{0,200})-iPhone/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork' - - regex: '^(.{0,200})/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork' - - # Podcast catchers - - regex: '^(Luminary)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - - regex: '(espn\.go)' - family_replacement: 'ESPN' - - regex: '(espnradio\.com)' - family_replacement: 'ESPN' - - regex: 'ESPN APP$' - family_replacement: 'ESPN' - - regex: '(audioboom\.com)' - family_replacement: 'AudioBoom' + - regex: ArcGIS Client Using WinInet + family_replacement: ArcMap + - regex: (OperationsDashboard)-(?:Windows)-(\d+)\.(\d+)\.(\d+) + family_replacement: Operations Dashboard for ArcGIS + - regex: (arcgisearth)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: ArcGIS Earth + - regex: com.esri.(earth).phone/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: ArcGIS Earth + - regex: (arcgis-explorer)/(\d+)\.(\d+)\.(\d+) + family_replacement: Explorer for ArcGIS + - regex: arcgis-(collector|aurora)/(\d+)\.(\d+)\.(\d+) + family_replacement: Collector for ArcGIS + - regex: (arcgis-workforce)/(\d+)\.(\d+)\.(\d+) + family_replacement: Workforce for ArcGIS + - regex: (Collector|Explorer|Workforce)-(?:Android|iOS)-(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: $1 for ArcGIS + - regex: (Explorer|Collector)/(\d+) CFNetwork + family_replacement: $1 for ArcGIS + - regex: ArcGISRuntime-(Android|iOS|NET|Qt)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: ArcGIS Runtime SDK for $1 + - regex: ArcGIS\.?(iOS|Android|NET|Qt)(?:-|\.)(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: ArcGIS Runtime SDK for $1 + - regex: ArcGIS\.Runtime\.(Qt)\.(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: ArcGIS Runtime SDK for $1 + - regex: ^(Luminary)[Stage]+/(\d+) CFNetwork + - regex: (ESPN)[%20| ]+Radio/(\d+)\.(\d+)\.(\d+) CFNetwork + - regex: (Antenna)/(\d+) CFNetwork + family_replacement: AntennaPod + - regex: (TopPodcasts)Pro/(\d+) CFNetwork + - regex: (MusicDownloader)Lite/(\d+)\.(\d+)\.(\d+) CFNetwork + - regex: ^(.{0,200})-iPad\/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork + - regex: ^(.{0,200})-iPhone/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork + - regex: ^(.{0,200})/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) CFNetwork + - regex: ^(Luminary)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (espn\.go) + family_replacement: ESPN + - regex: (espnradio\.com) + family_replacement: ESPN + - regex: ESPN APP$ + family_replacement: ESPN + - regex: (audioboom\.com) + family_replacement: AudioBoom - regex: ' (Rivo) RHYTHM' - - # @note: iOS / OSX Applications - - regex: '(CFNetwork)(?:/(\d+)\.(\d+)(?:\.(\d+)|)|)' - family_replacement: 'CFNetwork' - - # Pingdom - - 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' - # 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/61.0.3163.100 Chrome/61.0.3163.100 Safari/537.36 PingdomPageSpeed/1.0 (pingbot/2.0; +http://www.pingdom.com/)' - - regex: '(PingdomPageSpeed)/(\d+)\.(\d+)' - family_replacement: 'PingdomBot' - - # PTST / WebPageTest.org crawlers + - regex: (CFNetwork)(?:/(\d+)\.(\d+)(?:\.(\d+)|)|) + family_replacement: CFNetwork + - regex: (Pingdom\.com_bot_version_)(\d+)\.(\d+) + family_replacement: PingdomBot + - regex: (PingdomTMS)/(\d+)\.(\d+)\.(\d+) + family_replacement: PingdomBot + - regex: (PingdomPageSpeed)/(\d+)\.(\d+) + family_replacement: PingdomBot - 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' - - # Tableau - - regex: '(Tableau)/(\d+)\.(\d+)' - family_replacement: 'Tableau' - - # Adobe CreativeCloud - - regex: 'AppleWebKit/\d{1,10}\.\d{1,10}.{0,200} Safari.{0,200} (CreativeCloud)/(\d+)\.(\d+).(\d+)' - family_replacement: 'Adobe CreativeCloud' - - # Salesforce - - regex: '(Salesforce)(?:.)\/(\d+)\.(\d?)' - - #StatusCake - - regex: '(\(StatusCake\))' - family_replacement: 'StatusCakeBot' - - # Facebook - - regex: '(facebookexternalhit)/(\d+)\.(\d+)' - family_replacement: 'FacebookBot' - - # Google Plus - - regex: 'Google.{0,50}/\+/web/snippet' - family_replacement: 'GooglePlusBot' - - # Gmail - - regex: 'via ggpht\.com GoogleImageProxy' - family_replacement: 'GmailImageProxy' - - # Yahoo - - regex: 'YahooMailProxy; https://help\.yahoo\.com/kb/yahoo-mail-proxy-SLN28749\.html' - family_replacement: 'YahooMailProxy' - - # Twitter - - regex: '(Twitterbot)/(\d+)\.(\d+)' - family_replacement: 'Twitterbot' - - # Bots Pattern 'name/0.0.0' - - regex: '/((?:Ant-|)Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[ \-](\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - # Bots Pattern 'name/0.0.0' - - regex: '\b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|OgScrper|Pandora|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|[a-z]|);.{0,200} MSIECrawler' - family_replacement: 'MSIECrawler' - - # DAVdroid - - regex: '(DAVdroid)/(\d+)\.(\d+)(?:\.(\d+)|)' - - # Downloader ... - - regex: '(Google-HTTP-Java-Client|Apache-HttpClient|PostmanRuntime|Go-http-client|scalaj-http|http%20client|Python-urllib|HttpMonitor|TLSProber|WinHTTP|JNLP|okhttp|aihttp|reqwest|axios|unirest-(?:java|python|ruby|nodejs|php|net))(?:[ /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - - # Pinterestbot - - regex: '(Pinterest(?:bot|))/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)[;\s(]+\+https://www.pinterest.com/bot.html' - family_replacement: 'Pinterestbot' - - # Bots - - 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|OgScrper|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo Screenshot Bot|PHPCrawl|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|ArcGIS Hub Indexer)(?:[ /]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?|dotnet-(?:\d{1,2}|core)))|s3fs)/(\d+)\.(\d+)(?:\.(\d+)|)' - - # SAFE FME - - regex: '(FME)\/(\d+\.\d+)\.(\d+)\.(\d+)' - - # QGIS - - regex: '(QGIS)\/(\d)\.?0?(\d{1,2})\.?0?(\d{1,2})' - - # JOSM - - regex: '(JOSM)/(\d+)\.(\d+)' - - # Tygron Platform - - regex: '(Tygron Platform) \((\d+)\.(\d+)\.(\d+(?:\.\d+| RC \d+\.\d+))' - - # Facebook - # Must come before "Bots General matcher" to catch OrangeBotswana - # Facebook Messenger must go before Facebook - - regex: '\[(FBAN/MessengerForiOS|FB_IAB/MESSENGER);FBAV/(\d+)(?:\.(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)' - - family_replacement: 'Facebook Messenger' - # Facebook - - regex: '\[FB.{0,300};(FBAV)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - family_replacement: 'Facebook' - # Sometimes Facebook does not specify a version (FBAV) - - regex: '\[FB.{0,300};' - family_replacement: 'Facebook' - - # Bots General matcher 'name/0.0' - - regex: '^.{0,200}?(?:\/[A-Za-z0-9\.]{0,50}|) {0,2}([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: '^.{0,200}?((?:[A-Za-z][A-Za-z0-9 -]{0,50}|)[^C][^Uu][Bb]ot)\b(?:(?:[ /]| v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - # Bots containing spider|scrape|Crawl - - regex: '^.{0,200}?((?:[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 - # See os_parsers if you want to target a specific TV - - 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]*|)' - - # must be before Firefox / Gecko to catch SailfishBrowser properly - - regex: '(SailfishBrowser)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Sailfish Browser' - - # Social Networks (non-Facebook) - # Pinterest - - regex: '\[(Pinterest)/[^\]]{1,50}\]' + family_replacement: WebPageTest.org bot + - regex: X11; (Datanyze); Linux + - regex: (NewRelicPinger)/(\d+)\.(\d+) + family_replacement: NewRelicPingerBot + - regex: (Tableau)/(\d+)\.(\d+) + family_replacement: Tableau + - regex: AppleWebKit/\d{1,10}\.\d{1,10}.{0,200} Safari.{0,200} (CreativeCloud)/(\d+)\.(\d+).(\d+) + family_replacement: Adobe CreativeCloud + - regex: (Salesforce)(?:.)\/(\d+)\.(\d?) + - regex: (\(StatusCake\)) + family_replacement: StatusCakeBot + - regex: (facebookexternalhit)/(\d+)\.(\d+) + family_replacement: FacebookBot + - regex: Google.{0,50}/\+/web/snippet + family_replacement: GooglePlusBot + - regex: via ggpht\.com GoogleImageProxy + family_replacement: GmailImageProxy + - regex: YahooMailProxy; https://help\.yahoo\.com/kb/yahoo-mail-proxy-SLN28749\.html + family_replacement: YahooMailProxy + - regex: (Twitterbot)/(\d+)\.(\d+) + family_replacement: Twitterbot + - regex: /((?:Ant-|)Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[ + \-](\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: \b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|OgScrper|Pandora|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (MSIE) (\d+)\.(\d+)([a-z]\d|[a-z]|);.{0,200} MSIECrawler + family_replacement: MSIECrawler + - regex: (DAVdroid)/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: (Google-HTTP-Java-Client|Apache-HttpClient|PostmanRuntime|Go-http-client|scalaj-http|http%20client|Python-urllib|HttpMonitor|TLSProber|WinHTTP|JNLP|okhttp|aihttp|reqwest|axios|unirest-(?:java|python|ruby|nodejs|php|net))(?:[ + /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + - regex: (Pinterest(?:bot|))/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)[;\s(]+\+https://www.pinterest.com/bot.html + family_replacement: Pinterestbot + - 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|OgScrper|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo + Screenshot Bot|PHPCrawl|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|ArcGIS + Hub Indexer)(?:[ /]v?(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)' + - regex: \b(Boto3?|JetS3t|aws-(?:cli|sdk-(?:cpp|go|java|nodejs|ruby2?|dotnet-(?:\d{1,2}|core)))|s3fs)/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: (FME)\/(\d+\.\d+)\.(\d+)\.(\d+) + - regex: (QGIS)\/(\d)\.?0?(\d{1,2})\.?0?(\d{1,2}) + - regex: (JOSM)/(\d+)\.(\d+) + - regex: (Tygron Platform) \((\d+)\.(\d+)\.(\d+(?:\.\d+| RC \d+\.\d+)) + - regex: \[(FBAN/MessengerForiOS|FB_IAB/MESSENGER);FBAV/(\d+)(?:\.(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|) + family_replacement: Facebook Messenger + - regex: \[FB.{0,300};(FBAV)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Facebook + - regex: \[FB.{0,300}; + family_replacement: Facebook + - regex: ^.{0,200}?(?:\/[A-Za-z0-9\.]{0,50}|) {0,2}([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+)|)|) + - regex: ^.{0,200}?((?:[A-Za-z][A-Za-z0-9 -]{0,50}|)[^C][^Uu][Bb]ot)\b(?:(?:[ /]| + v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + - regex: '^.{0,200}?((?:[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+)|)|)' + - regex: (HbbTV)/(\d+)\.(\d+)\.(\d+) \( + - regex: (Chimera|SeaMonkey|Camino|Waterfox)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*|) + - regex: (SailfishBrowser)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Sailfish Browser + - regex: \[(Pinterest)/[^\]]{1,50}\] - regex: '(Pinterest)(?: for Android(?: Tablet|)|)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - # Instagram app - - regex: 'Mozilla.{1,200}Mobile.{1,100}(Instagram).(\d+)\.(\d+)\.(\d+)' - # Flipboard app - - regex: 'Mozilla.{1,200}Mobile.{1,100}(Flipboard).(\d+)\.(\d+)\.(\d+)' - # Flipboard-briefing app - - regex: 'Mozilla.{1,200}Mobile.{1,100}(Flipboard-Briefing).(\d+)\.(\d+)\.(\d+)' - # Onefootball app - - regex: 'Mozilla.{1,200}Mobile.{1,100}(Onefootball)\/Android.(\d+)\.(\d+)\.(\d+)' - # Snapchat - - regex: '(Snapchat)\/(\d+)\.(\d+)\.(\d+)\.(\d+)' - # Twitter - - regex: '(Twitter for (?:iPhone|iPad)|TwitterAndroid)(?:\/(\d+)\.(\d+)|)' - family_replacement: 'Twitter' - - # Phantom app - - regex: 'Mozilla.{1,200}Mobile.{1,100}(Phantom\/ios|android).(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Phantom' - - # aspiegel.com spider (owned by Huawei, later called PetalBot) - - regex: 'Mozilla.{1,100}Mobile.{1,100}(AspiegelBot|PetalBot)' - family_replacement: 'Spider' - - - regex: 'AspiegelBot|PetalBot' - family_replacement: 'Spider' - - # Basilisk - - regex: '(Firefox)/(\d+)\.(\d+) Basilisk/(\d+)' - family_replacement: 'Basilisk' - - # Pale Moon - - regex: '(PaleMoon)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Pale Moon' - - # Firefox - - regex: '(Fennec)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)' - family_replacement: 'Firefox Mobile' - - regex: '(Fennec)/(\d+)\.(\d+)(pre)' - family_replacement: 'Firefox Mobile' - - regex: '(Fennec)/(\d+)\.(\d+)' - family_replacement: 'Firefox Mobile' - - regex: '(?:Mobile|Tablet);.{0,200}(Firefox)/(\d+)\.(\d+)' - family_replacement: 'Firefox Mobile' - - 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]*)' - family_replacement: 'Firefox Alpha' - - regex: '(Firefox)-(?:\d+\.\d+|)/(\d+)\.(\d+)(b\d+[a-z]*)' - family_replacement: 'Firefox Beta' - - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)([ab]\d+[a-z]*|)' - family_replacement: 'Firefox ($1)' - - regex: '(Firefox).{0,200}Tablet browser (\d+)\.(\d+)\.(\d+)' - family_replacement: 'MicroB' - - regex: '(MozillaDeveloperPreview)/(\d+)\.(\d+)([ab]\d+[a-z]*|)' - - regex: '(FxiOS)/(\d+)\.(\d+)(\.(\d+)|)(\.(\d+)|)' - family_replacement: 'Firefox iOS' - - # e.g.: Flock/2.0b2 - - regex: '(Flock)/(\d+)\.(\d+)(b\d+?)' - - # RockMelt - - regex: '(RockMelt)/(\d+)\.(\d+)\.(\d+)' - - # e.g.: Fennec/0.9pre - - regex: '(Navigator)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Netscape' - - - regex: '(Navigator)/(\d+)\.(\d+)([ab]\d+)' - family_replacement: 'Netscape' - - - regex: '(Netscape6)/(\d+)\.(\d+)\.?([ab]?\d+|)' - family_replacement: 'Netscape' - - - regex: '(MyIBrow)/(\d+)\.(\d+)' - family_replacement: 'My Internet Browser' - - # UC Browser - # we need check it before opera. In other case case UC Browser detected look like Opera Mini - - regex: '(UC? ?Browser|UCWEB|U3)[ /]?(\d+)\.(\d+)\.(\d+)' - family_replacement: 'UC Browser' - - # 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).{0,200}Version/(\d+)\.(\d+)(?:\.(\d+)|)' - - regex: '(Opera Mini)(?:/att|)/?(\d+|)(?:\.(\d+)|)(?:\.(\d+)|)' - - regex: '(Opera)/.{1,100}Opera Mobi.{1,100}Version/(\d+)\.(\d+)' - family_replacement: 'Opera Mobile' - - regex: '(Opera)/(\d+)\.(\d+).{1,100}Opera Mobi' - family_replacement: 'Opera Mobile' - - regex: 'Opera Mobi.{1,100}(Opera)(?:/|\s+)(\d+)\.(\d+)' - family_replacement: 'Opera Mobile' - - regex: 'Opera Mobi' - family_replacement: 'Opera Mobile' - - regex: '(Opera)/9.80.{0,200}Version/(\d+)\.(\d+)(?:\.(\d+)|)' - - # Opera 14 for Android uses a WebKit render engine. - - regex: '(?:Mobile Safari).{1,300}(OPR)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Opera Mobile' - - # Opera >=15 for Desktop is similar to Chrome but includes an "OPR" Version string. - - regex: '(?:Chrome).{1,300}(OPR)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Opera' - - # Opera Coast - - regex: '(Coast)/(\d+).(\d+).(\d+)' - family_replacement: 'Opera Coast' - - # Opera Mini for iOS (from version 8.0.0) - - regex: '(OPiOS)/(\d+).(\d+).(\d+)' - family_replacement: 'Opera Mini' - - # Opera Neon - - regex: 'Chrome/.{1,200}( MMS)/(\d+).(\d+).(\d+)' - family_replacement: 'Opera Neon' - - # Palm WebOS looks a lot like Safari. - - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'webOS Browser' - - # LuaKit has no version info. - # http://luakit.org/projects/luakit/ - - regex: '(luakit)' - family_replacement: 'LuaKit' - - # Snowshoe - - regex: '(Snowshoe)/(\d+)\.(\d+).(\d+)' - - # Lightning (for Thunderbird) - # http://www.mozilla.org/projects/calendar/lightning/ - - regex: 'Gecko/\d+ (Lightning)/(\d+)\.(\d+)\.?((?:[ab]?\d+[a-z]*)|(?:\d*))' - - # Swiftfox - - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre|)) \(Swiftfox\)' - family_replacement: 'Swiftfox' - - regex: '(Firefox)/(\d+)\.(\d+)([ab]\d+[a-z]*|) \(Swiftfox\)' - family_replacement: 'Swiftfox' - - # Rekonq - - 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+)|)' - family_replacement: 'Conkeror' - - # catches lower case konqueror - - regex: '(konqueror)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Konqueror' - - - regex: '(WeTab)-Browser' - - - regex: '(Comodo_Dragon)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Comodo Dragon' - - - regex: '(Symphony) (\d+).(\d+)' - - - regex: 'PLAYSTATION 3.{1,200}WebKit' - family_replacement: 'NetFront NX' - - regex: 'PLAYSTATION 3' - family_replacement: 'NetFront' - - regex: '(PlayStation Portable)' - family_replacement: 'NetFront' - - regex: '(PlayStation Vita)' - family_replacement: 'NetFront NX' - - - regex: 'AppleWebKit.{1,200} (NX)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'NetFront NX' - - regex: '(Nintendo 3DS)' - family_replacement: 'NetFront NX' - - # Amazon Silk, should go before Safari and Chrome Mobile - - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|)' - family_replacement: 'Amazon Silk' - - # @ref: http://www.puffinbrowser.com - - regex: '(Puffin)/(\d+)\.(\d+)(?:\.(\d+)|)' - - # Edge Mobile - - regex: 'Windows Phone .{0,200}(Edge)/(\d+)\.(\d+)' - family_replacement: 'Edge Mobile' - - regex: '(EdgiOS|EdgA)/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Edge Mobile' - - # Oculus Browser, should go before Samsung Internet - - regex: '(OculusBrowser)/(\d+)\.(\d+).0.0(?:\.([0-9\-]+)|)' - family_replacement: 'Oculus Browser' - - # Samsung Internet (based on Chrome, but lacking some features) - - regex: '(SamsungBrowser)/(\d+)\.(\d+)' - family_replacement: 'Samsung Internet' - - # Seznam.cz browser (based on WebKit) - - 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+)|)' - family_replacement: 'Coc Coc' - - # Baidu Browsers (desktop spoofs chrome & IE, explorer is mobile) - - 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+)|)' - 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' - - # TopBuzz Android must go before Chrome Mobile WebView - - regex: '(TopBuzz)/(\d+).(\d+).(\d+)' - family_replacement: 'TopBuzz' - - # Google Search App on Android, eg: - - regex: 'Mozilla.{1,200}Android.{1,200}(GSA)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Google' - - # QQ Browsers - - regex: '(MQQBrowser/Mini)(?:(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - family_replacement: 'QQ Browser Mini' - - regex: '(MQQBrowser)(?:/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - family_replacement: 'QQ Browser Mobile' - - regex: '(QQBrowser)(?:/(\d+)(?:\.(\d+)\.(\d+)(?:\.(\d+)|)|)|)' - family_replacement: 'QQ Browser' - - # DuckDuckGo - - regex: 'Mobile.{0,200}(DuckDuckGo)/(\d+)' - family_replacement: 'DuckDuckGo Mobile' - - # Tenta Browser - - regex: '(Tenta/)(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Tenta Browser' - - # Chrome Mobile - - regex: 'Version/.{1,300}(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile WebView' - - regex: '; wv\).{1,300}(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile WebView' - - regex: '(CrMo)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile' - - regex: '(CriOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile iOS' - - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+) Mobile(?:[ /]|$)' - family_replacement: 'Chrome Mobile' + - regex: Mozilla.{1,200}Mobile.{1,100}(Instagram).(\d+)\.(\d+)\.(\d+) + - regex: Mozilla.{1,200}Mobile.{1,100}(Flipboard).(\d+)\.(\d+)\.(\d+) + - regex: Mozilla.{1,200}Mobile.{1,100}(Flipboard-Briefing).(\d+)\.(\d+)\.(\d+) + - regex: Mozilla.{1,200}Mobile.{1,100}(Onefootball)\/Android.(\d+)\.(\d+)\.(\d+) + - regex: (Snapchat)\/(\d+)\.(\d+)\.(\d+)\.(\d+) + - regex: (Twitter for (?:iPhone|iPad)|TwitterAndroid)(?:\/(\d+)\.(\d+)|) + family_replacement: Twitter + - regex: Mozilla.{1,200}Mobile.{1,100}(Phantom\/ios|Phantom\/android).(\d+)\.(\d+)\.(\d+) + family_replacement: Phantom + - regex: Mozilla.{1,100}Mobile.{1,100}(AspiegelBot|PetalBot) + family_replacement: Spider + - regex: AspiegelBot|PetalBot + family_replacement: Spider + - regex: (Firefox)/(\d+)\.(\d+) Basilisk/(\d+) + family_replacement: Basilisk + - regex: (PaleMoon)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Pale Moon + - regex: (Fennec)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*) + family_replacement: Firefox Mobile + - regex: (Fennec)/(\d+)\.(\d+)(pre) + family_replacement: Firefox Mobile + - regex: (Fennec)/(\d+)\.(\d+) + family_replacement: Firefox Mobile + - regex: (?:Mobile|Tablet);.{0,200}(Firefox)/(\d+)\.(\d+) + family_replacement: Firefox Mobile + - 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]*) + family_replacement: Firefox Alpha + - regex: (Firefox)-(?:\d+\.\d+|)/(\d+)\.(\d+)(b\d+[a-z]*) + family_replacement: Firefox Beta + - regex: (Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)([ab]\d+[a-z]*|) + family_replacement: Firefox ($1) + - regex: (Firefox).{0,200}Tablet browser (\d+)\.(\d+)\.(\d+) + family_replacement: MicroB + - regex: (MozillaDeveloperPreview)/(\d+)\.(\d+)([ab]\d+[a-z]*|) + - regex: (FxiOS)/(\d+)\.(\d+)(\.(\d+)|)(\.(\d+)|) + family_replacement: Firefox iOS + - regex: (Flock)/(\d+)\.(\d+)(b\d+?) + - regex: (RockMelt)/(\d+)\.(\d+)\.(\d+) + - regex: (Navigator)/(\d+)\.(\d+)\.(\d+) + family_replacement: Netscape + - regex: (Navigator)/(\d+)\.(\d+)([ab]\d+) + family_replacement: Netscape + - regex: (Netscape6)/(\d+)\.(\d+)\.?([ab]?\d+|) + family_replacement: Netscape + - regex: (MyIBrow)/(\d+)\.(\d+) + family_replacement: My Internet Browser + - regex: (UC? ?Browser|UCWEB|U3)[ /]?(\d+)\.(\d+)\.(\d+) + family_replacement: UC Browser + - regex: (Opera Tablet).{0,200}Version/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: (Opera Mini)(?:/att|)/?(\d+|)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (Opera)/.{1,100}Opera Mobi.{1,100}Version/(\d+)\.(\d+) + family_replacement: Opera Mobile + - regex: (Opera)/(\d+)\.(\d+).{1,100}Opera Mobi + family_replacement: Opera Mobile + - regex: Opera Mobi.{1,100}(Opera)(?:/|\s+)(\d+)\.(\d+) + family_replacement: Opera Mobile + - regex: Opera Mobi + family_replacement: Opera Mobile + - regex: (Opera)/9.80.{0,200}Version/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: (?:Mobile Safari).{1,300}(OPR)/(\d+)\.(\d+)\.(\d+) + family_replacement: Opera Mobile + - regex: (?:Chrome).{1,300}(OPR)/(\d+)\.(\d+)\.(\d+) + family_replacement: Opera + - regex: (Coast)/(\d+).(\d+).(\d+) + family_replacement: Opera Coast + - regex: (OPiOS)/(\d+).(\d+).(\d+) + family_replacement: Opera Mini + - regex: Chrome/.{1,200}( MMS)/(\d+).(\d+).(\d+) + family_replacement: Opera Neon + - regex: (hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: webOS Browser + - regex: (luakit) + family_replacement: LuaKit + - regex: (Snowshoe)/(\d+)\.(\d+).(\d+) + - regex: Gecko/\d+ (Lightning)/(\d+)\.(\d+)\.?((?:[ab]?\d+[a-z]*)|(?:\d*)) + - regex: (Firefox)/(\d+)\.(\d+)\.(\d+(?:pre|)) \(Swiftfox\) + family_replacement: Swiftfox + - regex: (Firefox)/(\d+)\.(\d+)([ab]\d+[a-z]*|) \(Swiftfox\) + family_replacement: Swiftfox + - regex: (rekonq)/(\d+)\.(\d+)(?:\.(\d+)|) Safari + family_replacement: Rekonq + - regex: rekonq + family_replacement: Rekonq + - regex: (conkeror|Conkeror)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Conkeror + - regex: (konqueror)/(\d+)\.(\d+)\.(\d+) + family_replacement: Konqueror + - regex: (WeTab)-Browser + - regex: (Comodo_Dragon)/(\d+)\.(\d+)\.(\d+) + family_replacement: Comodo Dragon + - regex: (Symphony) (\d+).(\d+) + - regex: PLAYSTATION 3.{1,200}WebKit + family_replacement: NetFront NX + - regex: PLAYSTATION 3 + family_replacement: NetFront + - regex: (PlayStation Portable) + family_replacement: NetFront + - regex: (PlayStation Vita) + family_replacement: NetFront NX + - regex: AppleWebKit.{1,200} (NX)/(\d+)\.(\d+)\.(\d+) + family_replacement: NetFront NX + - regex: (Nintendo 3DS) + family_replacement: NetFront NX + - regex: (HuaweiBrowser)/(\d+)\.(\d+)\.(\d+)\.\d+ + family_replacement: Huawei Browser + - regex: (AVG)/(\d+)\.(\d+)\.(\d+)\.\d+ + family_replacement: AVG + - regex: (AvastSecureBrowser|Avast)/(\d+)\.(\d+)\.(\d+) + family_replacement: Avast Secure Browser + - regex: (Instabridge)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (AlohaBrowser)/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Aloha Browser + - regex: ((?:B|b)rave(?:\sChrome)?)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Brave + - regex: (Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|) + family_replacement: Amazon Silk + - regex: (Puffin)/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: Windows Phone .{0,200}(Edge)/(\d+)\.(\d+) + family_replacement: Edge Mobile + - regex: (EdgiOS|EdgA)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Edge Mobile + - regex: (OculusBrowser)/(\d+)\.(\d+).0.0(?:\.([0-9\-]+)|) + family_replacement: Oculus Browser + - regex: (SamsungBrowser)/(\d+)\.(\d+) + family_replacement: Samsung Internet + - regex: (SznProhlizec)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Seznam prohlížeč + - regex: (coc_coc_browser)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Coc Coc + - regex: (baidubrowser)[/\s](\d+)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Baidu Browser + - regex: (FlyFlow)/(\d+)\.(\d+) + family_replacement: Baidu Explorer + - regex: (MxBrowser)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Maxthon + - regex: (Crosswalk)/(\d+)\.(\d+)\.(\d+)\.(\d+) + - regex: (Line)/(\d+)\.(\d+)\.(\d+) + family_replacement: LINE + - regex: (MiuiBrowser)/(\d+)\.(\d+)\.(\d+) + family_replacement: MiuiBrowser + - regex: (Mint Browser)/(\d+)\.(\d+)\.(\d+) + family_replacement: Mint Browser + - regex: (TopBuzz)/(\d+).(\d+).(\d+) + family_replacement: TopBuzz + - regex: Mozilla.{1,200}Android.{1,200}(GSA)/(\d+)\.(\d+)\.(\d+) + family_replacement: Google + - regex: (MQQBrowser/Mini)(?:(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + family_replacement: QQ Browser Mini + - regex: (MQQBrowser)(?:/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + family_replacement: QQ Browser Mobile + - regex: (QQBrowser)(?:/(\d+)(?:\.(\d+)\.(\d+)(?:\.(\d+)|)|)|) + family_replacement: QQ Browser + - regex: Mozilla.{1,200}Mobile.{1,100}(DuckDuckGo)/(\d+) + family_replacement: DuckDuckGo Mobile + - regex: Mozilla.{1,200}(DuckDuckGo)/(\d+) + family_replacement: DuckDuckGo + - regex: Mozilla.{1,200}Mobile.{1,100}(Ddg)/(\d+)(?:\.(\d+)|) + family_replacement: DuckDuckGo Mobile + - regex: Mozilla.{1,200}(Ddg)/(\d+)(?:\.(\d+)|) + family_replacement: DuckDuckGo + - regex: (Tenta/)(\d+)\.(\d+)\.(\d+) + family_replacement: Tenta Browser + - regex: (Ecosia) ios@(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Ecosia iOS + - regex: (Ecosia) android@(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Ecosia Android + - regex: Version/.{1,300}(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+) + family_replacement: Chrome Mobile WebView + - regex: ; wv\).{1,300}(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+) + family_replacement: Chrome Mobile WebView + - regex: (CrMo)/(\d+)\.(\d+)\.(\d+)\.(\d+) + family_replacement: Chrome Mobile + - regex: (CriOS)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Chrome Mobile iOS + - regex: (Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+) Mobile(?:[ /]|$) + family_replacement: Chrome Mobile - regex: ' Mobile .{1,300}(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile' - - # Chrome Frame must come before MSIE. - - regex: '(chromeframe)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Frame' - - # Tizen Browser (second case included in browser/major.minor regex) - - regex: '(SLP Browser)/(\d+)\.(\d+)' - family_replacement: 'Tizen Browser' - - # Sogou Explorer 2.X - - regex: '(SE 2\.X) MetaSr (\d+)\.(\d+)' - family_replacement: 'Sogou Explorer' - - # Rackspace Monitoring - - regex: '(Rackspace Monitoring)/(\d+)\.(\d+)' - family_replacement: 'RackspaceBot' - - # PRTG Network Monitoring - - regex: '(PRTG Network Monitor)' - - # PyAMF - - regex: '(PyAMF)/(\d+)\.(\d+)\.(\d+)' - - # Yandex Browser - - regex: '(YaBrowser)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Yandex Browser' - - # Mail.ru Amigo/Internet Browser (Chromium-based) - - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+).{0,100} MRCHROME' - family_replacement: 'Mail.ru Chromium Browser' - - # AOL Browser (IE-based) - - regex: '(AOL) (\d+)\.(\d+); AOLBuild (\d+)' - - # Podcast catcher Applications using iTunes - - regex: '(PodCruncher|Downcast)[ /]?(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|)' - - # Box Notes https://www.box.com/resources/downloads - # Must be before Electron + family_replacement: Chrome Mobile + - regex: (chromeframe)/(\d+)\.(\d+)\.(\d+) + family_replacement: Chrome Frame + - regex: (SLP Browser)/(\d+)\.(\d+) + family_replacement: Tizen Browser + - regex: (SE 2\.X) MetaSr (\d+)\.(\d+) + family_replacement: Sogou Explorer + - regex: (Rackspace Monitoring)/(\d+)\.(\d+) + family_replacement: RackspaceBot + - regex: (PRTG Network Monitor) + - regex: (PyAMF)/(\d+)\.(\d+)\.(\d+) + - regex: (YaBrowser)/(\d+)\.(\d+)\.(\d+) + family_replacement: Yandex Browser + - regex: (YaSearchBrowser)/(\d+)\.(\d+)\.(\d+) + family_replacement: Yandex Browser + - regex: (Chrome)/(\d+)\.(\d+)\.(\d+).{0,100} MRCHROME + family_replacement: Mail.ru Chromium Browser + - regex: (AOL) (\d+)\.(\d+); AOLBuild (\d+) + - regex: (PodCruncher|Downcast)[ /]?(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) - regex: ' (BoxNotes)/(\d+)\.(\d+)\.(\d+)' - - # Whale - - regex: '(Whale)/(\d+)\.(\d+)\.(\d+)\.(\d+) Mobile(?:[ /]|$)' - family_replacement: 'Whale' - - - regex: '(Whale)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Whale' - - # 1Password - - regex: '(1Password)/(\d+)\.(\d+)\.(\d+)' - - # Ghost - # @ref: http://www.ghost.org - - regex: '(Ghost)/(\d+)\.(\d+)\.(\d+)' - - # Palo Alto GlobalProtect Linux - - regex: 'PAN (GlobalProtect)/(\d+)\.(\d+)\.(\d+) .{1,100} \(X11; Linux x86_64\)' - - # Surveyon https://www.surveyon.com/ - - regex: '^(surveyon)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Surveyon' - - #### END SPECIAL CASES TOP #### - - #### MAIN CASES - this catches > 50% of all browsers #### - - - # Slack desktop client (needs to be before Apple Mail, Electron, and Chrome as it gets wrongly detected on Mac OS otherwise) - - regex: '(Slack_SSB)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Slack Desktop Client' - - # HipChat provides a version on Mac, but not on Windows. - # Needs to be before Chrome on Windows, and AppleMail on Mac. - - regex: '(HipChat)/?(\d+|)' - family_replacement: 'HipChat Desktop Client' - - # Browser/major_version.minor_version.beta_version - - regex: '\b(MobileIron|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Spotify|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\.Browser|Bunjalloo|Google Earth|Raven for Mac|Openwave|MacOutlook|Electron|OktaMobile)/(\d+)\.(\d+)\.(\d+)' - - # Outlook 2007 - - regex: 'Microsoft Office Outlook 12\.\d+\.\d+|MSOffice 12' - family_replacement: 'Outlook' + - regex: (Whale)/(\d+)\.(\d+)\.(\d+)\.(\d+) Mobile(?:[ /]|$) + family_replacement: Whale + - regex: (Whale)/(\d+)\.(\d+)\.(\d+) + family_replacement: Whale + - regex: (1Password)/(\d+)\.(\d+)\.(\d+) + - regex: (Ghost)/(\d+)\.(\d+)\.(\d+) + - regex: PAN (GlobalProtect)/(\d+)\.(\d+)\.(\d+) .{1,100} \(X11; Linux x86_64\) + - regex: ^(surveyon)/(\d+)\.(\d+)\.(\d+) + family_replacement: Surveyon + - regex: (Slack_SSB)/(\d+)\.(\d+)\.(\d+) + family_replacement: Slack Desktop Client + - regex: (HipChat)/?(\d+|) + family_replacement: HipChat Desktop Client + - regex: \b(MobileIron|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Spotify|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera + Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\.Browser|Bunjalloo|Google Earth|Raven + for Mac|Openwave|MacOutlook|Electron|OktaMobile)/(\d+)\.(\d+)\.(\d+) + - regex: Microsoft Office Outlook 12\.\d+\.\d+|MSOffice 12 + family_replacement: Outlook v1_replacement: '2007' - - # Outlook 2010 - - regex: 'Microsoft Outlook 14\.\d+\.\d+|MSOffice 14' - family_replacement: 'Outlook' + - regex: Microsoft Outlook 14\.\d+\.\d+|MSOffice 14 + family_replacement: Outlook v1_replacement: '2010' - - # Outlook 2013 - - regex: 'Microsoft Outlook 15\.\d+\.\d+' - family_replacement: 'Outlook' + - regex: Microsoft Outlook 15\.\d+\.\d+ + family_replacement: Outlook v1_replacement: '2013' - - # Outlook 2016 - - regex: 'Microsoft Outlook (?:Mail )?16\.\d+\.\d+|MSOffice 16' - family_replacement: 'Outlook' + - regex: Microsoft Outlook (?:Mail )?16\.\d+\.\d+|MSOffice 16 + 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+)|)' - - # Thunderbird - - regex: '(Thunderbird)/(\d+)\.(\d+)(?:\.(\d+(?:pre|))|)' - family_replacement: 'Thunderbird' - - # Postbox - - regex: '(Postbox)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Postbox' - - # Barca - - regex: '(Barca(?:Pro)?)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Barca' - - # Lotus Notes - - regex: '(Lotus-Notes)/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Lotus Notes' - - # Superhuman Mail Client - # @ref: https://www.superhuman.com - - regex: 'Superhuman' - family_replacement: 'Superhuman' - - # Vivaldi uses "Vivaldi" - - regex: '(Vivaldi)/(\d+)\.(\d+)\.(\d+)' - - # Edge/major_version.minor_version - # Edge with chromium Edg/major_version.minor_version.patch.minor_patch - - regex: '(Edge?)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|)' - family_replacement: 'Edge' - - # Brave Browser https://brave.com/ - - regex: '(brave)/(\d+)\.(\d+)\.(\d+) Chrome' - family_replacement: 'Brave' - - # Iron Browser ~since version 50 - - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+)[\d.]{0,100} Iron[^/]' - family_replacement: 'Iron' - - # Dolphin Browser - # @ref: http://www.dolphin.com + - regex: Microsoft Office (Word) 2014 + - regex: Outlook-Express\/7\.0 + family_replacement: Windows Live Mail + - regex: (Airmail) (\d+)\.(\d+)(?:\.(\d+)|) + - regex: (Thunderbird)/(\d+)\.(\d+)(?:\.(\d+(?:pre|))|) + family_replacement: Thunderbird + - regex: (Postbox)/(\d+)\.(\d+)\.(\d+) + family_replacement: Postbox + - regex: (Barca(?:Pro)?)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Barca + - regex: (Lotus-Notes)/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Lotus Notes + - regex: Superhuman + family_replacement: Superhuman + - regex: (Vivaldi)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (Edge?)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|) + family_replacement: Edge + - regex: (Chrome)/(\d+)\.(\d+)\.(\d+)[\d.]{0,100} Iron[^/] + family_replacement: Iron - 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+)|)' - - # Evolution Mail CardDav/CalDav integration - - regex: '(Evolution)/(\d+)\.(\d+)\.(\d+\.\d+)' - - # Roundcube Mail CardDav plugin - - 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+)|)' - - # Chrome/Chromium/major_version.minor_version - - regex: '(Chromium|Chrome)/(\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - - ########## - # IE Mobile needs to happen before Android to catch cases such as: - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; ANZ821)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Orange)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Vodafone)... - ########## - - # IE Mobile - - regex: '(IEMobile)[ /](\d+)\.(\d+)' - family_replacement: 'IE Mobile' - - # Baca Berita App News Reader - - regex: '(BacaBerita App)\/(\d+)\.(\d+)\.(\d+)' - - # 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: '^(bPod|Player FM) BMID/(\S+)' + - regex: (HeadlessChrome)(?:/(\d+)\.(\d+)\.(\d+)|) + - regex: (Evolution)/(\d+)\.(\d+)\.(\d+\.\d+) + - regex: (RCM CardDAV plugin)/(\d+)\.(\d+)\.(\d+(?:-dev|)) + - 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: (Chromium|Chrome)/(\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (IEMobile)[ /](\d+)\.(\d+) + family_replacement: IE Mobile + - regex: (BacaBerita App)\/(\d+)\.(\d+)\.(\d+) + - 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: ^(bPod|Player FM) BMID/(\S+) - regex: '^(Podcast ?Addict)/v(\d+) ' - regex: '^(Podcast ?Addict) ' - family_replacement: 'PodcastAddict' - - regex: '(Replay) AV' - - regex: '(VOX) Music Player' - - 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: '(Player FM|Pocket Casts|DoggCatcher|Spotify|MediaMonkey|MediaGo|BashPodder)' - - regex: '(QuickTime)\.(\d+)\.(\d+)\.(\d+)' - - regex: '(Kinoma)(\d+)' - - regex: '(Fancy) Cloud Music (\d+)\.(\d+)' - family_replacement: 'FancyMusic' - - regex: 'EspnDownloadManager' - family_replacement: 'ESPN' + family_replacement: PodcastAddict + - regex: (Replay) AV + - regex: (VOX) Music Player + - 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: (Player FM|Pocket Casts|DoggCatcher|Spotify|MediaMonkey|MediaGo|BashPodder) + - regex: (QuickTime)\.(\d+)\.(\d+)\.(\d+) + - regex: (Kinoma)(\d+) + - regex: (Fancy) Cloud Music (\d+)\.(\d+) + family_replacement: FancyMusic + - regex: EspnDownloadManager + family_replacement: ESPN - 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: '(WMPlayer)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - - regex: '^(Lavf)' - family_replacement: 'WMPlayer' - - 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: '^(Stitcher)/iOS' - - regex: '^(Stitcher)/Android' - - regex: '^(VLC) .{0,200}version (\d+)\.(\d+)\.(\d+)' + - regex: (podracer|jPodder) v ?(\d+)\.(\d+)(?:\.(\d+)|) + - regex: (ZDM)/(\d+)\.(\d+)[; ]? + - regex: (Zune|BeyondPod) (\d+)(?:\.(\d+)|)[\);] + - regex: (WMPlayer)/(\d+)\.(\d+)\.(\d+)\.(\d+) + - regex: ^(Lavf) + family_replacement: WMPlayer + - 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: ^(Stitcher)/iOS + - regex: ^(Stitcher)/Android + - regex: ^(VLC) .{0,200}version (\d+)\.(\d+)\.(\d+) - regex: ' (VLC) for' - - regex: '(vlc)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'VLC' - - regex: '^(foobar)\S{1,10}/(\d+)\.(\d+|)\.?([\da-z]+|)' - - regex: '^(Clementine)\S{1,10} (\d+)\.(\d+|)\.?(\d+|)' - - regex: '(amarok)/(\d+)\.(\d+|)\.?(\d+|)' - 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+)|)' - - # Kindle WebKit - - regex: '(Kindle)/(\d+)\.(\d+)' - - # weird android UAs - - regex: '(Android) Donut' + - regex: (vlc)/(\d+)\.(\d+)\.(\d+) + family_replacement: VLC + - regex: ^(foobar)\S{1,10}/(\d+)\.(\d+|)\.?([\da-z]+|) + - regex: ^(Clementine)\S{1,10} (\d+)\.(\d+|)\.?(\d+|) + - regex: (amarok)/(\d+)\.(\d+|)\.?(\d+|) + family_replacement: Amarok + - regex: (Custom)-Feed Reader + - regex: (iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) + (\d+)\.(\d+)\.(\d+) + - regex: (iCab|Lunascape|Opera|Android|Jasmine|Polaris|Microsoft SkyDriveSync|The + Bat!) (\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (Kindle)/(\d+)\.(\d+) + - regex: (Android) Donut v1_replacement: '1' v2_replacement: '2' - - - regex: '(Android) Eclair' + - regex: (Android) Eclair v1_replacement: '2' v2_replacement: '1' - - - regex: '(Android) Froyo' + - regex: (Android) Froyo v1_replacement: '2' v2_replacement: '2' - - - regex: '(Android) Gingerbread' + - regex: (Android) Gingerbread v1_replacement: '2' v2_replacement: '3' - - - regex: '(Android) Honeycomb' + - regex: (Android) Honeycomb v1_replacement: '3' - - # desktop mode - # http://www.anandtech.com/show/3982/windows-phone-7-review - - regex: '(MSIE) (\d+)\.(\d+).{0,100}XBLWP7' - family_replacement: 'IE Large Screen' - - # Nextcloud desktop sync client - - regex: '(Nextcloud)' - - # Generic mirall client - - regex: '(mirall)/(\d+)\.(\d+)\.(\d+)' - - # Nextcloud/Owncloud android client - - regex: '(ownCloud-android)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Owncloud' - - # Skype for Business - - regex: '(OC)/(\d+)\.(\d+)\.(\d+)\.(\d+) \(Skype for Business\)' - family_replacement: 'Skype' - - # OpenVAS Scanner - - regex: '(OpenVAS)(?:-VT)?(?:[ \/](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - family_replacement: 'OpenVAS Scanner' - - # AnyConnect - - regex: '(AnyConnect)\/(\d+)(?:\.(\d+)(?:\.(\d+)|)|)' - - # Monitis - - regex: 'compatible; monitis' - family_replacement: 'Monitis' - - #### END MAIN CASES #### - - #### SPECIAL CASES #### - - regex: '(Obigo)InternetBrowser' - - regex: '(Obigo)\-Browser' - - regex: '(Obigo|OBIGO)[^\d]*(\d+)(?:.(\d+)|)' - family_replacement: 'Obigo' - - - regex: '(MAXTHON|Maxthon) (\d+)\.(\d+)' - family_replacement: 'Maxthon' - - regex: '(Maxthon|MyIE2|Uzbl|Shiira)' + - regex: (MSIE) (\d+)\.(\d+).{0,100}XBLWP7 + family_replacement: IE Large Screen + - regex: (Nextcloud) + - regex: (mirall)/(\d+)\.(\d+)\.(\d+) + - regex: (ownCloud-android)/(\d+)\.(\d+)\.(\d+) + family_replacement: Owncloud + - regex: (OC)/(\d+)\.(\d+)\.(\d+)\.(\d+) \(Skype for Business\) + family_replacement: Skype + - regex: (OpenVAS)(?:-VT)?(?:[ \/](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + family_replacement: OpenVAS Scanner + - regex: (AnyConnect)\/(\d+)(?:\.(\d+)(?:\.(\d+)|)|) + - regex: compatible; monitis + family_replacement: Monitis + - regex: (Obigo)InternetBrowser + - regex: (Obigo)\-Browser + - regex: (Obigo|OBIGO)[^\d]*(\d+)(?:.(\d+)|) + family_replacement: Obigo + - regex: (MAXTHON|Maxthon) (\d+)\.(\d+) + family_replacement: Maxthon + - regex: (Maxthon|MyIE2|Uzbl|Shiira) v1_replacement: '0' - - - regex: '(BrowseX) \((\d+)\.(\d+)\.(\d+)' - - - regex: '(NCSA_Mosaic)/(\d+)\.(\d+)' - family_replacement: 'NCSA Mosaic' - - # Polaris/d.d is above - - regex: '(POLARIS)/(\d+)\.(\d+)' - family_replacement: 'Polaris' - - regex: '(Embider)/(\d+)\.(\d+)' - family_replacement: 'Polaris' - - - regex: '(BonEcho)/(\d+)\.(\d+)\.?([ab]?\d+|)' - family_replacement: 'Bon Echo' - - # topbuzz on IOS - - regex: '(TopBuzz) com.alex.NewsMaster/(\d+).(\d+).(\d+)' - family_replacement: 'TopBuzz' - - regex: '(TopBuzz) com.mobilesrepublic.newsrepublic/(\d+).(\d+).(\d+)' - family_replacement: 'TopBuzz' - - regex: '(TopBuzz) com.topbuzz.videoen/(\d+).(\d+).(\d+)' - family_replacement: 'TopBuzz' - - # @note: iOS / OSX Applications - - regex: '(iPod|iPhone|iPad).{1,200}GSA/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|) Mobile' - family_replacement: 'Google' - - regex: '(iPod|iPhone|iPad).{1,200}Version/(\d+)\.(\d+)(?:\.(\d+)|).{1,200}[ +]Safari' - family_replacement: 'Mobile Safari' - - regex: '(iPod|iPod touch|iPhone|iPad);.{0,30}CPU.{0,30}OS[ +](\d+)_(\d+)(?:_(\d+)|).{0,30} AppleNews\/\d+\.\d+(?:\.\d+|)' - family_replacement: 'Mobile Safari UI/WKWebView' - - regex: '(iPod|iPhone|iPad).{1,200}Version/(\d+)\.(\d+)(?:\.(\d+)|)' - family_replacement: 'Mobile Safari UI/WKWebView' - - regex: '(iPod|iPod touch|iPhone|iPad).{0,200} Safari' - family_replacement: 'Mobile Safari' - - regex: '(iPod|iPod touch|iPhone|iPad)' - family_replacement: 'Mobile Safari UI/WKWebView' - - regex: '(Watch)(\d+),(\d+)' - family_replacement: 'Apple $1 App' - - ########################## - # Outlook on iOS >= 2.62.0 - ########################## - - regex: '(Outlook-iOS)/\d+\.\d+\.prod\.iphone \((\d+)\.(\d+)\.(\d+)\)' - - - regex: '(AvantGo) (\d+).(\d+)' - - - regex: '(OneBrowser)/(\d+).(\d+)' - family_replacement: 'ONE Browser' - - - regex: '(Avant)' + - regex: (BrowseX) \((\d+)\.(\d+)\.(\d+) + - regex: (NCSA_Mosaic)/(\d+)\.(\d+) + family_replacement: NCSA Mosaic + - regex: (POLARIS)/(\d+)\.(\d+) + family_replacement: Polaris + - regex: (Embider)/(\d+)\.(\d+) + family_replacement: Polaris + - regex: (BonEcho)/(\d+)\.(\d+)\.?([ab]?\d+|) + family_replacement: Bon Echo + - regex: (TopBuzz) com.alex.NewsMaster/(\d+).(\d+).(\d+) + family_replacement: TopBuzz + - regex: (TopBuzz) com.mobilesrepublic.newsrepublic/(\d+).(\d+).(\d+) + family_replacement: TopBuzz + - regex: (TopBuzz) com.topbuzz.videoen/(\d+).(\d+).(\d+) + family_replacement: TopBuzz + - regex: (iPod|iPhone|iPad).{1,200}GSA/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|) Mobile + family_replacement: Google + - regex: (iPod|iPhone|iPad).{1,200}Version/(\d+)\.(\d+)(?:\.(\d+)|).{1,200}[ +]Safari + family_replacement: Mobile Safari + - regex: (iPod|iPod touch|iPhone|iPad);.{0,30}CPU.{0,30}OS[ +](\d+)_(\d+)(?:_(\d+)|).{0,30} + AppleNews\/\d+\.\d+(?:\.\d+|) + family_replacement: Mobile Safari UI/WKWebView + - regex: (iPod|iPhone|iPad).{1,200}Version/(\d+)\.(\d+)(?:\.(\d+)|) + family_replacement: Mobile Safari UI/WKWebView + - regex: (iPod|iPod touch|iPhone|iPad).{0,200} Safari + family_replacement: Mobile Safari + - regex: (iPod|iPod touch|iPhone|iPad) + family_replacement: Mobile Safari UI/WKWebView + - regex: (Watch)(\d+),(\d+) + family_replacement: Apple $1 App + - regex: (Outlook-iOS)/\d+\.\d+\.prod\.iphone \((\d+)\.(\d+)\.(\d+)\) + - regex: (AvantGo) (\d+).(\d+) + - regex: (OneBrowser)/(\d+).(\d+) + family_replacement: ONE Browser + - regex: (Avant) v1_replacement: '1' - - # This is the Tesla Model S (see similar entry in device parsers) - - regex: '(QtCarBrowser)' + - regex: (QtCarBrowser) v1_replacement: '1' - - - regex: '^(iBrowser/Mini)(\d+).(\d+)' - family_replacement: 'iBrowser Mini' - - regex: '^(iBrowser|iRAPP)/(\d+).(\d+)' - - # nokia browsers - # based on: http://www.developer.nokia.com/Community/Wiki/User-Agent_headers_for_Nokia_devices - - regex: '^(Nokia)' - family_replacement: 'Nokia Services (WAP) Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+).(\d+)\.(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+).(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(BrowserNG)/(\d+)\.(\d+).(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(Series60)/5\.0' - family_replacement: 'Nokia Browser' + - regex: ^(iBrowser/Mini)(\d+).(\d+) + family_replacement: iBrowser Mini + - regex: ^(iBrowser|iRAPP)/(\d+).(\d+) + - regex: ^(Nokia) + family_replacement: Nokia Services (WAP) Browser + - regex: (NokiaBrowser)/(\d+)\.(\d+).(\d+)\.(\d+) + family_replacement: Nokia Browser + - regex: (NokiaBrowser)/(\d+)\.(\d+).(\d+) + family_replacement: Nokia Browser + - regex: (NokiaBrowser)/(\d+)\.(\d+) + family_replacement: Nokia Browser + - regex: (BrowserNG)/(\d+)\.(\d+).(\d+) + family_replacement: Nokia Browser + - regex: (Series60)/5\.0 + family_replacement: Nokia Browser v1_replacement: '7' v2_replacement: '0' - - regex: '(Series60)/(\d+)\.(\d+)' - family_replacement: 'Nokia OSS Browser' - - regex: '(S40OviBrowser)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Ovi Browser' - - regex: '(Nokia)[EN]?(\d+)' - - # BlackBerry devices - - regex: '(PlayBook).{1,200}RIM Tablet OS (\d+)\.(\d+)\.(\d+)' - family_replacement: 'BlackBerry WebKit' - - regex: '(Black[bB]erry|BB10).{1,200}Version/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'BlackBerry WebKit' - - regex: '(Black[bB]erry)\s?(\d+)' - family_replacement: 'BlackBerry' - - - regex: '(OmniWeb)/v(\d+)\.(\d+)' - - - regex: '(Blazer)/(\d+)\.(\d+)' - family_replacement: 'Palm Blazer' - - - regex: '(Pre)/(\d+)\.(\d+)' - family_replacement: 'Palm Pre' - - # fork of Links - - regex: '(ELinks)/(\d+)\.(\d+)' - - regex: '(ELinks) \((\d+)\.(\d+)' - - regex: '(Links) \((\d+)\.(\d+)' - - - regex: '(QtWeb) Internet Browser/(\d+)\.(\d+)' - - # Phantomjs, should go before Safari - - regex: '(PhantomJS)/(\d+)\.(\d+)\.(\d+)' - - # WebKit Nightly - - regex: '(AppleWebKit)/(\d+)(?:\.(\d+)|)\+ .{0,200} Safari' - family_replacement: 'WebKit Nightly' - - # Safari - - regex: '(Version)/(\d+)\.(\d+)(?:\.(\d+)|).{0,100}Safari/' - family_replacement: 'Safari' - # Safari didn't provide "Version/d.d.d" prior to 3.0 - - regex: '(Safari)/\d+' - - - regex: '(OLPC)/Update(\d+)\.(\d+)' - - - regex: '(OLPC)/Update()\.(\d+)' + - regex: (Series60)/(\d+)\.(\d+) + family_replacement: Nokia OSS Browser + - regex: (S40OviBrowser)/(\d+)\.(\d+)\.(\d+)\.(\d+) + family_replacement: Ovi Browser + - regex: (Nokia)[EN]?(\d+) + - regex: (PlayBook).{1,200}RIM Tablet OS (\d+)\.(\d+)\.(\d+) + family_replacement: BlackBerry WebKit + - regex: (Black[bB]erry|BB10).{1,200}Version/(\d+)\.(\d+)\.(\d+) + family_replacement: BlackBerry WebKit + - regex: (Black[bB]erry)\s?(\d+) + family_replacement: BlackBerry + - regex: (OmniWeb)/v(\d+)\.(\d+) + - regex: (Blazer)/(\d+)\.(\d+) + family_replacement: Palm Blazer + - regex: (Pre)/(\d+)\.(\d+) + family_replacement: Palm Pre + - regex: (ELinks)/(\d+)\.(\d+) + - regex: (ELinks) \((\d+)\.(\d+) + - regex: (Links) \((\d+)\.(\d+) + - regex: (QtWeb) Internet Browser/(\d+)\.(\d+) + - regex: (PhantomJS)/(\d+)\.(\d+)\.(\d+) + - regex: (AppleWebKit)/(\d+)(?:\.(\d+)|)\+ .{0,200} Safari + family_replacement: WebKit Nightly + - regex: (Version)/(\d+)\.(\d+)(?:\.(\d+)|).{0,100}Safari/ + family_replacement: Safari + - regex: (Safari)/\d+ + - regex: (OLPC)/Update(\d+)\.(\d+) + - regex: (OLPC)/Update()\.(\d+) v1_replacement: '0' - - - regex: '(SEMC\-Browser)/(\d+)\.(\d+)' - - - regex: '(Teleca)' - family_replacement: 'Teleca Browser' - - - regex: '(Phantom)/V(\d+)\.(\d+)' - family_replacement: 'Phantom Browser' - - - regex: '(Trident)/(7|8)\.(0)' - family_replacement: 'IE' + - regex: (SEMC\-Browser)/(\d+)\.(\d+) + - regex: (Teleca) + family_replacement: Teleca Browser + - regex: (Phantom)/V(\d+)\.(\d+) + family_replacement: Phantom Browser + - regex: (Trident)/(7|8)\.(0) + family_replacement: IE v1_replacement: '11' - - - regex: '(Trident)/(6)\.(0)' - family_replacement: 'IE' + - regex: (Trident)/(6)\.(0) + family_replacement: IE v1_replacement: '10' - - - regex: '(Trident)/(5)\.(0)' - family_replacement: 'IE' + - regex: (Trident)/(5)\.(0) + family_replacement: IE v1_replacement: '9' - - - regex: '(Trident)/(4)\.(0)' - family_replacement: 'IE' + - regex: (Trident)/(4)\.(0) + family_replacement: IE v1_replacement: '8' - - # Espial - - regex: '(Espial)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - - # Apple Mail - - # apple mail - not directly detectable, have it after Safari stuff - - regex: '(AppleWebKit)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Apple Mail' - - # AFTER THE EDGE CASES ABOVE! - # AFTER IE11 - # BEFORE all other IE - - regex: '(Firefox)/(\d+)\.(\d+)(?:\.(\d+)|$)' - - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*|)' - - - - regex: '([MS]?IE) (\d+)\.(\d+)' - family_replacement: 'IE' - - - regex: '(python-requests)/(\d+)\.(\d+)' - family_replacement: 'Python Requests' - - # headless user-agents - - regex: '\b(Windows-Update-Agent|WindowsPowerShell|Microsoft-CryptoAPI|SophosUpdateManager|SophosAgent|Debian APT-HTTP|Ubuntu APT-HTTP|libcurl-agent|libwww-perl|urlgrabber|curl|PycURL|Wget|wget2|aria2|Axel|OpenBSD ftp|lftp|jupdate|insomnia|fetch libfetch|akka-http|got|CloudCockpitBackend|ReactorNetty|axios|Jersey|Vert.x-WebClient|Apache-CXF|Go-CF-client|go-resty|AHC|HTTPie)(?:[ /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)' - - # CloudFoundry - - regex: '^(cf)\/(\d+)\.(\d+)\.(\S+)' - family_replacement: 'CloudFoundry' - - # SAP Leonardo - - regex: '^(sap-leonardo-iot-sdk-nodejs) \/ (\d+)\.(\d+)\.(\d+)' - - # SAP Netweaver Application Server - - regex: '^(SAP NetWeaver Application Server) \(1.0;(\d{1})(\d{2})\)' - - # HttpClient - - regex: '^(\w+-HTTPClient)\/(\d+)\.(\d+)-(\S+)' - family_replacement: 'HTTPClient' - - # go-cli - - regex: '^(go-cli)\s(\d+)\.(\d+).(\S+)' - - # Other Clients with the pattern /[v].[.] - - regex: '^(Java-EurekaClient|Java-EurekaClient-Replication|HTTPClient|lua-resty-http)\/v?(\d+)\.(\d+)\.?(\d*)' - - ## Clints with the pattern - - regex: '^(ping-service|sap xsuaa|Node-oauth|Site24x7|SAP CPI|JAEGER_SECURITY)' - - # Asynchronous HTTP Client/Server for asyncio and Python (https://aiohttp.readthedocs.io/) - - regex: '(Python/3\.\d{1,3} aiohttp)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Python aiohttp' - - - regex: '(Java)[/ ]?\d{1}\.(\d+)\.(\d+)[_-]*([a-zA-Z0-9]+|)' - - - regex: '(Java)[/ ]?(\d+)\.(\d+)\.(\d+)' - - # minio-go (https://github.com/minio/minio-go) - - regex: '(minio-go)/v(\d+)\.(\d+)\.(\d+)' - - # ureq - minimal request library in rust (https://github.com/algesten/ureq) - - regex: '^(ureq)[/ ](\d+)\.(\d+).(\d+)' - - # http.rb - HTTP (The Gem! a.k.a. http.rb) - a fast Ruby HTTP client - # (https://github.com/httprb/http/blob/3aa7470288deb81f7d7b982c1e2381871049dcbb/lib/http/request.rb#L27) - - regex: '^(http\.rb)/(\d+)\.(\d+).(\d+)' - - # Guzzle, PHP HTTP client (https://docs.guzzlephp.org/) - - regex: '^(GuzzleHttp)/(\d+)\.(\d+).(\d+)' - - # lorien/grab - Web Scraping Framework (https://github.com/lorien/grab) - - regex: '^(grab)\b' - - # Cloud Storage Clients - - regex: '^(Cyberduck)/(\d+)\.(\d+)\.(\d+)(?:\.\d+|)' - - regex: '^(S3 Browser) (\d+)[.-](\d+)[.-](\d+)(?:\s*https?://s3browser\.com|)' - - regex: '(S3Gof3r)' - # IBM COS (Cloud Object Storage) API - - regex: '\b(ibm-cos-sdk-(?:core|java|js|python))/(\d+)\.(\d+)(?:\.(\d+)|)' - # rusoto - Rusoto - AWS SDK for Rust - https://github.com/rusoto/rusoto - - regex: '^(rusoto)/(\d+)\.(\d+)\.(\d+)' - # rclone - rsync for cloud storage - https://rclone.org/ - - regex: '^(rclone)/v(\d+)\.(\d+)' - - # Roku Digital-Video-Players https://www.roku.com/ - - regex: '^(Roku)/DVP-(\d+)\.(\d+)' - - # Kurio App News Reader https://kurio.co.id/ - - regex: '(Kurio)\/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Kurio App' - - # Box Drive and Box Sync https://www.box.com/resources/downloads + - regex: (Espial)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (AppleWebKit)/(\d+)\.(\d+)\.(\d+) + family_replacement: Apple Mail + - regex: (Firefox)/(\d+)\.(\d+)(?:\.(\d+)|$) + - regex: (Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*|) + - regex: ([MS]?IE) (\d+)\.(\d+) + family_replacement: IE + - regex: (python-requests)/(\d+)\.(\d+) + family_replacement: Python Requests + - regex: \b(Windows-Update-Agent|WindowsPowerShell|Microsoft-CryptoAPI|SophosUpdateManager|SophosAgent|Debian + APT-HTTP|Ubuntu APT-HTTP|libcurl-agent|libwww-perl|urlgrabber|curl|PycURL|Wget|wget2|aria2|Axel|OpenBSD + ftp|lftp|jupdate|insomnia|fetch libfetch|akka-http|got|CloudCockpitBackend|ReactorNetty|axios|Jersey|Vert.x-WebClient|Apache-CXF|Go-CF-client|go-resty|AHC|HTTPie)(?:[ + /](\d+)(?:\.(\d+)|)(?:\.(\d+)|)|) + - regex: ^(cf)\/(\d+)\.(\d+)\.(\S+) + family_replacement: CloudFoundry + - regex: ^(sap-leonardo-iot-sdk-nodejs) \/ (\d+)\.(\d+)\.(\d+) + - regex: ^(SAP NetWeaver Application Server) \(1.0;(\d{1})(\d{2})\) + - regex: ^(\w+-HTTPClient)\/(\d+)\.(\d+)-(\S+) + family_replacement: HTTPClient + - regex: ^(go-cli)\s(\d+)\.(\d+).(\S+) + - regex: ^(Java-EurekaClient|Java-EurekaClient-Replication|HTTPClient|lua-resty-http)\/v?(\d+)\.(\d+)\.?(\d*) + - regex: ^(ping-service|sap xsuaa|Node-oauth|Site24x7|SAP CPI|JAEGER_SECURITY) + - regex: (Python/3\.\d{1,3} aiohttp)/(\d+)\.(\d+)\.(\d+) + family_replacement: Python aiohttp + - regex: (Java)[/ ]?\d{1}\.(\d+)\.(\d+)[_-]*([a-zA-Z0-9]+|) + - regex: (Java)[/ ]?(\d+)\.(\d+)\.(\d+) + - regex: (minio-go)/v(\d+)\.(\d+)\.(\d+) + - regex: ^(ureq)[/ ](\d+)\.(\d+).(\d+) + - regex: ^(http\.rb)/(\d+)\.(\d+).(\d+) + - regex: ^(GuzzleHttp)/(\d+)\.(\d+).(\d+) + - regex: ^(grab)\b + - regex: ^(Cyberduck)/(\d+)\.(\d+)\.(\d+)(?:\.\d+|) + - regex: ^(S3 Browser) (\d+)[.-](\d+)[.-](\d+)(?:\s*https?://s3browser\.com|) + - regex: (S3Gof3r) + - regex: \b(ibm-cos-sdk-(?:core|java|js|python))/(\d+)\.(\d+)(?:\.(\d+)|) + - regex: ^(rusoto)/(\d+)\.(\d+)\.(\d+) + - regex: ^(rclone)/v(\d+)\.(\d+) + - regex: ^(Roku)/DVP-(\d+)\.(\d+) + - regex: (Kurio)\/(\d+)\.(\d+)\.(\d+) + family_replacement: Kurio App - 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' - - # Transmit (https://library.panic.com/transmit/) - - regex: '(Transmit)/(\d+)\.(\d+)\.(\d+)' - - # Download Master (https://downloadmaster.ru/) - - regex: '(Download Master)' - - # HTTrack crawler - - regex: '\b(HTTrack) (\d+)\.(\d+)(?:[\.\-](\d+)|)' - - # SerenityOS (https://serenityos.org) - # https://github.com/SerenityOS/serenity/blob/2e1bbcb0faeae92d7595b8e0b022a8cdcecca07e/Userland/Libraries/LibWeb/Loader/ResourceLoader.h#L27 - - regex: 'SerenityOS' - family_replacement: 'SerenityOS Browser' - + - regex: ^(ViaFree|Viafree)-(?:tvOS-)?[A-Z]{2}/(\d+)\.(\d+)\.(\d+) + family_replacement: ViaFree + - regex: (Transmit)/(\d+)\.(\d+)\.(\d+) + - regex: (Download Master) + - regex: \b(HTTrack) (\d+)\.(\d+)(?:[\.\-](\d+)|) + - regex: (Ladybird)\/(\d+)\.(\d+) + - regex: (MullvadBrowser)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|) os_parsers: - ########## - # HbbTV vendors - ########## - - # starts with the easy one : Panasonic seems consistent across years, hope it will continue - #HbbTV/1.1.1 (;Panasonic;VIERA 2011;f.532;0071-0802 2000-0000;) - #HbbTV/1.1.1 (;Panasonic;VIERA 2012;1.261;0071-3103 2000-0000;) - #HbbTV/1.2.1 (;Panasonic;VIERA 2013;3.672;4101-0003 0002-0000;) - #- regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Panasonic);VIERA ([0-9]{4});' - - # Sony is consistent too but do not place year like the other - # Opera/9.80 (Linux armv7l; HbbTV/1.1.1 (; Sony; KDL32W650A; PKG3.211EUA; 2013;); ) Presto/2.12.362 Version/12.11 - # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Sony; KDL40HX751; PKG1.902EUA; 2012;);; en) Presto/2.10.250 Version/11.60 - # Opera/9.80 (Linux mips; U; HbbTV/1.1.1 (; Sony; KDL22EX320; PKG4.017EUA; 2011;);; en) Presto/2.7.61 Version/11.00 - #- regex: 'HbbTV/\d+\.\d+\.\d+ \(; (Sony);.{0,200};.{0,200}; ([0-9]{4});\)' - - - # LG is consistent too, but we need to add manually the year model - #Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.1+ (KHTML, like Gecko) Safari/537.1+ HbbTV/1.1.1 ( ;LGE ;NetCast 4.0 ;03.20.30 ;1.0M ;) - #Mozilla/5.0 (DirectFB; Linux armv7l) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ HbbTV/1.1.1 ( ;LGE ;NetCast 3.0 ;1.0 ;1.0M ;) - - regex: 'HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 4.0' + - regex: HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 4.0 os_v1_replacement: '2013' - - regex: 'HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 3.0' + - regex: HbbTV/\d+\.\d+\.\d+ \( ;(LG)E ;NetCast 3.0 os_v1_replacement: '2012' - - # Samsung is on its way of normalizing their user-agent - # HbbTV/1.1.1 (;Samsung;SmartTV2013;T-FXPDEUC-1102.2;;) WebKit - # HbbTV/1.1.1 (;Samsung;SmartTV2013;T-MST12DEUC-1102.1;;) WebKit - # HbbTV/1.1.1 (;Samsung;SmartTV2012;;;) WebKit - # HbbTV/1.1.1 (;;;;;) Maple_2011 - - regex: 'HbbTV/1.1.1 \(;;;;;\) Maple_2011' - os_replacement: 'Samsung' + - regex: HbbTV/1.1.1 \(;;;;;\) Maple_2011 + os_replacement: Samsung os_v1_replacement: '2011' - # manage the two models of 2013 - - regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.{0,200}FXPDEUC' - os_v2_replacement: 'UE40F7000' - - regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.{0,200}MST12DEUC' - os_v2_replacement: 'UE32F4500' - # generic Samsung (works starting in 2012) - #- regex: 'HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});' - - # 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);.{0,200}NETTV/4' + - regex: HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.{0,200}FXPDEUC + os_v2_replacement: UE40F7000 + - regex: HbbTV/\d+\.\d+\.\d+ \(;(Samsung);SmartTV([0-9]{4});.{0,200}MST12DEUC + os_v2_replacement: UE32F4500 + - regex: HbbTV/1\.1\.1 \(; (Philips);.{0,200}NETTV/4 os_v1_replacement: '2013' - - regex: 'HbbTV/1\.1\.1 \(; (Philips);.{0,200}NETTV/3' + - regex: HbbTV/1\.1\.1 \(; (Philips);.{0,200}NETTV/3 os_v1_replacement: '2012' - - regex: 'HbbTV/1\.1\.1 \(; (Philips);.{0,200}NETTV/2' + - regex: HbbTV/1\.1\.1 \(; (Philips);.{0,200}NETTV/2 os_v1_replacement: '2011' - - # the HbbTV emulator developers use HbbTV/1.1.1 (;;;;;) firetv-firefox-plugin 1.1.20 - - regex: 'HbbTV/\d+\.\d+\.\d+.{0,100}(firetv)-firefox-plugin (\d+).(\d+).(\d+)' - os_replacement: 'FireHbbTV' - - # generic HbbTV, hoping to catch manufacturer name (always after 2nd comma) and the first string that looks like a 2011-2019 year - - regex: 'HbbTV/\d+\.\d+\.\d+ \(.{0,30}; ?([a-zA-Z]+) ?;.{0,30}(201[1-9]).{0,30}\)' - - # aspiegel.com spider (owned by Huawei, later renamed PetalBot) - - regex: 'AspiegelBot|PetalBot' - os_replacement: 'Other' - - ########## - # @note: Windows Phone needs to come before Windows NT 6.1 {0,2}and* before Android to catch cases such as: - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; ANZ821)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Orange)... - # Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920; Vodafone)... - ########## - - - regex: '(Windows Phone) (?:OS[ /])?(\d+)\.(\d+)' - - # Again a MS-special one: iPhone.{0,200}Outlook-iOS-Android/x.x is erroneously detected as Android - - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone)[ +]+(\d+)[_\.](\d+)(?:[_\.](\d+)|).{0,100}Outlook-iOS-Android' - os_replacement: 'iOS' - - # Special case for old ArcGIS Mobile products - - regex: 'ArcGIS\.?(iOS|Android)-\d+\.\d+(?:\.\d+|)(?:[^\/]{1,50}|)\/(\d+)(?:\.(\d+)(?:\.(\d+)|)|)' - - # Special case for new ArcGIS Mobile products - - regex: 'ArcGISRuntime-(?:Android|iOS)\/\d+\.\d+(?:\.\d+|) \((Android|iOS) (\d+)(?:\.(\d+)(?:\.(\d+)|)|);' - - ########## - # Android - # can actually detect rooted android os. do we care? - ########## - - regex: '(Android)[ \-/](\d+)(?:\.(\d+)|)(?:[.\-]([a-z0-9]+)|)' - - - regex: '(Android) Donut' + - regex: HbbTV/\d+\.\d+\.\d+.{0,100}(firetv)-firefox-plugin (\d+).(\d+).(\d+) + os_replacement: FireHbbTV + - regex: HbbTV/\d+\.\d+\.\d+ \(.{0,30}; ?([a-zA-Z]+) ?;.{0,30}(201[1-9]).{0,30}\) + - regex: AspiegelBot|PetalBot + os_replacement: Other + - regex: (Windows Phone) (?:OS[ /])?(\d+)\.(\d+) + - regex: (CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone)[ +]+(\d+)[_\.](\d+)(?:[_\.](\d+)|).{0,100}Outlook-iOS-Android + os_replacement: iOS + - regex: ArcGIS\.?(iOS|Android)-\d+\.\d+(?:\.\d+|)(?:[^\/]{1,50}|)\/(\d+)(?:\.(\d+)(?:\.(\d+)|)|) + - regex: ArcGISRuntime-(?:Android|iOS)\/\d+\.\d+(?:\.\d+|) \((Android|iOS) (\d+)(?:\.(\d+)(?:\.(\d+)|)|); + - regex: (Android) (\d+)(?:\.(\d+)).*CrKey + os_replacement: Chromecast Android + - regex: Fuchsia.*(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+)|)|) + os_replacement: Chromecast Fuchsia + - regex: Linux.*(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+)|)|).*DeviceType/SmartSpeaker + os_replacement: Chromecast SmartSpeaker + - regex: Linux.*(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+)|)|) + os_replacement: Chromecast Linux + - regex: (Android)[ \-/](\d+)(?:\.(\d+)|)(?:[.\-]([a-z0-9]+)|) + - regex: (Android) Donut os_v1_replacement: '1' os_v2_replacement: '2' - - - regex: '(Android) Eclair' + - regex: (Android) Eclair os_v1_replacement: '2' os_v2_replacement: '1' - - - regex: '(Android) Froyo' + - regex: (Android) Froyo os_v1_replacement: '2' os_v2_replacement: '2' - - - regex: '(Android) Gingerbread' + - regex: (Android) Gingerbread os_v1_replacement: '2' os_v2_replacement: '3' - - - regex: '(Android) Honeycomb' + - regex: (Android) Honeycomb os_v1_replacement: '3' - - # Android 9; Android 10; - - regex: '(Android) (\d+);' + - regex: (Android) (\d+); - regex: '(Android): (\d+)(?:\.(\d+)(?:\.(\d+)|)|);' - - # UCWEB - - regex: '^UCWEB.{0,200}; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]{1,100})|);' - os_replacement: 'Android' - - regex: '^UCWEB.{0,200}; (iPad|iPh|iPd) OS (\d+)_(\d+)(?:_(\d+)|);' - os_replacement: 'iOS' - - regex: '^UCWEB.{0,200}; (wds) (\d+)\.(\d+)(?:\.(\d+)|);' - os_replacement: 'Windows Phone' - # JUC - - regex: '^(JUC).{0,200}; ?U; ?(?:Android|)(\d+)\.(\d+)(?:[\.\-]([a-z0-9]{1,100})|)' - os_replacement: 'Android' - - # Salesforce - - regex: '(android)\s(?:mobile\/)(\d+)(?:\.(\d+)(?:\.(\d+)|)|)' - os_replacement: 'Android' - - ########## - # Meta Quest - ########## - - regex: 'Quest' - os_replacement: 'Android' - - ########## - # Kindle Android - ########## - - regex: '(Silk-Accelerated=[a-z]{4,5})' - os_replacement: 'Android' - - # Citrix Chrome App on Chrome OS - # Note, this needs to come before the windows parsers as the app doesn't - # 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+).{0,100}Chrome.{0,100}(?:CitrixChromeApp)$' - os_replacement: 'Chrome OS' - - ########## - # Windows - # http://en.wikipedia.org/wiki/Windows_NT#Releases - # possibility of false positive when different marketing names share same NT kernel - # e.g. windows server 2003 and windows xp - # lots of ua strings have Windows NT 4.1 !?!?!?!? !?!? !? !????!?! !!! ??? !?!?! ? - # (very) roughly ordered in terms of frequency of occurence of regex (win xp currently most frequent, etc) - ########## - - # ie mobile desktop mode - # spoofs nt 6.1. must come before windows 7 - - regex: '(XBLWP7)' - os_replacement: 'Windows Phone' - - # @note: This needs to come before Windows NT 6.1 - - regex: '(Windows ?Mobile)' - os_replacement: 'Windows Mobile' - - - regex: '(Windows 10)' - os_replacement: 'Windows' + - regex: ^UCWEB.{0,200}; (Adr) (\d+)\.(\d+)(?:[.\-]([a-z0-9]{1,100})|); + os_replacement: Android + - regex: ^UCWEB.{0,200}; (iPad|iPh|iPd) OS (\d+)_(\d+)(?:_(\d+)|); + os_replacement: iOS + - regex: ^UCWEB.{0,200}; (wds) (\d+)\.(\d+)(?:\.(\d+)|); + os_replacement: Windows Phone + - regex: ^(JUC).{0,200}; ?U; ?(?:Android|)(\d+)\.(\d+)(?:[\.\-]([a-z0-9]{1,100})|) + os_replacement: Android + - regex: (android)\s(?:mobile\/)(\d+)(?:\.(\d+)(?:\.(\d+)|)|) + os_replacement: Android + - regex: Quest + os_replacement: Android + - regex: (Silk-Accelerated=[a-z]{4,5}) + os_replacement: Android + - regex: (x86_64|aarch64)\ (\d+)\.(\d+)\.(\d+).{0,100}Chrome.{0,100}(?:CitrixChromeApp)$ + os_replacement: Chrome OS + - regex: (XBLWP7) + os_replacement: Windows Phone + - regex: (Windows ?Mobile) + os_replacement: Windows Mobile + - regex: (Windows 10) + os_replacement: Windows os_v1_replacement: '10' - - - regex: '(Windows (?:NT 5\.2|NT 5\.1))' - os_replacement: 'Windows' - os_v1_replacement: 'XP' - - - regex: '(Win(?:dows NT |32NT\/)6\.1)' - os_replacement: 'Windows' + - regex: (Windows (?:NT 5\.2|NT 5\.1)) + os_replacement: Windows + os_v1_replacement: XP + - regex: (Win(?:dows NT |32NT\/)6\.1) + os_replacement: Windows os_v1_replacement: '7' - - - regex: '(Win(?:dows NT |32NT\/)6\.0)' - os_replacement: 'Windows' - os_v1_replacement: 'Vista' - - - regex: '(Win 9x 4\.90)' - os_replacement: 'Windows' - os_v1_replacement: 'ME' - - - regex: '(Windows NT 6\.2; ARM;)' - os_replacement: 'Windows' - os_v1_replacement: 'RT' - - - regex: '(Win(?:dows NT |32NT\/)6\.2)' - os_replacement: 'Windows' + - regex: (Win(?:dows NT |32NT\/)6\.0) + os_replacement: Windows + os_v1_replacement: Vista + - regex: (Win 9x 4\.90) + os_replacement: Windows + os_v1_replacement: ME + - regex: (Windows NT 6\.2; ARM;) + os_replacement: Windows + os_v1_replacement: RT + - regex: (Win(?:dows NT |32NT\/)6\.2) + os_replacement: Windows os_v1_replacement: '8' - - - regex: '(Windows NT 6\.3; ARM;)' - os_replacement: 'Windows' - os_v1_replacement: 'RT 8' + - regex: (Windows NT 6\.3; ARM;) + os_replacement: Windows + os_v1_replacement: RT 8 os_v2_replacement: '1' - - - regex: '(Win(?:dows NT |32NT\/)6\.3)' - os_replacement: 'Windows' + - regex: (Win(?:dows NT |32NT\/)6\.3) + os_replacement: Windows os_v1_replacement: '8' os_v2_replacement: '1' - - - regex: '(Win(?:dows NT |32NT\/)6\.4)' - os_replacement: 'Windows' + - regex: (Win(?:dows NT |32NT\/)6\.4) + os_replacement: Windows os_v1_replacement: '10' - - - regex: '(Windows NT 10\.0)' - os_replacement: 'Windows' + - regex: (Windows NT 10\.0) + os_replacement: Windows os_v1_replacement: '10' - - - regex: '(Windows NT 5\.0)' - os_replacement: 'Windows' + - regex: (Windows NT 5\.0) + os_replacement: Windows os_v1_replacement: '2000' - - - regex: '(WinNT4.0)' - os_replacement: 'Windows' - os_v1_replacement: 'NT 4.0' - - - regex: '(Windows ?CE)' - os_replacement: 'Windows' - os_v1_replacement: 'CE' - - - regex: 'Win(?:dows)? ?(95|98|3.1|NT|ME|2000|XP|Vista|7|CE)' - os_replacement: 'Windows' - os_v1_replacement: '$1' - - - regex: 'Win16' - os_replacement: 'Windows' + - regex: (WinNT4.0) + os_replacement: Windows + os_v1_replacement: NT 4.0 + - regex: (Windows ?CE) + os_replacement: Windows + os_v1_replacement: CE + - regex: Win(?:dows)? ?(95|98|3.1|NT|ME|2000|XP|Vista|7|CE) + os_replacement: Windows + os_v1_replacement: $1 + - regex: Win16 + os_replacement: Windows os_v1_replacement: '3.1' - - - regex: 'Win32' - os_replacement: 'Windows' + - regex: Win32 + os_replacement: Windows os_v1_replacement: '95' - - # Box apps (Drive, Sync, Notes) on Windows https://www.box.com/resources/downloads - - regex: '^Box.{0,200}Windows/([\d.]+);' - os_replacement: 'Windows' - os_v1_replacement: '$1' - - ########## - # Tizen OS from Samsung - # spoofs Android so pushing it above - ########## - - regex: '(Tizen)[/ ](\d+)\.(\d+)' - - ########## - # Mac OS - # @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)' - os_replacement: 'Mac OS X' - - regex: 'Mac OS X\s.{1,50}\s(\d+).(\d+).(\d+)' - os_replacement: 'Mac OS X' - os_v1_replacement: '$1' - os_v2_replacement: '$2' - os_v3_replacement: '$3' - # Leopard + - regex: ^Box.{0,200}Windows/([\d.]+); + os_replacement: Windows + os_v1_replacement: $1 + - regex: (Tizen)[/ ](\d+)\.(\d+) + - regex: Intel Mac OS X.+(CriOS|EdgiOS)/\d+ + os_replacement: iOS + - regex: ((?:Mac[ +]?|; )OS[ +]X)[\s+/](?:(\d+)[_.](\d+)(?:[_.](\d+)|)|Mach-O) + os_replacement: Mac OS X + - regex: Mac OS X\s.{1,50}\s(\d+).(\d+).(\d+) + os_replacement: Mac OS X + os_v1_replacement: $1 + os_v2_replacement: $2 + os_v3_replacement: $3 - regex: ' (Dar)(win)/(9).(\d+).{0,100}\((?:i386|x86_64|Power Macintosh)\)' - os_replacement: 'Mac OS X' + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '5' - # Snow Leopard - regex: ' (Dar)(win)/(10).(\d+).{0,100}\((?:i386|x86_64)\)' - os_replacement: 'Mac OS X' + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '6' - # Lion - regex: ' (Dar)(win)/(11).(\d+).{0,100}\((?:i386|x86_64)\)' - os_replacement: 'Mac OS X' + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '7' - # Mountain Lion - regex: ' (Dar)(win)/(12).(\d+).{0,100}\((?:i386|x86_64)\)' - os_replacement: 'Mac OS X' + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '8' - # Mavericks - regex: ' (Dar)(win)/(13).(\d+).{0,100}\((?:i386|x86_64)\)' - os_replacement: 'Mac OS X' + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '9' - # Yosemite is Darwin/14.x but patch versions are inconsistent in the Darwin string; - # more accurately covered by CFNetwork regexes downstream - - # IE on Mac doesn't specify version number - - regex: 'Mac_PowerPC' - os_replacement: 'Mac OS' - - # builds before tiger don't seem to specify version? - - # ios devices spoof (mac os x), so including intel/ppc prefixes - - regex: '(?:PPC|Intel) (Mac OS X)' - - # Box Drive and Box Sync on Mac OS X use OSX version numbers, not Darwin - - regex: '^Box.{0,200};(Darwin)/(10)\.(1\d)(?:\.(\d+)|)' - os_replacement: 'Mac OS X' - - ########## - # iOS - # 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+)|)' - os_replacement: 'ATV OS X' - - - regex: '(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(\d+)[_\.](\d+)(?:[_\.](\d+)|)' - os_replacement: 'iOS' - - # remaining cases are mostly only opera uas, so catch opera as to not catch iphone spoofs - - regex: '(iPhone|iPad|iPod); Opera' - os_replacement: 'iOS' - - # few more stragglers - - regex: '(iPhone|iPad|iPod).{0,100}Mac OS X.{0,100}Version/(\d+)\.(\d+)' - os_replacement: 'iOS' - - # CFNetwork/Darwin - The specific CFNetwork or Darwin version determines - # whether the os maps to Mac OS, or iOS, or just Darwin. - # See: http://user-agents.me/cfnetwork-version-list - - regex: '(CFNetwork)/(5)48\.0\.3.{0,100} Darwin/11\.0\.0' - os_replacement: 'iOS' - - regex: '(CFNetwork)/(5)48\.(0)\.4.{0,100} Darwin/(1)1\.0\.0' - os_replacement: 'iOS' - - regex: '(CFNetwork)/(5)48\.(1)\.4' - os_replacement: 'iOS' - - regex: '(CFNetwork)/(4)85\.1(3)\.9' - os_replacement: 'iOS' - - regex: '(CFNetwork)/(6)09\.(1)\.4' - os_replacement: 'iOS' - - regex: '(CFNetwork)/(6)(0)9' - os_replacement: 'iOS' - - regex: '(CFNetwork)/6(7)2\.(1)\.13' - os_replacement: 'iOS' - - regex: '(CFNetwork)/6(7)2\.(1)\.(1)4' - os_replacement: 'iOS' - - regex: '(CF)(Network)/6(7)(2)\.1\.15' - os_replacement: 'iOS' + - regex: Mac_PowerPC + os_replacement: Mac OS + - regex: (?:PPC|Intel) (Mac OS X) + - regex: ^Box.{0,200};(Darwin)/(10)\.(1\d)(?:\.(\d+)|) + os_replacement: Mac OS X + - regex: (Apple\s?TV)(?:/(\d+)\.(\d+)|) + os_replacement: ATV OS X + - regex: (CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(\d+)[_\.](\d+)(?:[_\.](\d+)|) + os_replacement: iOS + - regex: (iPhone|iPad|iPod); Opera + os_replacement: iOS + - regex: (iPhone|iPad|iPod).{0,100}Mac OS X.{0,100}Version/(\d+)\.(\d+) + os_replacement: iOS + - regex: (CFNetwork)/(5)48\.0\.3.{0,100} Darwin/11\.0\.0 + os_replacement: iOS + - regex: (CFNetwork)/(5)48\.(0)\.4.{0,100} Darwin/(1)1\.0\.0 + os_replacement: iOS + - regex: (CFNetwork)/(5)48\.(1)\.4 + os_replacement: iOS + - regex: (CFNetwork)/(4)85\.1(3)\.9 + os_replacement: iOS + - regex: (CFNetwork)/(6)09\.(1)\.4 + os_replacement: iOS + - regex: (CFNetwork)/(6)(0)9 + os_replacement: iOS + - regex: (CFNetwork)/6(7)2\.(1)\.13 + os_replacement: iOS + - regex: (CFNetwork)/6(7)2\.(1)\.(1)4 + os_replacement: iOS + - regex: (CF)(Network)/6(7)(2)\.1\.15 + os_replacement: iOS os_v1_replacement: '7' os_v2_replacement: '1' - - regex: '(CFNetwork)/6(7)2\.(0)\.(?:2|8)' - os_replacement: 'iOS' - - regex: '(CFNetwork)/709\.1' - os_replacement: 'iOS' + - regex: (CFNetwork)/6(7)2\.(0)\.(?:2|8) + os_replacement: iOS + - regex: (CFNetwork)/709\.1 + os_replacement: iOS os_v1_replacement: '8' - os_v2_replacement: '0.b5' - - regex: '(CF)(Network)/711\.(\d)' - os_replacement: 'iOS' + os_v2_replacement: 0.b5 + - regex: (CF)(Network)/711\.(\d) + os_replacement: iOS os_v1_replacement: '8' - - regex: '(CF)(Network)/(720)\.(\d)' - os_replacement: 'Mac OS X' + - regex: (CF)(Network)/(720)\.(\d) + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '10' - - regex: '(CF)(Network)/(760)\.(\d)' - os_replacement: 'Mac OS X' + - regex: (CF)(Network)/(760)\.(\d) + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '11' - - regex: 'CFNetwork/7.{0,100} Darwin/15\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/7.{0,100} Darwin/15\.4\.\d+ + os_replacement: iOS os_v1_replacement: '9' os_v2_replacement: '3' os_v3_replacement: '1' - - regex: 'CFNetwork/7.{0,100} Darwin/15\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/7.{0,100} Darwin/15\.5\.\d+ + os_replacement: iOS os_v1_replacement: '9' os_v2_replacement: '3' os_v3_replacement: '2' - - regex: 'CFNetwork/7.{0,100} Darwin/15\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/7.{0,100} Darwin/15\.6\.\d+ + os_replacement: iOS os_v1_replacement: '9' os_v2_replacement: '3' os_v3_replacement: '5' - - regex: '(CF)(Network)/758\.(\d)' - os_replacement: 'iOS' + - regex: (CF)(Network)/758\.(\d) + os_replacement: iOS os_v1_replacement: '9' - - regex: 'CFNetwork/808\.3 Darwin/16\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/808\.3 Darwin/16\.3\.\d+ + os_replacement: iOS os_v1_replacement: '10' os_v2_replacement: '2' os_v3_replacement: '1' - - regex: '(CF)(Network)/808\.(\d)' - os_replacement: 'iOS' + - regex: (CF)(Network)/808\.(\d) + os_replacement: iOS os_v1_replacement: '10' - - ########## - # CFNetwork macOS Apps (must be before CFNetwork iOS Apps - # @ref: https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history - ########## - - regex: 'CFNetwork/.{0,100} Darwin/17\.\d+.{0,100}\(x86_64\)' - os_replacement: 'Mac OS X' + - regex: CFNetwork/.{0,100} Darwin/17\.\d+.{0,100}\(x86_64\) + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '13' - - regex: 'CFNetwork/.{0,100} Darwin/16\.\d+.{0,100}\(x86_64\)' - os_replacement: 'Mac OS X' + - regex: CFNetwork/.{0,100} Darwin/16\.\d+.{0,100}\(x86_64\) + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '12' - - regex: 'CFNetwork/8.{0,100} Darwin/15\.\d+.{0,100}\(x86_64\)' - os_replacement: 'Mac OS X' + - regex: CFNetwork/8.{0,100} Darwin/15\.\d+.{0,100}\(x86_64\) + os_replacement: Mac OS X os_v1_replacement: '10' os_v2_replacement: '11' - ########## - # CFNetwork iOS Apps - # @ref: https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history - ########## - - regex: 'CFNetwork/.{0,100} Darwin/(9)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(9)\.\d+ + os_replacement: iOS os_v1_replacement: '1' - - regex: 'CFNetwork/.{0,100} Darwin/(10)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(10)\.\d+ + os_replacement: iOS os_v1_replacement: '4' - - regex: 'CFNetwork/.{0,100} Darwin/(11)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(11)\.\d+ + os_replacement: iOS os_v1_replacement: '5' - - regex: 'CFNetwork/.{0,100} Darwin/(13)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(13)\.\d+ + os_replacement: iOS os_v1_replacement: '6' - - regex: 'CFNetwork/6.{0,100} Darwin/(14)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/6.{0,100} Darwin/(14)\.\d+ + os_replacement: iOS os_v1_replacement: '7' - - regex: 'CFNetwork/7.{0,100} Darwin/(14)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/7.{0,100} Darwin/(14)\.\d+ + os_replacement: iOS os_v1_replacement: '8' os_v2_replacement: '0' - - regex: 'CFNetwork/7.{0,100} Darwin/(15)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/7.{0,100} Darwin/(15)\.\d+ + os_replacement: iOS os_v1_replacement: '9' os_v2_replacement: '0' - - regex: 'CFNetwork/8.{0,100} Darwin/16\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/16\.5\.\d+ + os_replacement: iOS os_v1_replacement: '10' os_v2_replacement: '3' - - regex: 'CFNetwork/8.{0,100} Darwin/16\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/16\.6\.\d+ + os_replacement: iOS os_v1_replacement: '10' os_v2_replacement: '3' os_v3_replacement: '2' - - regex: 'CFNetwork/8.{0,100} Darwin/16\.7\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/16\.7\.\d+ + os_replacement: iOS os_v1_replacement: '10' os_v2_replacement: '3' os_v3_replacement: '3' - - regex: 'CFNetwork/8.{0,100} Darwin/(16)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/(16)\.\d+ + os_replacement: iOS os_v1_replacement: '10' - - regex: 'CFNetwork/8.{0,100} Darwin/17\.0\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/17\.0\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '0' - - regex: 'CFNetwork/8.{0,100} Darwin/17\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/17\.2\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '1' - - regex: 'CFNetwork/8.{0,100} Darwin/17\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/17\.3\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '2' - - regex: 'CFNetwork/8.{0,100} Darwin/17\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/17\.4\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '2' os_v3_replacement: '6' - - regex: 'CFNetwork/8.{0,100} Darwin/17\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/17\.5\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '3' - - regex: 'CFNetwork/9.{0,100} Darwin/17\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/17\.6\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '4' - - regex: 'CFNetwork/9.{0,100} Darwin/17\.7\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/17\.7\.\d+ + os_replacement: iOS os_v1_replacement: '11' os_v2_replacement: '4' os_v3_replacement: '1' - - regex: 'CFNetwork/8.{0,100} Darwin/(17)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/8.{0,100} Darwin/(17)\.\d+ + os_replacement: iOS os_v1_replacement: '11' - - regex: 'CFNetwork/9.{0,100} Darwin/18\.0\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/18\.0\.\d+ + os_replacement: iOS os_v1_replacement: '12' os_v2_replacement: '0' - - regex: 'CFNetwork/9.{0,100} Darwin/18\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/18\.2\.\d+ + os_replacement: iOS os_v1_replacement: '12' os_v2_replacement: '1' - - regex: 'CFNetwork/9.{0,100} Darwin/18\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/18\.5\.\d+ + os_replacement: iOS os_v1_replacement: '12' os_v2_replacement: '2' - - regex: 'CFNetwork/9.{0,100} Darwin/18\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/18\.6\.\d+ + os_replacement: iOS os_v1_replacement: '12' os_v2_replacement: '3' - - regex: 'CFNetwork/9.{0,100} Darwin/18\.7\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/18\.7\.\d+ + os_replacement: iOS os_v1_replacement: '12' os_v2_replacement: '4' - - regex: 'CFNetwork/9.{0,100} Darwin/(18)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/9.{0,100} Darwin/(18)\.\d+ + os_replacement: iOS os_v1_replacement: '12' - - regex: 'CFNetwork/11.{0,100} Darwin/19\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/11.{0,100} Darwin/19\.2\.\d+ + os_replacement: iOS os_v1_replacement: '13' os_v2_replacement: '3' - - regex: 'CFNetwork/11.{0,100} Darwin/19\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/11.{0,100} Darwin/19\.3\.\d+ + os_replacement: iOS os_v1_replacement: '13' os_v2_replacement: '3' os_v3_replacement: '1' - - regex: 'CFNetwork/11.{0,100} Darwin/19\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/11.{0,100} Darwin/19\.4\.\d+ + os_replacement: iOS os_v1_replacement: '13' os_v2_replacement: '4' - - regex: 'CFNetwork/11.{0,100} Darwin/19\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/11.{0,100} Darwin/19\.5\.\d+ + os_replacement: iOS os_v1_replacement: '13' os_v2_replacement: '5' - - regex: 'CFNetwork/11.{0,100} Darwin/19\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/11.{0,100} Darwin/19\.6\.\d+ + os_replacement: iOS os_v1_replacement: '13' os_v2_replacement: '6' - - regex: 'CFNetwork/1[01].{0,100} Darwin/19\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/1[01].{0,100} Darwin/19\.\d+ + os_replacement: iOS os_v1_replacement: '13' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.1\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.1\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '2' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.2\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '3' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.3\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '4' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.4\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '5' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.5\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '6' - - regex: 'CFNetwork/12.{0,100} Darwin/20\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/12.{0,100} Darwin/20\.6\.\d+ + os_replacement: iOS os_v1_replacement: '14' os_v2_replacement: '8' - - regex: 'CFNetwork/.{0,100} Darwin/(20)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(20)\.\d+ + os_replacement: iOS os_v1_replacement: '14' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.0\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.0\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '0' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.1\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.1\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '1' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.2\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '2' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.3\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '3' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.4\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '4' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.5\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.5\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '5' - - regex: 'CFNetwork/13.{0,100} Darwin/21\.6\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/13.{0,100} Darwin/21\.6\.\d+ + os_replacement: iOS os_v1_replacement: '15' os_v2_replacement: '6' - - regex: 'CFNetwork/.{0,100} Darwin/(21)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(21)\.\d+ + os_replacement: iOS os_v1_replacement: '15' - - regex: 'CFNetwork/.{0,100} Darwin/22\.0\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/22\.0\.\d+ + os_replacement: iOS os_v1_replacement: '16' os_v2_replacement: '0' - - regex: 'CFNetwork/.{0,100} Darwin/22\.1\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/22\.1\.\d+ + os_replacement: iOS os_v1_replacement: '16' os_v2_replacement: '1' - - regex: 'CFNetwork/.{0,100} Darwin/22\.2\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/22\.2\.\d+ + os_replacement: iOS os_v1_replacement: '16' os_v2_replacement: '2' - - regex: 'CFNetwork/.{0,100} Darwin/22\.3\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/22\.3\.\d+ + os_replacement: iOS os_v1_replacement: '16' os_v2_replacement: '3' - - regex: 'CFNetwork/.{0,100} Darwin/22\.4\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/22\.4\.\d+ + os_replacement: iOS os_v1_replacement: '16' os_v2_replacement: '4' - - regex: 'CFNetwork/.{0,100} Darwin/(22)\.\d+' - os_replacement: 'iOS' + - regex: CFNetwork/.{0,100} Darwin/(22)\.\d+ + os_replacement: iOS os_v1_replacement: '16' - - regex: 'CFNetwork/.{0,100} Darwin/' - os_replacement: 'iOS' - - # iOS Apps + - regex: CFNetwork/.{0,100} Darwin/ + os_replacement: iOS - 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);' - - ########## - # Apple Watch - ########## - - regex: '(watchOS)[/ ](\d+)\.(\d+)(?:\.(\d+)|)' - os_replacement: 'WatchOS' - - ########################## - # Outlook on iOS >= 2.62.0 - ########################## - - 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+)(?:\.(\d+)|)' - os_replacement: 'tvOS' - - ########## - # Chrome OS - # if version 0.0.0, probably this stuff: - # 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+)|)' - os_replacement: 'Chrome OS' - - ########## - # Linux distros - ########## - - regex: '([Dd]ebian)' - os_replacement: 'Debian' - - regex: '(Linux Mint)(?:/(\d+)|)' + os_replacement: iOS + - regex: \((iOS); + - regex: (watchOS)[/ ](\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: WatchOS + - regex: Outlook-(iOS)/\d+\.\d+\.prod\.iphone + - regex: (iPod|iPhone|iPad) + os_replacement: iOS + - regex: (tvOS)[/ ](\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: tvOS + - regex: (CrOS) [a-z0-9_]+ (\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: Chrome OS + - regex: ([Dd]ebian) + os_replacement: Debian + - regex: (Linux Mint)(?:/(\d+)|) - regex: '(Mandriva)(?: Linux|)/(?:[\d.-]+m[a-z]{2}(\d+).(\d)|)' - - ########## - # Symbian + Symbian OS - # http://en.wikipedia.org/wiki/History_of_Symbian - ########## - - regex: '(Symbian[Oo][Ss])[/ ](\d+)\.(\d+)' - os_replacement: 'Symbian OS' - - regex: '(Symbian/3).{1,200}NokiaBrowser/7\.3' - os_replacement: 'Symbian^3 Anna' - - regex: '(Symbian/3).{1,200}NokiaBrowser/7\.4' - os_replacement: 'Symbian^3 Belle' - - regex: '(Symbian/3)' - os_replacement: 'Symbian^3' - - regex: '\b(Series 60|SymbOS|S60Version|S60V\d|S60\b)' - os_replacement: 'Symbian OS' - - regex: '(MeeGo)' - - regex: 'Symbian [Oo][Ss]' - os_replacement: 'Symbian OS' - - regex: 'Series40;' - os_replacement: 'Nokia Series 40' - - regex: 'Series30Plus;' - os_replacement: 'Nokia Series 30 Plus' - - ########## - # BlackBerry devices - ########## - - regex: '(BB10);.{1,200}Version/(\d+)\.(\d+)\.(\d+)' - os_replacement: 'BlackBerry OS' - - regex: '(Black[Bb]erry)[0-9a-z]+/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)' - os_replacement: 'BlackBerry OS' - - regex: '(Black[Bb]erry).{1,200}Version/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|)' - os_replacement: 'BlackBerry OS' - - regex: '(RIM Tablet OS) (\d+)\.(\d+)\.(\d+)' - os_replacement: 'BlackBerry Tablet OS' - - regex: '(Play[Bb]ook)' - os_replacement: 'BlackBerry Tablet OS' - - regex: '(Black[Bb]erry)' - os_replacement: 'BlackBerry OS' - - ########## - # KaiOS - ########## - - regex: '(K[Aa][Ii]OS)\/(\d+)\.(\d+)(?:\.(\d+)|)' - os_replacement: 'KaiOS' - - ########## - # Firefox OS - ########## - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/18.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: (Symbian[Oo][Ss])[/ ](\d+)\.(\d+) + os_replacement: Symbian OS + - regex: (Symbian/3).{1,200}NokiaBrowser/7\.3 + os_replacement: Symbian^3 Anna + - regex: (Symbian/3).{1,200}NokiaBrowser/7\.4 + os_replacement: Symbian^3 Belle + - regex: (Symbian/3) + os_replacement: Symbian^3 + - regex: \b(Series 60|SymbOS|S60Version|S60V\d|S60\b) + os_replacement: Symbian OS + - regex: (MeeGo) + - regex: Symbian [Oo][Ss] + os_replacement: Symbian OS + - regex: Series40; + os_replacement: Nokia Series 40 + - regex: Series30Plus; + os_replacement: Nokia Series 30 Plus + - regex: (BB10);.{1,200}Version/(\d+)\.(\d+)\.(\d+) + os_replacement: BlackBerry OS + - regex: (Black[Bb]erry)[0-9a-z]+/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: BlackBerry OS + - regex: (Black[Bb]erry).{1,200}Version/(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: BlackBerry OS + - regex: (RIM Tablet OS) (\d+)\.(\d+)\.(\d+) + os_replacement: BlackBerry Tablet OS + - regex: (Play[Bb]ook) + os_replacement: BlackBerry Tablet OS + - regex: (Black[Bb]erry) + os_replacement: BlackBerry OS + - regex: (K[Aa][Ii]OS)\/(\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: KaiOS + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/18.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '1' os_v2_replacement: '0' os_v3_replacement: '1' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/18.1 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/18.1 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '1' os_v2_replacement: '1' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/26.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/26.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '1' os_v2_replacement: '2' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/28.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/28.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '1' os_v2_replacement: '3' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/30.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/30.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '1' os_v2_replacement: '4' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/32.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/32.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '2' os_v2_replacement: '0' - - - regex: '\((?:Mobile|Tablet);.{1,200}Gecko/34.0 Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' + - regex: \((?:Mobile|Tablet);.{1,200}Gecko/34.0 Firefox/\d+\.\d+ + os_replacement: Firefox OS os_v1_replacement: '2' os_v2_replacement: '1' - - # Firefox OS Generic - - regex: '\((?:Mobile|Tablet);.{1,200}Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' - - - ########## - # BREW - # yes, Brew is lower-cased for Brew MP - ########## - - regex: '(BREW)[ /](\d+)\.(\d+)\.(\d+)' - - regex: '(BREW);' - - regex: '(Brew MP|BMP)[ /](\d+)\.(\d+)\.(\d+)' - os_replacement: 'Brew MP' - - regex: 'BMP;' - os_replacement: 'Brew MP' - - ########## - # Google TV - ########## + - regex: \((?:Mobile|Tablet);.{1,200}Firefox/\d+\.\d+ + os_replacement: Firefox OS + - regex: (BREW)[ /](\d+)\.(\d+)\.(\d+) + - regex: (BREW); + - regex: (Brew MP|BMP)[ /](\d+)\.(\d+)\.(\d+) + os_replacement: Brew MP + - regex: BMP; + os_replacement: Brew MP - regex: '(GoogleTV)(?: (\d+)\.(\d+)(?:\.(\d+)|)|/[\da-z]+)' - - - regex: '(WebTV)/(\d+).(\d+)' - - ########## - # Chromecast - ########## - - regex: '(CrKey)(?:[/](\d+)\.(\d+)(?:\.(\d+)|)|)' - os_replacement: 'Chromecast' - - ########## - # Misc mobile - ########## - - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|)' - os_replacement: 'webOS' - - regex: '(VRE);' - - ########## - # Generic patterns - # since the majority of os cases are very specific, these go last - ########## - - regex: '(Fedora|Red Hat|PCLinuxOS|Puppy|Ubuntu|Kindle|Bada|Sailfish|Lubuntu|BackTrack|Slackware|(?:Free|Open|Net|\b)BSD)[/ ](\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|)' - - # Gentoo Linux + Kernel Version - - regex: '(Linux)[ /](\d+)\.(\d+)(?:\.(\d+)|).{0,100}gentoo' - os_replacement: 'Gentoo' - - # Opera Mini Bada - - regex: '\((Bada);' - - # just os - - regex: '(Windows|Android|WeTab|Maemo|Web0S)' - - regex: '(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Mageia|SerenityOS|(?:Free|Open|Net|\b)BSD)' - # Linux + Kernel Version - - regex: '(Linux)(?:[ /](\d+)\.(\d+)(?:\.(\d+)|)|)' - - regex: 'SunOS' - os_replacement: 'Solaris' - # Wget/x.x.x (linux-gnu) - - regex: '\(linux-gnu\)' - os_replacement: 'Linux' - - regex: '\(x86_64-redhat-linux-gnu\)' - os_replacement: 'Red Hat' - - regex: '\((freebsd)(\d+)\.(\d+)\)' - os_replacement: 'FreeBSD' - - regex: 'linux' - os_replacement: 'Linux' - - # Roku Digital-Video-Players https://www.roku.com/ - - regex: '^(Roku)/DVP-(\d+)\.(\d+)' - + - regex: (WebTV)/(\d+).(\d+) + - regex: (hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+)|) + os_replacement: webOS + - regex: (VRE); + - regex: (Fedora|Red Hat|PCLinuxOS|Puppy|Ubuntu|Kindle|Bada|Sailfish|Lubuntu|BackTrack|Slackware|(?:Free|Open|Net|\b)BSD)[/ + ](\d+)\.(\d+)(?:\.(\d+)|)(?:\.(\d+)|) + - regex: (Linux)[ /](\d+)\.(\d+)(?:\.(\d+)|).{0,100}gentoo + os_replacement: Gentoo + - regex: \((Bada); + - regex: (Windows|Android|WeTab|Maemo|Web0S) + - regex: (Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Mageia|SerenityOS|(?:Free|Open|Net|\b)BSD) + - regex: (Linux)(?:[ /](\d+)\.(\d+)(?:\.(\d+)|)|) + - regex: SunOS + os_replacement: Solaris + - regex: \(linux-gnu\) + os_replacement: Linux + - regex: \(x86_64-redhat-linux-gnu\) + os_replacement: Red Hat + - regex: \((freebsd)(\d+)\.(\d+)\) + os_replacement: FreeBSD + - regex: linux + os_replacement: Linux + - regex: ^(Roku)/DVP-(\d+)\.(\d+) device_parsers: - - ######### - # Mobile Spiders - # Catch the mobile crawler before checking for iPhones / Androids. - ######### - - regex: '^.{0,100}?(?:(?:iPhone|Windows CE|Windows Phone|Android).{0,300}(?:(?:Bot|Yeti)-Mobile|YRSpider|BingPreview|bots?/\d|(?:bot|spider)\.html)|AdsBot-Google-Mobile.{0,200}iPhone)' - regex_flag: 'i' - device_replacement: 'Spider' - brand_replacement: 'Spider' - model_replacement: 'Smartphone' - - regex: '^.{0,100}?(?:DoCoMo|\bMOT\b|\bLG\b|Nokia|Samsung|SonyEricsson).{0,200}(?:(?:Bot|Yeti)-Mobile|bots?/\d|(?:bot|crawler)\.html|(?:jump|google|Wukong)bot|ichiro/mobile|/spider|YahooSeeker)' - regex_flag: 'i' - device_replacement: 'Spider' - brand_replacement: 'Spider' - model_replacement: 'Feature Phone' - - # PTST / WebPageTest.org crawlers + - regex: ^.{0,100}?(?:(?:iPhone|Windows CE|Windows Phone|Android).{0,300}(?:(?:Bot|Yeti)-Mobile|YRSpider|BingPreview|bots?/\d|(?:bot|spider)\.html)|AdsBot-Google-Mobile.{0,200}iPhone) + regex_flag: i + device_replacement: Spider + brand_replacement: Spider + model_replacement: Smartphone + - regex: ^.{0,100}?(?:DoCoMo|\bMOT\b|\bLG\b|Nokia|Samsung|SonyEricsson).{0,200}(?:(?:Bot|Yeti)-Mobile|bots?/\d|(?:bot|crawler)\.html|(?:jump|google|Wukong)bot|ichiro/mobile|/spider|YahooSeeker) + regex_flag: i + device_replacement: Spider + brand_replacement: Spider + model_replacement: Feature Phone - regex: ' PTST/\d+(?:\.\d+|)$' - device_replacement: 'Spider' - brand_replacement: 'Spider' - - # Datanyze.com spider - - regex: 'X11; Datanyze; Linux' - device_replacement: 'Spider' - brand_replacement: 'Spider' - - # aspiegel.com spider (owned by Huawei) - - regex: 'Mozilla.{1,100}Mobile.{1,100}(AspiegelBot|PetalBot)' - device_replacement: 'Spider' - brand_replacement: 'Spider' - model_replacement: 'Smartphone' - - regex: 'Mozilla.{0,200}(AspiegelBot|PetalBot)' - device_replacement: 'Spider' - brand_replacement: 'Spider' - model_replacement: 'Desktop' - - ######### - # WebBrowser for SmartWatch - # @ref: https://play.google.com/store/apps/details?id=se.vaggan.webbrowser&hl=en - ######### - - regex: '\bSmartWatch {0,2}\( {0,2}([^;]{1,200}) {0,2}; {0,2}([^;]{1,200}) {0,2};' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ###################################################################### - # Android parsers - # - # @ref: https://support.google.com/googleplay/answer/1727131?hl=en - ###################################################################### - - # Android Application - - regex: 'Android Application[^\-]{1,300} - (Sony) ?(Ericsson|) (.{1,200}) \w{1,20} - ' - device_replacement: '$1 $2' - brand_replacement: '$1$2' - model_replacement: '$3' - - regex: 'Android Application[^\-]{1,300} - (?:HTC|HUAWEI|LGE|LENOVO|MEDION|TCT) (HTC|HUAWEI|LG|LENOVO|MEDION|ALCATEL)[ _\-](.{1,200}) \w{1,20} - ' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' + device_replacement: Spider + brand_replacement: Spider + - regex: X11; Datanyze; Linux + device_replacement: Spider + brand_replacement: Spider + - regex: Mozilla.{1,100}Mobile.{1,100}(AspiegelBot|PetalBot) + device_replacement: Spider + brand_replacement: Spider + model_replacement: Smartphone + - regex: Mozilla.{0,200}(AspiegelBot|PetalBot) + device_replacement: Spider + brand_replacement: Spider + model_replacement: Desktop + - regex: \bSmartWatch {0,2}\( {0,2}([^;]{1,200}) {0,2}; {0,2}([^;]{1,200}) {0,2}; + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - regex: 'Android Application[^\-]{1,300} - (Sony) ?(Ericsson|) (.{1,200}) \w{1,20} + - ' + device_replacement: $1 $2 + brand_replacement: $1$2 + model_replacement: $3 + - regex: 'Android Application[^\-]{1,300} - (?:HTC|HUAWEI|LGE|LENOVO|MEDION|TCT) + (HTC|HUAWEI|LG|LENOVO|MEDION|ALCATEL)[ _\-](.{1,200}) \w{1,20} - ' + regex_flag: i + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: 'Android Application[^\-]{1,300} - ([^ ]+) (.{1,200}) \w{1,20} - ' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # 3Q - # @ref: http://www.3q-int.com/ - ######### + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}([BLRQ]C\d{4}[A-Z]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '3Q $1' - brand_replacement: '3Q' - model_replacement: '$1' + device_replacement: 3Q $1 + brand_replacement: 3Q + model_replacement: $1 - regex: '; {0,2}(?:3Q_)([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '3Q $1' - brand_replacement: '3Q' - model_replacement: '$1' - - ######### - # Acer - # @ref: http://us.acer.com/ac/en/US/content/group/tablets - ######### - - regex: 'Android [34].{0,200}; {0,2}(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[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Acer' - model_replacement: '$1' + device_replacement: 3Q $1 + brand_replacement: 3Q + model_replacement: $1 + - regex: 'Android [34].{0,200}; {0,2}(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[^;/]{1,100}?)(?: Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Acer + model_replacement: $1 - regex: '; {0,2}Acer Iconia Tab ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Acer' - model_replacement: '$1' - - regex: '; {0,2}(Z1[1235]0|E320[^/]{0,10}|S500|S510|Liquid[^;/]{0,30}|Iconia A\d+)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Acer' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Acer + model_replacement: $1 + - regex: '; {0,2}(Z1[1235]0|E320[^/]{0,10}|S500|S510|Liquid[^;/]{0,30}|Iconia A\d+)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Acer + model_replacement: $1 - regex: '; {0,2}(Acer |ACER )([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Acer' - model_replacement: '$2' - - ######### - # Advent - # @ref: https://en.wikipedia.org/wiki/Advent_Vega - # @note: VegaBean and VegaComb (names derived from jellybean, honeycomb) are - # custom ROM builds for Vega - ######### + device_replacement: $1$2 + brand_replacement: Acer + model_replacement: $2 - regex: '; {0,2}(Advent |)(Vega(?:Bean|Comb|)).{0,200}?(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Advent' - model_replacement: '$2' - - ######### - # Ainol - # @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product - ######### + device_replacement: $1$2 + brand_replacement: Advent + model_replacement: $2 - regex: '; {0,2}(Ainol |)((?:NOVO|[Nn]ovo)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Ainol' - model_replacement: '$2' - - ######### - # Airis - # @ref: http://airis.es/Tienda/Default.aspx?idG=001 - ######### - - regex: '; {0,2}AIRIS[ _\-]?([^/;\)]+) {0,2}(?:;|\)|Build)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Airis' - model_replacement: '$1' + device_replacement: $1$2 + brand_replacement: Ainol + model_replacement: $2 + - regex: ; {0,2}AIRIS[ _\-]?([^/;\)]+) {0,2}(?:;|\)|Build) + regex_flag: i + device_replacement: $1 + brand_replacement: Airis + model_replacement: $1 - regex: '; {0,2}(OnePAD[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Airis' - model_replacement: '$1' - - ######### - # Airpad - # @ref: ?? - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Airis + model_replacement: $1 - regex: '; {0,2}Airpad[ \-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Airpad $1' - brand_replacement: 'Airpad' - model_replacement: '$1' - - ######### - # Alcatel - TCT - # @ref: http://www.alcatelonetouch.com/global-en/products/smartphones.html - ######### + device_replacement: Airpad $1 + brand_replacement: Airpad + model_replacement: $1 - regex: '; {0,2}(one ?touch) (EVO7|T10|T20)(?: Build|\) AppleWebKit)' - device_replacement: 'Alcatel One Touch $2' - brand_replacement: 'Alcatel' - model_replacement: 'One Touch $2' - - regex: '; {0,2}(?:alcatel[ _]|)(?:(?:one[ _]?touch[ _])|ot[ \-])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Alcatel One Touch $1' - brand_replacement: 'Alcatel' - model_replacement: 'One Touch $1' + device_replacement: Alcatel One Touch $2 + brand_replacement: Alcatel + model_replacement: One Touch $2 + - regex: '; {0,2}(?:alcatel[ _]|)(?:(?:one[ _]?touch[ _])|ot[ \-])([^;/]{1,100}?)(?: + Build|\) AppleWebKit)' + regex_flag: i + device_replacement: Alcatel One Touch $1 + brand_replacement: Alcatel + model_replacement: One Touch $1 - regex: '; {0,2}(TCL)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - # operator specific models + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(Vodafone Smart II|Optimus_Madrid)(?: Build|\) AppleWebKit)' - device_replacement: 'Alcatel $1' - brand_replacement: 'Alcatel' - model_replacement: '$1' + device_replacement: Alcatel $1 + brand_replacement: Alcatel + model_replacement: $1 - regex: '; {0,2}BASE_Lutea_3(?: Build|\) AppleWebKit)' - device_replacement: 'Alcatel One Touch 998' - brand_replacement: 'Alcatel' - model_replacement: 'One Touch 998' + device_replacement: Alcatel One Touch 998 + brand_replacement: Alcatel + model_replacement: One Touch 998 - regex: '; {0,2}BASE_Varia(?: Build|\) AppleWebKit)' - device_replacement: 'Alcatel One Touch 918D' - brand_replacement: 'Alcatel' - model_replacement: 'One Touch 918D' - - ######### - # Allfine - # @ref: http://www.myallfine.com/Products.asp - ######### + device_replacement: Alcatel One Touch 918D + brand_replacement: Alcatel + model_replacement: One Touch 918D - regex: '; {0,2}((?:FINE|Fine)\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Allfine' - model_replacement: '$1' - - ######### - # Allview - # @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/ - ######### - - regex: '; {0,2}(ALLVIEW[ _]?|Allview[ _]?)((?:Speed|SPEED).{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Allview' - model_replacement: '$2' - - regex: '; {0,2}(ALLVIEW[ _]?|Allview[ _]?|)(AX1_Shine|AX2_Frenzy)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Allview' - model_replacement: '$2' + device_replacement: $1 + brand_replacement: Allfine + model_replacement: $1 + - regex: '; {0,2}(ALLVIEW[ _]?|Allview[ _]?)((?:Speed|SPEED).{0,200}?)(?: Build|\) + AppleWebKit)' + device_replacement: $1$2 + brand_replacement: Allview + model_replacement: $2 + - regex: '; {0,2}(ALLVIEW[ _]?|Allview[ _]?|)(AX1_Shine|AX2_Frenzy)(?: Build|\) + AppleWebKit)' + device_replacement: $1$2 + brand_replacement: Allview + model_replacement: $2 - regex: '; {0,2}(ALLVIEW[ _]?|Allview[ _]?)([^;/]*?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Allview' - model_replacement: '$2' - - ######### - # Allwinner - # @ref: http://www.allwinner.com/ - # @models: A31 (13.3"),A20,A10, - ######### + device_replacement: $1$2 + brand_replacement: Allview + model_replacement: $2 - regex: '; {0,2}(A13-MID)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Allwinner' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Allwinner + model_replacement: $1 - regex: '; {0,2}(Allwinner)[ _\-]?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Allwinner' - model_replacement: '$1' - - ######### - # Amaway - # @ref: http://www.amaway.cn/ - ######### - - regex: '; {0,2}(A651|A701B?|A702|A703|A705|A706|A707|A711|A712|A713|A717|A722|A785|A801|A802|A803|A901|A902|A1002|A1003|A1006|A1007|A9701|A9703|Q710|Q80)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Amaway' - model_replacement: '$1' - - ######### - # Amoi - # @ref: http://www.amoi.com/en/prd/prd_index.jspx - ######### + device_replacement: $1 $2 + brand_replacement: Allwinner + model_replacement: $1 + - regex: '; {0,2}(A651|A701B?|A702|A703|A705|A706|A707|A711|A712|A713|A717|A722|A785|A801|A802|A803|A901|A902|A1002|A1003|A1006|A1007|A9701|A9703|Q710|Q80)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Amaway + model_replacement: $1 - regex: '; {0,2}(?:AMOI|Amoi)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Amoi $1' - brand_replacement: 'Amoi' - model_replacement: '$1' - - regex: '^(?:AMOI|Amoi)[ _]([^;/]{1,100}?) Linux' - device_replacement: 'Amoi $1' - brand_replacement: 'Amoi' - model_replacement: '$1' - - ######### - # Aoc - # @ref: http://latin.aoc.com/media_tablet - ######### + device_replacement: Amoi $1 + brand_replacement: Amoi + model_replacement: $1 + - regex: ^(?:AMOI|Amoi)[ _]([^;/]{1,100}?) Linux + device_replacement: Amoi $1 + brand_replacement: Amoi + model_replacement: $1 - regex: '; {0,2}(MW(?:0[789]|10)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Aoc' - model_replacement: '$1' - - ######### - # Aoson - # @ref: http://www.luckystar.com.cn/en/mid.aspx?page=1 - # @ref: http://www.luckystar.com.cn/en/mobiletel.aspx?page=1 - # @note: brand owned by luckystar - ######### - - regex: '; {0,2}(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|\) AppleWebKit)' - device_replacement: 'Aoson $1' - brand_replacement: 'Aoson' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Aoc + model_replacement: $1 + - regex: '; {0,2}(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|\) AppleWebKit)' + device_replacement: Aoson $1 + brand_replacement: Aoson + model_replacement: $1 - regex: '; {0,2}Aoson ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Aoson $1' - brand_replacement: 'Aoson' - model_replacement: '$1' - - ######### - # Apanda - # @ref: http://www.apanda.com.cn/ - ######### + regex_flag: i + device_replacement: Aoson $1 + brand_replacement: Aoson + model_replacement: $1 - regex: '; {0,2}[Aa]panda[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Apanda $1' - brand_replacement: 'Apanda' - model_replacement: '$1' - - ######### - # Archos - # @ref: http://www.archos.com/de/products/tablets.html - # @ref: http://www.archos.com/de/products/smartphones/index.html - ######### + device_replacement: Apanda $1 + brand_replacement: Apanda + model_replacement: $1 - regex: '; {0,2}(?:ARCHOS|Archos) ?(GAMEPAD.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Archos $1' - brand_replacement: 'Archos' - model_replacement: '$1' - - regex: 'ARCHOS; GOGI; ([^;]{1,200});' - device_replacement: 'Archos $1' - brand_replacement: 'Archos' - model_replacement: '$1' + device_replacement: Archos $1 + brand_replacement: Archos + model_replacement: $1 + - regex: ARCHOS; GOGI; ([^;]{1,200}); + device_replacement: Archos $1 + brand_replacement: Archos + model_replacement: $1 - regex: '(?:ARCHOS|Archos)[ _]?(.{0,200}?)(?: Build|[;/\(\)\-]|$)' - device_replacement: 'Archos $1' - brand_replacement: 'Archos' - model_replacement: '$1' + device_replacement: Archos $1 + brand_replacement: Archos + model_replacement: $1 - regex: '; {0,2}(AN(?:7|8|9|10|13)[A-Z0-9]{1,4})(?: Build|\) AppleWebKit)' - device_replacement: 'Archos $1' - brand_replacement: 'Archos' - model_replacement: '$1' - - regex: '; {0,2}(A28|A32|A43|A70(?:BHT|CHT|HB|S|X)|A101(?:B|C|IT)|A7EB|A7EB-WK|101G9|80G9)(?: Build|\) AppleWebKit)' - device_replacement: 'Archos $1' - brand_replacement: 'Archos' - model_replacement: '$1' - - ######### - # A-rival - # @ref: http://www.a-rival.de/de/ - ######### + device_replacement: Archos $1 + brand_replacement: Archos + model_replacement: $1 + - regex: '; {0,2}(A28|A32|A43|A70(?:BHT|CHT|HB|S|X)|A101(?:B|C|IT)|A7EB|A7EB-WK|101G9|80G9)(?: + Build|\) AppleWebKit)' + device_replacement: Archos $1 + brand_replacement: Archos + model_replacement: $1 - regex: '; {0,2}(PAD-FMD[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Arival' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Arival + model_replacement: $1 - regex: '; {0,2}(BioniQ) ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Arival' - model_replacement: '$1 $2' - - ######### - # Arnova - # @ref: http://arnovatech.com/ - ######### + device_replacement: $1 $2 + brand_replacement: Arival + model_replacement: $1 $2 - regex: '; {0,2}(AN\d[^;/]{1,100}|ARCHM\d+)(?: Build|\) AppleWebKit)' - device_replacement: 'Arnova $1' - brand_replacement: 'Arnova' - model_replacement: '$1' + device_replacement: Arnova $1 + brand_replacement: Arnova + model_replacement: $1 - regex: '; {0,2}(?:ARNOVA|Arnova) ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Arnova $1' - brand_replacement: 'Arnova' - model_replacement: '$1' - - ######### - # Assistant - # @ref: http://www.assistant.ua - ######### - - regex: '; {0,2}(?:ASSISTANT |)(AP)-?([1789]\d{2}[A-Z]{0,2}|80104)(?: Build|\) AppleWebKit)' - device_replacement: 'Assistant $1-$2' - brand_replacement: 'Assistant' - model_replacement: '$1-$2' - - ######### - # Asus - # @ref: http://www.asus.com/uk/Tablets_Mobile/ - ######### - - regex: '; {0,2}(ME17\d[^;/]*|ME3\d{2}[^;/]{1,100}|K00[A-Z]|Nexus 10|Nexus 7(?: 2013|)|PadFone[^;/]*|Transformer[^;/]*|TF\d{3}[^;/]*|eeepc)(?: Build|\) AppleWebKit)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' + device_replacement: Arnova $1 + brand_replacement: Arnova + model_replacement: $1 + - regex: '; {0,2}(?:ASSISTANT |)(AP)-?([1789]\d{2}[A-Z]{0,2}|80104)(?: Build|\) + AppleWebKit)' + device_replacement: Assistant $1-$2 + brand_replacement: Assistant + model_replacement: $1-$2 + - regex: '; {0,2}(ME17\d[^;/]*|ME3\d{2}[^;/]{1,100}|K00[A-Z]|Nexus 10|Nexus 7(?: + 2013|)|PadFone[^;/]*|Transformer[^;/]*|TF\d{3}[^;/]*|eeepc)(?: Build|\) AppleWebKit)' + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 - regex: '; {0,2}ASUS[ _]{0,10}([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' - - ######### - # Garmin-Asus - ######### + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 - regex: '; {0,2}Garmin-Asus ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Garmin-Asus $1' - brand_replacement: 'Garmin-Asus' - model_replacement: '$1' + device_replacement: Garmin-Asus $1 + brand_replacement: Garmin-Asus + model_replacement: $1 - regex: '; {0,2}(Garminfone)(?: Build|\) AppleWebKit)' - device_replacement: 'Garmin $1' - brand_replacement: 'Garmin-Asus' - model_replacement: '$1' - - ######### - # Attab - # @ref: http://www.theattab.com/ - ######### + device_replacement: Garmin $1 + brand_replacement: Garmin-Asus + model_replacement: $1 - regex: '; (@TAB-[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Attab' - model_replacement: '$1' - - ######### - # Audiosonic - # @ref: ?? - # @note: Take care with Docomo T-01 Toshiba - ######### + device_replacement: $1 + brand_replacement: Attab + model_replacement: $1 - regex: '; {0,2}(T-(?:07|[^0]\d)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Audiosonic' - model_replacement: '$1' - - ######### - # Axioo - # @ref: http://www.axiooworld.com/ww/index.php - ######### - - regex: '; {0,2}(?:Axioo[ _\-]([^;/]{1,100}?)|(picopad)[ _\-]([^;/]{1,100}?))(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Axioo $1$2 $3' - brand_replacement: 'Axioo' - model_replacement: '$1$2 $3' - - ######### - # Azend - # @ref: http://azendcorp.com/index.php/products/portable-electronics - ######### + device_replacement: $1 + brand_replacement: Audiosonic + model_replacement: $1 + - regex: '; {0,2}(?:Axioo[ _\-]([^;/]{1,100}?)|(picopad)[ _\-]([^;/]{1,100}?))(?: + Build|\) AppleWebKit)' + regex_flag: i + device_replacement: Axioo $1$2 $3 + brand_replacement: Axioo + model_replacement: $1$2 $3 - regex: '; {0,2}(V(?:100|700|800)[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Azend' - model_replacement: '$1' - - ######### - # Bak - # @ref: http://www.bakinternational.com/produtos.php?cat=80 - ######### + device_replacement: $1 + brand_replacement: Azend + model_replacement: $1 - regex: '; {0,2}(IBAK\-[^;/]*)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Bak' - model_replacement: '$1' - - ######### - # Bedove - # @ref: http://www.bedove.com/product.html - # @models: HY6501|HY5001|X12|X21|I5 - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Bak + model_replacement: $1 - regex: '; {0,2}(HY5001|HY6501|X12|X21|I5)(?: Build|\) AppleWebKit)' - device_replacement: 'Bedove $1' - brand_replacement: 'Bedove' - model_replacement: '$1' - - ######### - # Benss - # @ref: http://www.benss.net/ - ######### + device_replacement: Bedove $1 + brand_replacement: Bedove + model_replacement: $1 - regex: '; {0,2}(JC-[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'Benss $1' - brand_replacement: 'Benss' - model_replacement: '$1' - - ######### - # Blackberry - # @ref: http://uk.blackberry.com/ - # @note: Android Apps seams to be used here - ######### + device_replacement: Benss $1 + brand_replacement: Benss + model_replacement: $1 - regex: '; {0,2}(BB) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Blackberry' - model_replacement: '$2' - - ######### - # Blackbird - # @ref: http://iblackbird.co.kr - ######### + device_replacement: $1 $2 + brand_replacement: Blackberry + model_replacement: $2 - regex: '; {0,2}(BlackBird)[ _](I8.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(BlackBird)[ _](.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Blaupunkt - # @ref: http://www.blaupunkt.com - ######### - # Endeavour + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}([0-9]+BP[EM][^;/]*|Endeavour[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Blaupunkt $1' - brand_replacement: 'Blaupunkt' - model_replacement: '$1' - - ######### - # Blu - # @ref: http://bluproducts.com - ######### + device_replacement: Blaupunkt $1 + brand_replacement: Blaupunkt + model_replacement: $1 - regex: '; {0,2}((?:BLU|Blu)[ _\-])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Blu' - model_replacement: '$2' - # BMOBILE = operator branded device - - regex: '; {0,2}(?:BMOBILE )?(Blu|BLU|DASH [^;/]{1,100}|VIVO 4\.3|TANK 4\.5)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Blu' - model_replacement: '$1' - - ######### - # Blusens - # @ref: http://www.blusens.com/es/?sg=1&sv=al&roc=1 - ######### - # tablet + device_replacement: $1$2 + brand_replacement: Blu + model_replacement: $2 + - regex: '; {0,2}(?:BMOBILE )?(Blu|BLU|DASH [^;/]{1,100}|VIVO 4\.3|TANK 4\.5)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Blu + model_replacement: $1 - regex: '; {0,2}(TOUCH\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Blusens' - model_replacement: '$1' - - ######### - # Bmobile - # @ref: http://bmobile.eu.com/?categoria=smartphones-2 - # @note: Might collide with Maxx as AX is used also there. - ######### - # smartphone + device_replacement: $1 + brand_replacement: Blusens + model_replacement: $1 - regex: '; {0,2}(AX5\d+)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Bmobile' - model_replacement: '$1' - - ######### - # bq - # @ref: http://bqreaders.com - ######### + device_replacement: $1 + brand_replacement: Bmobile + model_replacement: $1 - regex: '; {0,2}([Bb]q) ([^;/]{1,100}?);?(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'bq' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: bq + model_replacement: $2 - regex: '; {0,2}(Maxwell [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'bq' - model_replacement: '$1' - - ######### - # Braun Phototechnik - # @ref: http://www.braun-phototechnik.de/en/products/list/~pcat.250/Tablet-PC.html - ######### + device_replacement: $1 + brand_replacement: bq + model_replacement: $1 - regex: '; {0,2}((?:B-Tab|B-TAB) ?\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Braun' - model_replacement: '$1' - - ######### - # Broncho - # @ref: http://www.broncho.cn/ - ######### + device_replacement: $1 + brand_replacement: Braun + model_replacement: $1 - regex: '; {0,2}(Broncho) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Captiva - # @ref: http://www.captiva-power.de - ######### + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}CAPTIVA ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Captiva $1' - brand_replacement: 'Captiva' - model_replacement: '$1' - - ######### - # Casio - # @ref: http://www.casiogzone.com/ - ######### + device_replacement: Captiva $1 + brand_replacement: Captiva + model_replacement: $1 - regex: '; {0,2}(C771|CAL21|IS11CA)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Casio' - model_replacement: '$1' - - ######### - # Cat - # @ref: http://www.cat-sound.com - ######### + device_replacement: $1 + brand_replacement: Casio + model_replacement: $1 - regex: '; {0,2}(?:Cat|CAT) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Cat $1' - brand_replacement: 'Cat' - model_replacement: '$1' + device_replacement: Cat $1 + brand_replacement: Cat + model_replacement: $1 - regex: '; {0,2}(?:Cat)(Nova.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Cat $1' - brand_replacement: 'Cat' - model_replacement: '$1' + device_replacement: Cat $1 + brand_replacement: Cat + model_replacement: $1 - regex: '; {0,2}(INM8002KP|ADM8000KP_[AB])(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Cat' - model_replacement: 'Tablet PHOENIX 8.1J0' - - ######### - # Celkon - # @ref: http://www.celkonmobiles.com/?_a=products - # @models: A10, A19Q, A101, A105, A107, A107\+, A112, A118, A119, A119Q, A15, A19, A20, A200, A220, A225, A22 Race, A27, A58, A59, A60, A62, A63, A64, A66, A67, A69, A75, A77, A79, A8\+, A83, A85, A86, A87, A89 Ultima, A9\+, A90, A900, A95, A97i, A98, AR 40, AR 45, AR 50, ML5 - ######### - - regex: '; {0,2}(?:[Cc]elkon[ _\*]|CELKON[ _\*])([^;/\)]+) ?(?:Build|;|\))' - device_replacement: '$1' - brand_replacement: 'Celkon' - model_replacement: '$1' - - regex: 'Build/(?:[Cc]elkon)+_?([^;/_\)]+)' - device_replacement: '$1' - brand_replacement: 'Celkon' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Cat + model_replacement: Tablet PHOENIX 8.1J0 + - regex: ; {0,2}(?:[Cc]elkon[ _\*]|CELKON[ _\*])([^;/\)]+) ?(?:Build|;|\)) + device_replacement: $1 + brand_replacement: Celkon + model_replacement: $1 + - regex: Build/(?:[Cc]elkon)+_?([^;/_\)]+) + device_replacement: $1 + brand_replacement: Celkon + model_replacement: $1 - regex: '; {0,2}(CT)-?(\d+)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Celkon' - model_replacement: '$1$2' - # smartphones - - regex: '; {0,2}(A19|A19Q|A105|A107[^;/\)]*) ?(?:Build|;|\))' - device_replacement: '$1' - brand_replacement: 'Celkon' - model_replacement: '$1' - - ######### - # ChangJia - # @ref: http://www.cjshowroom.com/eproducts.aspx?classcode=004001001 - # @brief: China manufacturer makes tablets for different small brands - # (eg. http://www.zeepad.net/index.html) - ######### + device_replacement: $1$2 + brand_replacement: Celkon + model_replacement: $1$2 + - regex: ; {0,2}(A19|A19Q|A105|A107[^;/\)]*) ?(?:Build|;|\)) + device_replacement: $1 + brand_replacement: Celkon + model_replacement: $1 - regex: '; {0,2}(TPC[0-9]{4,5})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'ChangJia' - model_replacement: '$1' - - ######### - # Cloudfone - # @ref: http://www.cloudfonemobile.com/ - ######### + device_replacement: $1 + brand_replacement: ChangJia + model_replacement: $1 + - regex: CrKey.*DeviceType/([^/]*) + brand_replacement: Google + device_replacement: Chromecast + model_replacement: $1 + - regex: Fuchsia.*CrKey + brand_replacement: Google + device_replacement: Chromecast + model_replacement: Nest Hub + - regex: Linux.*CrKey/1.36 + brand_replacement: Google + device_replacement: Chromecast + model_replacement: First Generation + - regex: CrKey/ + brand_replacement: Google + device_replacement: Chromecast + model_replacement: Chromecast - regex: '; {0,2}(Cloudfone)[ _](Excite)([^ ][^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2 $3' - brand_replacement: 'Cloudfone' - model_replacement: '$1 $2 $3' + device_replacement: $1 $2 $3 + brand_replacement: Cloudfone + model_replacement: $1 $2 $3 - regex: '; {0,2}(Excite|ICE)[ _](\d+[^;/]{0,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Cloudfone $1 $2' - brand_replacement: 'Cloudfone' - model_replacement: 'Cloudfone $1 $2' + device_replacement: Cloudfone $1 $2 + brand_replacement: Cloudfone + model_replacement: Cloudfone $1 $2 - regex: '; {0,2}(Cloudfone|CloudPad)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Cloudfone' - model_replacement: '$1 $2' - - ######### - # Cmx - # @ref: http://cmx.at/de/ - ######### + device_replacement: $1 $2 + brand_replacement: Cloudfone + model_replacement: $1 $2 - regex: '; {0,2}((?:Aquila|Clanga|Rapax)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Cmx' - model_replacement: '$1' - - ######### - # CobyKyros - # @ref: http://cobykyros.com - # @note: Be careful with MID\d{3} from MpMan or Manta - ######### - - regex: '; {0,2}(?:CFW-|Kyros )?(MID[0-9]{4}(?:[ABC]|SR|TV)?)(\(3G\)-4G| GB 8K| 3G| 8K| GB)? {0,2}(?:Build|[;\)])' - device_replacement: 'CobyKyros $1$2' - brand_replacement: 'CobyKyros' - model_replacement: '$1$2' - - ######### - # Coolpad - # @ref: ?? - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Cmx + model_replacement: $1 + - regex: ; {0,2}(?:CFW-|Kyros )?(MID[0-9]{4}(?:[ABC]|SR|TV)?)(\(3G\)-4G| GB 8K| + 3G| 8K| GB)? {0,2}(?:Build|[;\)]) + device_replacement: CobyKyros $1$2 + brand_replacement: CobyKyros + model_replacement: $1$2 - regex: '; {0,2}([^;/]{0,50})Coolpad[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Coolpad' - model_replacement: '$1$2' - - ######### - # Cube - # @ref: http://www.cube-tablet.com/buy-products.html - ######### + device_replacement: $1$2 + brand_replacement: Coolpad + model_replacement: $1$2 - regex: '; {0,2}(CUBE[ _])?([KU][0-9]+ ?GT.{0,200}?|A5300)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1$2' - brand_replacement: 'Cube' - model_replacement: '$2' - - ######### - # Cubot - # @ref: http://www.cubotmall.com/ - ######### + regex_flag: i + device_replacement: $1$2 + brand_replacement: Cube + model_replacement: $2 - regex: '; {0,2}CUBOT ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Cubot' - model_replacement: '$1' + regex_flag: i + device_replacement: $1 + brand_replacement: Cubot + model_replacement: $1 - regex: '; {0,2}(BOBBY)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Cubot' - model_replacement: '$1' - - ######### - # Danew - # @ref: http://www.danew.com/produits-tablette.php - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Cubot + model_replacement: $1 - regex: '; {0,2}(Dslide [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Danew' - model_replacement: '$1' - - ######### - # Dell - # @ref: http://www.dell.com - # @ref: http://www.softbank.jp/mobile/support/product/101dl/ - # @ref: http://www.softbank.jp/mobile/support/product/001dl/ - # @ref: http://developer.emnet.ne.jp/android.html - # @ref: http://www.dell.com/in/p/mobile-xcd28/pd - # @ref: http://www.dell.com/in/p/mobile-xcd35/pd - ######### + device_replacement: $1 + brand_replacement: Danew + model_replacement: $1 - regex: '; {0,2}(XCD)[ _]?(28|35)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1$2' - brand_replacement: 'Dell' - model_replacement: '$1$2' + device_replacement: Dell $1$2 + brand_replacement: Dell + model_replacement: $1$2 - regex: '; {0,2}(001DL)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: 'Streak' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: Streak - regex: '; {0,2}(?:Dell|DELL) (Streak)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: 'Streak' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: Streak - regex: '; {0,2}(101DL|GS01|Streak Pro[^;/]{0,100})(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: 'Streak Pro' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: Streak Pro - regex: '; {0,2}([Ss]treak ?7)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: 'Streak 7' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: Streak 7 - regex: '; {0,2}(Mini-3iX)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: '$1' - - regex: '; {0,2}(?:Dell|DELL)[ _](Aero|Venue|Thunder|Mini.{0,200}?|Streak[ _]Pro)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: '$1' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: $1 + - regex: '; {0,2}(?:Dell|DELL)[ _](Aero|Venue|Thunder|Mini.{0,200}?|Streak[ _]Pro)(?: + Build|\) AppleWebKit)' + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: $1 - regex: '; {0,2}Dell[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: '$1' - - ######### - # Denver - # @ref: http://www.denver-electronics.com/tablets1/ - ######### + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: $1 - regex: '; {0,2}(TA[CD]-\d+[^;/]{0,100})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Denver' - model_replacement: '$1' - - ######### - # Dex - # @ref: http://dex.ua/ - ######### + device_replacement: $1 + brand_replacement: Denver + model_replacement: $1 - regex: '; {0,2}(iP[789]\d{2}(?:-3G)?|IP10\d{2}(?:-8GB)?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Dex' - model_replacement: '$1' - - ######### - # DNS AirTab - # @ref: http://www.dns-shop.ru/ - ######### + device_replacement: $1 + brand_replacement: Dex + model_replacement: $1 - regex: '; {0,2}(AirTab)[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'DNS' - model_replacement: '$1 $2' - - ######### - # Docomo (Operator Branded Device) - # @ref: http://www.ipentec.com/document/document.aspx?page=android-useragent - ######### + device_replacement: $1 $2 + brand_replacement: DNS + model_replacement: $1 $2 - regex: '; {0,2}(F\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Fujitsu' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Fujitsu + model_replacement: $1 - regex: '; {0,2}(HT-03A)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'Magic' + device_replacement: $1 + brand_replacement: HTC + model_replacement: Magic - regex: '; {0,2}(HT\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: HTC + model_replacement: $1 - regex: '; {0,2}(L\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'LG' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: LG + model_replacement: $1 - regex: '; {0,2}(N\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Nec' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Nec + model_replacement: $1 - regex: '; {0,2}(P\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Panasonic' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Panasonic + model_replacement: $1 - regex: '; {0,2}(SC\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Samsung' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Samsung + model_replacement: $1 - regex: '; {0,2}(SH\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sharp' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Sharp + model_replacement: $1 - regex: '; {0,2}(SO\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'SonyEricsson' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: SonyEricsson + model_replacement: $1 - regex: '; {0,2}(T\-0[12][^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Toshiba' - model_replacement: '$1' - - ######### - # DOOV - # @ref: http://www.doov.com.cn/ - ######### + device_replacement: $1 + brand_replacement: Toshiba + model_replacement: $1 - regex: '; {0,2}(DOOV)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'DOOV' - model_replacement: '$2' - - ######### - # Enot - # @ref: http://www.enot.ua/ - ######### + device_replacement: $1 $2 + brand_replacement: DOOV + model_replacement: $2 - regex: '; {0,2}(Enot|ENOT)[ -]?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Enot' - model_replacement: '$2' - - ######### - # Evercoss - # @ref: http://evercoss.com/android/ - ######### - - regex: '; {0,2}[^;/]{1,100} Build/(?:CROSS|Cross)+[ _\-]([^\)]+)' - device_replacement: 'CROSS $1' - brand_replacement: 'Evercoss' - model_replacement: 'Cross $1' + device_replacement: $1 $2 + brand_replacement: Enot + model_replacement: $2 + - regex: ; {0,2}[^;/]{1,100} Build/(?:CROSS|Cross)+[ _\-]([^\)]+) + device_replacement: CROSS $1 + brand_replacement: Evercoss + model_replacement: Cross $1 - regex: '; {0,2}(CROSS|Cross)[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Evercoss' - model_replacement: 'Cross $2' - - ######### - # Explay - # @ref: http://explay.ru/ - ######### - - regex: '; {0,2}Explay[_ ](.{1,200}?)(?:[\)]| Build)' - device_replacement: '$1' - brand_replacement: 'Explay' - model_replacement: '$1' - - ######### - # Fly - # @ref: http://www.fly-phone.com/ - ######### + device_replacement: $1 $2 + brand_replacement: Evercoss + model_replacement: Cross $2 + - regex: ; {0,2}Explay[_ ](.{1,200}?)(?:[\)]| Build) + device_replacement: $1 + brand_replacement: Explay + model_replacement: $1 - regex: '; {0,2}(IQ.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Fly' - model_replacement: '$1' - - regex: '; {0,2}(Fly|FLY)[ _](IQ[^;]{1,100}?|F[34]\d+[^;]{0,100}?);?(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Fly' - model_replacement: '$2' - - ######### - # Fujitsu - # @ref: http://www.fujitsu.com/global/ - ######### + device_replacement: $1 + brand_replacement: Fly + model_replacement: $1 + - regex: '; {0,2}(Fly|FLY)[ _](IQ[^;]{1,100}?|F[34]\d+[^;]{0,100}?);?(?: Build|\) + AppleWebKit)' + device_replacement: $1 $2 + brand_replacement: Fly + model_replacement: $2 - regex: '; {0,2}(M532|Q572|FJL21)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Fujitsu' - model_replacement: '$1' - - ######### - # Galapad - # @ref: http://www.galapad.net/product.html - ######### + device_replacement: $1 + brand_replacement: Fujitsu + model_replacement: $1 - regex: '; {0,2}(G1)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Galapad' - model_replacement: '$1' - - ######### - # Geeksphone - # @ref: http://www.geeksphone.com/ - ######### + device_replacement: $1 + brand_replacement: Galapad + model_replacement: $1 - regex: '; {0,2}(Geeksphone) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Gfive - # @ref: http://www.gfivemobile.com/en - ######### + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(G[^F]?FIVE) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Gfive' - model_replacement: '$2' - - ######### - # Gionee - # @ref: http://www.gionee.com/ - ######### + device_replacement: $1 $2 + brand_replacement: Gfive + model_replacement: $2 - regex: '; {0,2}(Gionee)[ _\-]([^;/]{1,100}?)(?:/[^;/]{1,100}|)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Gionee' - model_replacement: '$2' + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Gionee + model_replacement: $2 - regex: '; {0,2}(GN\d+[A-Z]?|INFINITY_PASSION|Ctrl_V1)(?: Build|\) AppleWebKit)' - device_replacement: 'Gionee $1' - brand_replacement: 'Gionee' - model_replacement: '$1' - - regex: '; {0,2}(E3) Build/JOP40D' - device_replacement: 'Gionee $1' - brand_replacement: 'Gionee' - model_replacement: '$1' - - regex: '\sGIONEE[-\s_](\w*)' - regex_flag: 'i' - device_replacement: 'Gionee $1' - brand_replacement: 'Gionee' - model_replacement: '$1' - - ######### - # GoClever - # @ref: http://www.goclever.com - ######### - - regex: '; {0,2}((?:FONE|QUANTUM|INSIGNIA) \d+[^;/]{0,100}|PLAYTAB)(?: Build|\) AppleWebKit)' - device_replacement: 'GoClever $1' - brand_replacement: 'GoClever' - model_replacement: '$1' + device_replacement: Gionee $1 + brand_replacement: Gionee + model_replacement: $1 + - regex: ; {0,2}(E3) Build/JOP40D + device_replacement: Gionee $1 + brand_replacement: Gionee + model_replacement: $1 + - regex: \sGIONEE[-\s_](\w*) + regex_flag: i + device_replacement: Gionee $1 + brand_replacement: Gionee + model_replacement: $1 + - regex: '; {0,2}((?:FONE|QUANTUM|INSIGNIA) \d+[^;/]{0,100}|PLAYTAB)(?: Build|\) + AppleWebKit)' + device_replacement: GoClever $1 + brand_replacement: GoClever + model_replacement: $1 - regex: '; {0,2}GOCLEVER ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'GoClever $1' - brand_replacement: 'GoClever' - model_replacement: '$1' - - ######### - # Google - # @ref: http://www.google.de/glass/start/ - ######### + device_replacement: GoClever $1 + brand_replacement: GoClever + model_replacement: $1 - regex: '; {0,2}(Glass \d+)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Google' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Google + model_replacement: $1 - regex: '; {0,2}([g|G]oogle)? (Pixel[ a-zA-z0-9]{1,100});(?: Build|.{0,50}\) AppleWebKit)' - device_replacement: '$2' - brand_replacement: 'Google' - model_replacement: '$2' + device_replacement: $2 + brand_replacement: Google + model_replacement: $2 - regex: '; {0,2}([g|G]oogle)? (Pixel.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$2' - brand_replacement: 'Google' - model_replacement: '$2' - - ######### - # Gigabyte - # @ref: http://gsmart.gigabytecm.com/en/ - ######### + device_replacement: $2 + brand_replacement: Google + model_replacement: $2 - regex: '; {0,2}(GSmart)[ -]([^/]{1,50})(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Gigabyte' - model_replacement: '$1 $2' - - ######### - # Freescale development boards - # @ref: http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=IMX53QSB - ######### + device_replacement: $1 $2 + brand_replacement: Gigabyte + model_replacement: $1 $2 - regex: '; {0,2}(imx5[13]_[^/]{1,50})(?: Build|\) AppleWebKit)' - device_replacement: 'Freescale $1' - brand_replacement: 'Freescale' - model_replacement: '$1' - - ######### - # Haier - # @ref: http://www.haier.com/ - # @ref: http://www.haier.com/de/produkte/tablet/ - ######### + device_replacement: Freescale $1 + brand_replacement: Freescale + model_replacement: $1 - regex: '; {0,2}Haier[ _\-]([^/]{1,50})(?: Build|\) AppleWebKit)' - device_replacement: 'Haier $1' - brand_replacement: 'Haier' - model_replacement: '$1' + device_replacement: Haier $1 + brand_replacement: Haier + model_replacement: $1 - regex: '; {0,2}(PAD1016)(?: Build|\) AppleWebKit)' - device_replacement: 'Haipad $1' - brand_replacement: 'Haipad' - model_replacement: '$1' - - ######### - # Haipad - # @ref: http://www.haipad.net/ - # @models: V7P|M7SM7S|M9XM9X|M7XM7X|M9|M8|M7-M|M1002|M7|M701 - ######### + device_replacement: Haipad $1 + brand_replacement: Haipad + model_replacement: $1 - regex: '; {0,2}(M701|M7|M8|M9)(?: Build|\) AppleWebKit)' - device_replacement: 'Haipad $1' - brand_replacement: 'Haipad' - model_replacement: '$1' - - ######### - # Hannspree - # @ref: http://www.hannspree.eu/ - # @models: SN10T1|SN10T2|SN70T31B|SN70T32W - ######### + device_replacement: Haipad $1 + brand_replacement: Haipad + model_replacement: $1 - regex: '; {0,2}(SN\d+T[^;\)/]*)(?: Build|[;\)])' - device_replacement: 'Hannspree $1' - brand_replacement: 'Hannspree' - model_replacement: '$1' - - ######### - # HCLme - # @ref: http://www.hclmetablet.com/india/ - ######### - - regex: 'Build/HCL ME Tablet ([^;\)]{1,3})[\);]' - device_replacement: 'HCLme $1' - brand_replacement: 'HCLme' - model_replacement: '$1' - - regex: '; {0,2}([^;\/]+) Build/HCL' - device_replacement: 'HCLme $1' - brand_replacement: 'HCLme' - model_replacement: '$1' - - ######### - # Hena - # @ref: http://www.henadigital.com/en/product/index.asp?id=6 - ######### + device_replacement: Hannspree $1 + brand_replacement: Hannspree + model_replacement: $1 + - regex: Build/HCL ME Tablet ([^;\)]{1,3})[\);] + device_replacement: HCLme $1 + brand_replacement: HCLme + model_replacement: $1 + - regex: ; {0,2}([^;\/]+) Build/HCL + device_replacement: HCLme $1 + brand_replacement: HCLme + model_replacement: $1 - regex: '; {0,2}(MID-?\d{4}C[EM])(?: Build|\) AppleWebKit)' - device_replacement: 'Hena $1' - brand_replacement: 'Hena' - model_replacement: '$1' - - ######### - # Hisense - # @ref: http://www.hisense.com/ - ######### + device_replacement: Hena $1 + brand_replacement: Hena + model_replacement: $1 - regex: '; {0,2}(EG\d{2,}|HS-[^;/]{1,100}|MIRA[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Hisense $1' - brand_replacement: 'Hisense' - model_replacement: '$1' + device_replacement: Hisense $1 + brand_replacement: Hisense + model_replacement: $1 - regex: '; {0,2}(andromax[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Hisense $1' - brand_replacement: 'Hisense' - model_replacement: '$1' - - ######### - # hitech - # @ref: http://www.hitech-mobiles.com/ - ######### + regex_flag: i + device_replacement: Hisense $1 + brand_replacement: Hisense + model_replacement: $1 - regex: '; {0,2}(?:AMAZE[ _](S\d+)|(S\d+)[ _]AMAZE)(?: Build|\) AppleWebKit)' - device_replacement: 'AMAZE $1$2' - brand_replacement: 'hitech' - model_replacement: 'AMAZE $1$2' - - ######### - # HP - # @ref: http://www.hp.com/ - ######### + device_replacement: AMAZE $1$2 + brand_replacement: hitech + model_replacement: AMAZE $1$2 - regex: '; {0,2}(PlayBook)(?: Build|\) AppleWebKit)' - device_replacement: 'HP $1' - brand_replacement: 'HP' - model_replacement: '$1' + device_replacement: HP $1 + brand_replacement: HP + model_replacement: $1 - regex: '; {0,2}HP ([^/]{1,50})(?: Build|\) AppleWebKit)' - device_replacement: 'HP $1' - brand_replacement: 'HP' - model_replacement: '$1' + device_replacement: HP $1 + brand_replacement: HP + model_replacement: $1 - regex: '; {0,2}([^/]{1,30}_tenderloin)(?: Build|\) AppleWebKit)' - device_replacement: 'HP TouchPad' - brand_replacement: 'HP' - model_replacement: 'TouchPad' - - ######### - # Huawei - # @ref: http://www.huaweidevice.com - # @note: Needs to be before HTC due to Desire HD Build on U8815 - ######### - - regex: '; {0,2}(HUAWEI |Huawei-|)([UY][^;/]{1,100}) Build/(?:Huawei|HUAWEI)([UY][^\);]+)\)' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}([^;/]{1,100}) Build[/ ]Huawei(MT1-U06|[A-Z]{1,50}\d+[^\);]{1,50})\)' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}(S7|M860) Build' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: '; {0,2}((?:HUAWEI|Huawei)[ \-]?)(MediaPad) Build' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}((?:HUAWEI[ _]?|Huawei[ _]|)Ascend[ _])([^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}((?:HUAWEI|Huawei)[ _\-]?)((?:G700-|MT-)[^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}((?:HUAWEI|Huawei)[ _\-]?)([^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: '$2' - - regex: '; {0,2}(MediaPad[^;]{1,200}|SpringBoard) Build/Huawei' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: '; {0,2}([^;]{1,200}) Build/(?:Huawei|HUAWEI)' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: '; {0,2}([Uu])([89]\d{3}) Build' - device_replacement: '$1$2' - brand_replacement: 'Huawei' - model_replacement: 'U$2' - - regex: '; {0,2}(?:Ideos |IDEOS )(S7) Build' - device_replacement: 'Huawei Ideos$1' - brand_replacement: 'Huawei' - model_replacement: 'Ideos$1' - - regex: '; {0,2}(?:Ideos |IDEOS )([^;/]{1,50}\s{0,5}|\s{0,5})Build' - device_replacement: 'Huawei Ideos$1' - brand_replacement: 'Huawei' - model_replacement: 'Ideos$1' - - regex: '; {0,2}(Orange Daytona|Pulse|Pulse Mini|Vodafone 858|C8500|C8600|C8650|C8660|Nexus 6P|ATH-.{1,200}?) Build[/ ]' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: '; {0,2}((?:[A-Z]{3})\-L[A-Za0-9]{2})[\)]' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: '; {0,2}([^;]{1,200}) Build/(HONOR|Honor)' - device_replacement: 'Huawei Honor $1' - brand_replacement: 'Huawei' - model_replacement: 'Honor $1' - - ######### - # HTC - # @ref: http://www.htc.com/www/products/ - # @ref: http://en.wikipedia.org/wiki/List_of_HTC_phones - ######### - - - regex: '; {0,2}HTC[ _]([^;]{1,200}); Windows Phone' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - # Android HTC with Version Number matcher - # ; HTC_0P3Z11/1.12.161.3 Build - # ;HTC_A3335 V2.38.841.1 Build + device_replacement: HP TouchPad + brand_replacement: HP + model_replacement: TouchPad + - regex: ; {0,2}(HUAWEI |Huawei-|)([UY][^;/]{1,100}) Build/(?:Huawei|HUAWEI)([UY][^\);]+)\) + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}([^;/]{1,100}) Build[/ ]Huawei(MT1-U06|[A-Z]{1,50}\d+[^\);]{1,50})\) + device_replacement: $1 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}(S7|M860) Build + device_replacement: $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: ; {0,2}((?:HUAWEI|Huawei)[ \-]?)(MediaPad) Build + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}((?:HUAWEI[ _]?|Huawei[ _]|)Ascend[ _])([^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}((?:HUAWEI|Huawei)[ _\-]?)((?:G700-|MT-)[^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}((?:HUAWEI|Huawei)[ _\-]?)([^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: $2 + - regex: ; {0,2}(MediaPad[^;]{1,200}|SpringBoard) Build/Huawei + device_replacement: $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: ; {0,2}([^;]{1,200}) Build/(?:Huawei|HUAWEI) + device_replacement: $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: ; {0,2}([Uu])([89]\d{3}) Build + device_replacement: $1$2 + brand_replacement: Huawei + model_replacement: U$2 + - regex: ; {0,2}(?:Ideos |IDEOS )(S7) Build + device_replacement: Huawei Ideos$1 + brand_replacement: Huawei + model_replacement: Ideos$1 + - regex: ; {0,2}(?:Ideos |IDEOS )([^;/]{1,50}\s{0,5}|\s{0,5})Build + device_replacement: Huawei Ideos$1 + brand_replacement: Huawei + model_replacement: Ideos$1 + - regex: ; {0,2}(Orange Daytona|Pulse|Pulse Mini|Vodafone 858|C8500|C8600|C8650|C8660|Nexus + 6P|ATH-.{1,200}?) Build[/ ] + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: ; {0,2}((?:[A-Z]{3})\-L[A-Za0-9]{2})[\)] + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: ; {0,2}([^;]{1,200}) Build/(HONOR|Honor) + device_replacement: Huawei Honor $1 + brand_replacement: Huawei + model_replacement: Honor $1 + - regex: ; {0,2}HTC[ _]([^;]{1,200}); Windows Phone + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' - device_replacement: 'HTC $1 $2' - brand_replacement: 'HTC' - model_replacement: '$1 $2' - - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)|)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' - device_replacement: 'HTC $1 $2 $3' - brand_replacement: 'HTC' - model_replacement: '$1 $2 $3' - - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)|)|)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' - device_replacement: 'HTC $1 $2 $3 $4' - brand_replacement: 'HTC' - model_replacement: '$1 $2 $3 $4' - - # Android HTC without Version Number matcher - - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/;]+)(?: {0,2}Build|[;\)]| - )' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/;\)]+)|)(?: {0,2}Build|[;\)]| - )' - device_replacement: 'HTC $1 $2' - brand_replacement: 'HTC' - model_replacement: '$1 $2' - - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/;\)]+)|)|)(?: {0,2}Build|[;\)]| - )' - device_replacement: 'HTC $1 $2 $3' - brand_replacement: 'HTC' - model_replacement: '$1 $2 $3' - - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ /;]+)|)|)|)(?: {0,2}Build|[;\)]| - )' - device_replacement: 'HTC $1 $2 $3 $4' - brand_replacement: 'HTC' - model_replacement: '$1 $2 $3 $4' - - # HTC Streaming Player - - regex: 'HTC Streaming Player [^\/]{0,30}/[^\/]{0,10}/ htc_([^/]{1,10}) /' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - # general matcher for anything else - - regex: '(?:[;,] {0,2}|^)(?:htccn_chs-|)HTC[ _-]?([^;]{1,200}?)(?: {0,2}Build|clay|Android|-?Mozilla| Opera| Profile| UNTRUSTED|[;/\(\)]|$)' - regex_flag: 'i' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - # Android matchers without HTC - - regex: '; {0,2}(A6277|ADR6200|ADR6300|ADR6350|ADR6400[A-Z]*|ADR6425[A-Z]*|APX515CKT|ARIA|Desire[^_ ]*|Dream|EndeavorU|Eris|Evo|Flyer|HD2|Hero|HERO200|Hero CDMA|HTL21|Incredible|Inspire[A-Z0-9]*|Legend|Liberty|Nexus ?(?:One|HD2)|One|One S C2|One[ _]?(?:S|V|X\+?)\w*|PC36100|PG06100|PG86100|S31HT|Sensation|Wildfire)(?: Build|[/;\(\)])' - regex_flag: 'i' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - regex: '; {0,2}(ADR6200|ADR6400L|ADR6425LVW|Amaze|DesireS?|EndeavorU|Eris|EVO|Evo\d[A-Z]+|HD2|IncredibleS?|Inspire[A-Z0-9]*|Inspire[A-Z0-9]*|Sensation[A-Z0-9]*|Wildfire)[ _-](.{1,200}?)(?:[/;\)]|Build|MIUI|1\.0)' - regex_flag: 'i' - device_replacement: 'HTC $1 $2' - brand_replacement: 'HTC' - model_replacement: '$1 $2' - - ######### - # Hyundai - # @ref: http://www.hyundaitechnologies.com - ######### + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: + {0,2}Build|\))' + device_replacement: HTC $1 $2 + brand_replacement: HTC + model_replacement: $1 $2 + - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)|)|)(?:[/\\]1\.0 + | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' + device_replacement: HTC $1 $2 $3 + brand_replacement: HTC + model_replacement: $1 $2 $3 + - regex: '; {0,2}(?:HTC[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ _/]+)(?:[ _/]([^ + _/]+)|)|)|)(?:[/\\]1\.0 | V|/| +)\d+\.\d[\d\.]*(?: {0,2}Build|\))' + device_replacement: HTC $1 $2 $3 $4 + brand_replacement: HTC + model_replacement: $1 $2 $3 $4 + - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/;]+)(?: {0,2}Build|[;\)]| + - )' + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/;\)]+)|)(?: + {0,2}Build|[;\)]| - )' + device_replacement: HTC $1 $2 + brand_replacement: HTC + model_replacement: $1 $2 + - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ + _/]([^ _/;\)]+)|)|)(?: {0,2}Build|[;\)]| - )' + device_replacement: HTC $1 $2 $3 + brand_replacement: HTC + model_replacement: $1 $2 $3 + - regex: '; {0,2}(?:(?:HTC|htc)(?:_blocked|)[ _/])+([^ _/]+)(?:[ _/]([^ _/]+)(?:[ + _/]([^ _/]+)(?:[ _/]([^ /;]+)|)|)|)(?: {0,2}Build|[;\)]| - )' + device_replacement: HTC $1 $2 $3 $4 + brand_replacement: HTC + model_replacement: $1 $2 $3 $4 + - regex: HTC Streaming Player [^\/]{0,30}/[^\/]{0,10}/ htc_([^/]{1,10}) / + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: '(?:[;,] {0,2}|^)(?:htccn_chs-|)HTC[ _-]?([^;]{1,200}?)(?: {0,2}Build|clay|Android|-?Mozilla| + Opera| Profile| UNTRUSTED|[;/\(\)]|$)' + regex_flag: i + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: '; {0,2}(A6277|ADR6200|ADR6300|ADR6350|ADR6400[A-Z]*|ADR6425[A-Z]*|APX515CKT|ARIA|Desire[^_ + ]*|Dream|EndeavorU|Eris|Evo|Flyer|HD2|Hero|HERO200|Hero CDMA|HTL21|Incredible|Inspire[A-Z0-9]*|Legend|Liberty|Nexus + ?(?:One|HD2)|One|One S C2|One[ _]?(?:S|V|X\+?)\w*|PC36100|PG06100|PG86100|S31HT|Sensation|Wildfire)(?: + Build|[/;\(\)])' + regex_flag: i + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: ; {0,2}(ADR6200|ADR6400L|ADR6425LVW|Amaze|DesireS?|EndeavorU|Eris|EVO|Evo\d[A-Z]+|HD2|IncredibleS?|Inspire[A-Z0-9]*|Inspire[A-Z0-9]*|Sensation[A-Z0-9]*|Wildfire)[ + _-](.{1,200}?)(?:[/;\)]|Build|MIUI|1\.0) + regex_flag: i + device_replacement: HTC $1 $2 + brand_replacement: HTC + model_replacement: $1 $2 - regex: '; {0,2}HYUNDAI (T\d[^/]{0,10})(?: Build|\) AppleWebKit)' - device_replacement: 'Hyundai $1' - brand_replacement: 'Hyundai' - model_replacement: '$1' + device_replacement: Hyundai $1 + brand_replacement: Hyundai + model_replacement: $1 - regex: '; {0,2}HYUNDAI ([^;/]{1,10}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Hyundai $1' - brand_replacement: 'Hyundai' - model_replacement: '$1' - # X900? http://www.amazon.com/Hyundai-X900-Retina-Android-Bluetooth/dp/B00AO07H3O + device_replacement: Hyundai $1 + brand_replacement: Hyundai + model_replacement: $1 - regex: '; {0,2}(X700|Hold X|MB-6900)(?: Build|\) AppleWebKit)' - device_replacement: 'Hyundai $1' - brand_replacement: 'Hyundai' - model_replacement: '$1' - - ######### - # iBall - # @ref: http://www.iball.co.in/Category/Mobiles/22 - ######### + device_replacement: Hyundai $1 + brand_replacement: Hyundai + model_replacement: $1 - regex: '; {0,2}(?:iBall[ _\-]|)(Andi)[ _]?(\d[^;/]*)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'iBall' - model_replacement: '$1 $2' + regex_flag: i + device_replacement: $1 $2 + brand_replacement: iBall + model_replacement: $1 $2 - regex: '; {0,2}(IBall)(?:[ _]([^;/]{1,100}?)|)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'iBall' - model_replacement: '$2' - - ######### - # IconBIT - # @ref: http://www.iconbit.com/catalog/tablets/ - ######### - - regex: '; {0,2}(NT-\d+[^ ;/]{0,50}|Net[Tt]AB [^;/]{1,50}|Mercury [A-Z]{1,50}|iconBIT)(?: S/N:[^;/]{1,50}|)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'IconBIT' - model_replacement: '$1' - - ######### - # IMO - # @ref: http://www.ponselimo.com/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: iBall + model_replacement: $2 + - regex: '; {0,2}(NT-\d+[^ ;/]{0,50}|Net[Tt]AB [^;/]{1,50}|Mercury [A-Z]{1,50}|iconBIT)(?: + S/N:[^;/]{1,50}|)(?: Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: IconBIT + model_replacement: $1 - regex: '; {0,2}(IMO)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'IMO' - model_replacement: '$2' - - ######### - # i-mobile - # @ref: http://www.i-mobilephone.com/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: IMO + model_replacement: $2 - regex: '; {0,2}i-?mobile[ _]([^/]{1,50})(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'i-mobile $1' - brand_replacement: 'imobile' - model_replacement: '$1' + regex_flag: i + device_replacement: i-mobile $1 + brand_replacement: imobile + model_replacement: $1 - regex: '; {0,2}(i-(?:style|note)[^/]{0,10})(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'i-mobile $1' - brand_replacement: 'imobile' - model_replacement: '$1' - - ######### - # Impression - # @ref: http://impression.ua/planshetnye-kompyutery - ######### + regex_flag: i + device_replacement: i-mobile $1 + brand_replacement: imobile + model_replacement: $1 - regex: '; {0,2}(ImPAD) ?(\d+(?:.){0,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Impression' - model_replacement: '$1 $2' - - ######### - # Infinix - # @ref: http://www.infinixmobility.com/index.html - ######### + device_replacement: $1 $2 + brand_replacement: Impression + model_replacement: $1 $2 - regex: '; {0,2}(Infinix)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Infinix' - model_replacement: '$2' - - ######### - # Informer - # @ref: ?? - ######### + device_replacement: $1 $2 + brand_replacement: Infinix + model_replacement: $2 - regex: '; {0,2}(Informer)[ \-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Informer' - model_replacement: '$2' - - ######### - # Intenso - # @ref: http://www.intenso.de - # @models: 7":TAB 714,TAB 724;8":TAB 814,TAB 824;10":TAB 1004 - ######### + device_replacement: $1 $2 + brand_replacement: Informer + model_replacement: $2 - regex: '; {0,2}(TAB) ?([78][12]4)(?: Build|\) AppleWebKit)' - device_replacement: 'Intenso $1' - brand_replacement: 'Intenso' - model_replacement: '$1 $2' - - ######### - # Intex - # @ref: http://intexmobile.in/index.aspx - # @note: Zync also offers a "Cloud Z5" device - ######### - # smartphones - - regex: '; {0,2}(?:Intex[ _]|)(AQUA|Aqua)([ _\.\-])([^;/]{1,100}?) {0,2}(?:Build|;)' - device_replacement: '$1$2$3' - brand_replacement: 'Intex' - model_replacement: '$1 $3' - # matches "INTEX CLOUD X1" - - regex: '; {0,2}(?:INTEX|Intex)(?:[_ ]([^\ _;/]+))(?:[_ ]([^\ _;/]+)|) {0,2}(?:Build|;)' - device_replacement: '$1 $2' - brand_replacement: 'Intex' - model_replacement: '$1 $2' - # tablets - - regex: '; {0,2}([iI]Buddy)[ _]?(Connect)(?:_|\?_| |)([^;/]{0,50}) {0,2}(?:Build|;)' - device_replacement: '$1 $2 $3' - brand_replacement: 'Intex' - model_replacement: 'iBuddy $2 $3' - - regex: '; {0,2}(I-Buddy)[ _]([^;/]{1,100}?) {0,2}(?:Build|;)' - device_replacement: '$1 $2' - brand_replacement: 'Intex' - model_replacement: 'iBuddy $2' - - ######### - # iOCEAN - # @ref: http://www.iocean.cc/ - ######### + device_replacement: Intenso $1 + brand_replacement: Intenso + model_replacement: $1 $2 + - regex: ; {0,2}(?:Intex[ _]|)(AQUA|Aqua)([ _\.\-])([^;/]{1,100}?) {0,2}(?:Build|;) + device_replacement: $1$2$3 + brand_replacement: Intex + model_replacement: $1 $3 + - regex: ; {0,2}(?:INTEX|Intex)(?:[_ ]([^\ _;/]+))(?:[_ ]([^\ _;/]+)|) {0,2}(?:Build|;) + device_replacement: $1 $2 + brand_replacement: Intex + model_replacement: $1 $2 + - regex: ; {0,2}([iI]Buddy)[ _]?(Connect)(?:_|\?_| |)([^;/]{0,50}) {0,2}(?:Build|;) + device_replacement: $1 $2 $3 + brand_replacement: Intex + model_replacement: iBuddy $2 $3 + - regex: ; {0,2}(I-Buddy)[ _]([^;/]{1,100}?) {0,2}(?:Build|;) + device_replacement: $1 $2 + brand_replacement: Intex + model_replacement: iBuddy $2 - regex: '; {0,2}(iOCEAN) ([^/]{1,50})(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'iOCEAN' - model_replacement: '$2' - - ######### - # i.onik - # @ref: http://www.i-onik.de/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: iOCEAN + model_replacement: $2 - regex: '; {0,2}(TP\d+(?:\.\d+|)\-\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'ionik $1' - brand_replacement: 'ionik' - model_replacement: '$1' - - ######### - # IRU.ru - # @ref: http://www.iru.ru/catalog/soho/planetable/ - ######### + device_replacement: ionik $1 + brand_replacement: ionik + model_replacement: $1 - regex: '; {0,2}(M702pro)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Iru' - model_replacement: '$1' - - ######### - # Itel Mobile - # @ref: https://www.itel-mobile.com/global/products/ - ######### + device_replacement: $1 + brand_replacement: Iru + model_replacement: $1 - regex: '; {0,2}itel ([^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'Itel $1' - brand_replacement: 'Itel' - model_replacement: '$1' - - ######### - # Ivio - # @ref: http://www.ivio.com/mobile.php - # @models: DG80,DG20,DE38,DE88,MD70 - ######### + device_replacement: Itel $1 + brand_replacement: Itel + model_replacement: $1 - regex: '; {0,2}(DE88Plus|MD70)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Ivio' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Ivio + model_replacement: $1 - regex: '; {0,2}IVIO[_\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Ivio' - model_replacement: '$1' - - ######### - # Jaytech - # @ref: http://www.jay-tech.de/jaytech/servlet/frontend/ - ######### + device_replacement: $1 + brand_replacement: Ivio + model_replacement: $1 - regex: '; {0,2}(TPC-\d+|JAY-TECH)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Jaytech' - model_replacement: '$1' - - ######### - # Jiayu - # @ref: http://www.ejiayu.com/en/Product.html - ######### + device_replacement: $1 + brand_replacement: Jaytech + model_replacement: $1 - regex: '; {0,2}(JY-[^;/]{1,100}|G[234]S?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Jiayu' - model_replacement: '$1' - - ######### - # JXD - # @ref: http://www.jxd.hk/ - ######### + device_replacement: $1 + brand_replacement: Jiayu + model_replacement: $1 - regex: '; {0,2}(JXD)[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'JXD' - model_replacement: '$2' - - ######### - # Karbonn - # @ref: http://www.karbonnmobiles.com/products_tablet.php - ######### - - regex: '; {0,2}Karbonn[ _]?([^;/]{1,100}) {0,2}(?:Build|;)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Karbonn' - model_replacement: '$1' - - regex: '; {0,2}([^;]{1,200}) Build/Karbonn' - device_replacement: '$1' - brand_replacement: 'Karbonn' - model_replacement: '$1' - - regex: '; {0,2}(A11|A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2|Titanium S\d) +Build' - device_replacement: '$1' - brand_replacement: 'Karbonn' - model_replacement: '$1' - - ######### - # KDDI (Operator Branded Device) - # @ref: http://www.ipentec.com/document/document.aspx?page=android-useragent - ######### + device_replacement: $1 $2 + brand_replacement: JXD + model_replacement: $2 + - regex: ; {0,2}Karbonn[ _]?([^;/]{1,100}) {0,2}(?:Build|;) + regex_flag: i + device_replacement: $1 + brand_replacement: Karbonn + model_replacement: $1 + - regex: ; {0,2}([^;]{1,200}) Build/Karbonn + device_replacement: $1 + brand_replacement: Karbonn + model_replacement: $1 + - regex: ; {0,2}(A11|A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2|Titanium S\d) + +Build + device_replacement: $1 + brand_replacement: Karbonn + model_replacement: $1 - regex: '; {0,2}(IS01|IS03|IS05|IS\d{2}SH)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sharp' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Sharp + model_replacement: $1 - regex: '; {0,2}(IS04)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Regza' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Regza + model_replacement: $1 - regex: '; {0,2}(IS06|IS\d{2}PT)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Pantech' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Pantech + model_replacement: $1 - regex: '; {0,2}(IS11S)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'SonyEricsson' - model_replacement: 'Xperia Acro' + device_replacement: $1 + brand_replacement: SonyEricsson + model_replacement: Xperia Acro - regex: '; {0,2}(IS11CA)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Casio' - model_replacement: 'GzOne $1' + device_replacement: $1 + brand_replacement: Casio + model_replacement: GzOne $1 - regex: '; {0,2}(IS11LG)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'LG' - model_replacement: 'Optimus X' + device_replacement: $1 + brand_replacement: LG + model_replacement: Optimus X - regex: '; {0,2}(IS11N)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Medias' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Medias + model_replacement: $1 - regex: '; {0,2}(IS11PT)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Pantech' - model_replacement: 'MIRACH' + device_replacement: $1 + brand_replacement: Pantech + model_replacement: MIRACH - regex: '; {0,2}(IS12F)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Fujitsu' - model_replacement: 'Arrows ES' - # @ref: https://ja.wikipedia.org/wiki/IS12M + device_replacement: $1 + brand_replacement: Fujitsu + model_replacement: Arrows ES - regex: '; {0,2}(IS12M)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Motorola' - model_replacement: 'XT909' + device_replacement: $1 + brand_replacement: Motorola + model_replacement: XT909 - regex: '; {0,2}(IS12S)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'SonyEricsson' - model_replacement: 'Xperia Acro HD' + device_replacement: $1 + brand_replacement: SonyEricsson + model_replacement: Xperia Acro HD - regex: '; {0,2}(ISW11F)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Fujitsu' - model_replacement: 'Arrowz Z' + device_replacement: $1 + brand_replacement: Fujitsu + model_replacement: Arrowz Z - regex: '; {0,2}(ISW11HT)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'EVO' + device_replacement: $1 + brand_replacement: HTC + model_replacement: EVO - regex: '; {0,2}(ISW11K)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Kyocera' - model_replacement: 'DIGNO' + device_replacement: $1 + brand_replacement: Kyocera + model_replacement: DIGNO - regex: '; {0,2}(ISW11M)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Motorola' - model_replacement: 'Photon' + device_replacement: $1 + brand_replacement: Motorola + model_replacement: Photon - regex: '; {0,2}(ISW11SC)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Samsung' - model_replacement: 'GALAXY S II WiMAX' + device_replacement: $1 + brand_replacement: Samsung + model_replacement: GALAXY S II WiMAX - regex: '; {0,2}(ISW12HT)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'EVO 3D' + device_replacement: $1 + brand_replacement: HTC + model_replacement: EVO 3D - regex: '; {0,2}(ISW13HT)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'J' + device_replacement: $1 + brand_replacement: HTC + model_replacement: J - regex: '; {0,2}(ISW?[0-9]{2}[A-Z]{0,2})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'KDDI' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: KDDI + model_replacement: $1 - regex: '; {0,2}(INFOBAR [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'KDDI' - model_replacement: '$1' - - ######### - # Kingcom - # @ref: http://www.e-kingcom.com - ######### + device_replacement: $1 + brand_replacement: KDDI + model_replacement: $1 - regex: '; {0,2}(JOYPAD|Joypad)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Kingcom' - model_replacement: '$1 $2' - - ######### - # Kobo - # @ref: https://en.wikipedia.org/wiki/Kobo_Inc. - # @ref: http://www.kobo.com/devices#tablets - ######### + device_replacement: $1 $2 + brand_replacement: Kingcom + model_replacement: $1 $2 - regex: '; {0,2}(Vox|VOX|Arc|K080)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Kobo' - model_replacement: '$1' - - regex: '\b(Kobo Touch)\b' - device_replacement: '$1' - brand_replacement: 'Kobo' - model_replacement: '$1' - - ######### - # K-Touch - # @ref: ?? - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Kobo + model_replacement: $1 + - regex: \b(Kobo Touch)\b + device_replacement: $1 + brand_replacement: Kobo + model_replacement: $1 - regex: '; {0,2}(K-Touch)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Ktouch' - model_replacement: '$2' - - ######### - # KT Tech - # @ref: http://www.kttech.co.kr - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Ktouch + model_replacement: $2 - regex: '; {0,2}((?:EV|KM)-S\d+[A-Z]?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'KTtech' - model_replacement: '$1' - - ######### - # Kyocera - # @ref: http://www.android.com/devices/?country=all&m=kyocera - ######### - - regex: '; {0,2}(Zio|Hydro|Torque|Event|EVENT|Echo|Milano|Rise|URBANO PROGRESSO|WX04K|WX06K|WX10K|KYL21|101K|C5[12]\d{2})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Kyocera' - model_replacement: '$1' - - ######### - # Lava - # @ref: http://www.lavamobiles.com/ - ######### - - regex: '; {0,2}(?:LAVA[ _]|)IRIS[ _\-]?([^/;\)]+) {0,2}(?:;|\)|Build)' - regex_flag: 'i' - device_replacement: 'Iris $1' - brand_replacement: 'Lava' - model_replacement: 'Iris $1' - - regex: '; {0,2}LAVA[ _]([^;/]{1,100}) Build' - device_replacement: '$1' - brand_replacement: 'Lava' - model_replacement: '$1' - - ######### - # Lemon - # @ref: http://www.lemonmobiles.com/products.php?type=1 - ######### - - regex: '; {0,2}(?:(Aspire A1)|(?:LEMON|Lemon)[ _]([^;/]{1,100}))_?(?: Build|\) AppleWebKit)' - device_replacement: 'Lemon $1$2' - brand_replacement: 'Lemon' - model_replacement: '$1$2' - - ######### - # Lenco - # @ref: http://www.lenco.com/c/tablets/ - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: KTtech + model_replacement: $1 + - regex: '; {0,2}(Zio|Hydro|Torque|Event|EVENT|Echo|Milano|Rise|URBANO PROGRESSO|WX04K|WX06K|WX10K|KYL21|101K|C5[12]\d{2})(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Kyocera + model_replacement: $1 + - regex: ; {0,2}(?:LAVA[ _]|)IRIS[ _\-]?([^/;\)]+) {0,2}(?:;|\)|Build) + regex_flag: i + device_replacement: Iris $1 + brand_replacement: Lava + model_replacement: Iris $1 + - regex: ; {0,2}LAVA[ _]([^;/]{1,100}) Build + device_replacement: $1 + brand_replacement: Lava + model_replacement: $1 + - regex: '; {0,2}(?:(Aspire A1)|(?:LEMON|Lemon)[ _]([^;/]{1,100}))_?(?: Build|\) + AppleWebKit)' + device_replacement: Lemon $1$2 + brand_replacement: Lemon + model_replacement: $1$2 - regex: '; {0,2}(TAB-1012)(?: Build|\) AppleWebKit)' - device_replacement: 'Lenco $1' - brand_replacement: 'Lenco' - model_replacement: '$1' + device_replacement: Lenco $1 + brand_replacement: Lenco + model_replacement: $1 - regex: '; Lenco ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Lenco $1' - brand_replacement: 'Lenco' - model_replacement: '$1' - - ######### - # Lenovo - # @ref: http://support.lenovo.com/en_GB/downloads/default.page?# - ######### - - regex: '; {0,2}(A1_07|A2107A-H|S2005A-H|S1-37AH0) Build' - device_replacement: '$1' - brand_replacement: 'Lenovo' - model_replacement: '$1' - - regex: '; {0,2}(Idea[Tp]ab)[ _]([^;/]{1,100});? Build' - device_replacement: 'Lenovo $1 $2' - brand_replacement: 'Lenovo' - model_replacement: '$1 $2' - - regex: '; {0,2}(Idea(?:Tab|pad)) ?([^;/]{1,100}) Build' - device_replacement: 'Lenovo $1 $2' - brand_replacement: 'Lenovo' - model_replacement: '$1 $2' - - regex: '; {0,2}(ThinkPad) ?(Tablet) Build/' - device_replacement: 'Lenovo $1 $2' - brand_replacement: 'Lenovo' - model_replacement: '$1 $2' - - regex: '; {0,2}(?:LNV-|)(?:=?[Ll]enovo[ _\-]?|LENOVO[ _])(.{1,200}?)(?:Build|[;/\)])' - device_replacement: 'Lenovo $1' - brand_replacement: 'Lenovo' - model_replacement: '$1' + device_replacement: Lenco $1 + brand_replacement: Lenco + model_replacement: $1 + - regex: ; {0,2}(A1_07|A2107A-H|S2005A-H|S1-37AH0) Build + device_replacement: $1 + brand_replacement: Lenovo + model_replacement: $1 + - regex: ; {0,2}(Idea[Tp]ab)[ _]([^;/]{1,100});? Build + device_replacement: Lenovo $1 $2 + brand_replacement: Lenovo + model_replacement: $1 $2 + - regex: ; {0,2}(Idea(?:Tab|pad)) ?([^;/]{1,100}) Build + device_replacement: Lenovo $1 $2 + brand_replacement: Lenovo + model_replacement: $1 $2 + - regex: ; {0,2}(ThinkPad) ?(Tablet) Build/ + device_replacement: Lenovo $1 $2 + brand_replacement: Lenovo + model_replacement: $1 $2 + - regex: ; {0,2}(?:LNV-|)(?:=?[Ll]enovo[ _\-]?|LENOVO[ _])(.{1,200}?)(?:Build|[;/\)]) + device_replacement: Lenovo $1 + brand_replacement: Lenovo + model_replacement: $1 - regex: '[;,] (?:Vodafone |)(SmartTab) ?(II) ?(\d+) Build/' - device_replacement: 'Lenovo $1 $2 $3' - brand_replacement: 'Lenovo' - model_replacement: '$1 $2 $3' - - regex: '; {0,2}(?:Ideapad |)K1 Build/' - device_replacement: 'Lenovo Ideapad K1' - brand_replacement: 'Lenovo' - model_replacement: 'Ideapad K1' - - regex: '; {0,2}(3GC101|3GW10[01]|A390) Build/' - device_replacement: '$1' - brand_replacement: 'Lenovo' - model_replacement: '$1' - - regex: '\b(?:Lenovo|LENOVO)+[ _\-]?([^,;:/ ]+)' - device_replacement: 'Lenovo $1' - brand_replacement: 'Lenovo' - model_replacement: '$1' - - ######### - # Lexibook - # @ref: http://www.lexibook.com/fr - ######### + device_replacement: Lenovo $1 $2 $3 + brand_replacement: Lenovo + model_replacement: $1 $2 $3 + - regex: ; {0,2}(?:Ideapad |)K1 Build/ + device_replacement: Lenovo Ideapad K1 + brand_replacement: Lenovo + model_replacement: Ideapad K1 + - regex: ; {0,2}(3GC101|3GW10[01]|A390) Build/ + device_replacement: $1 + brand_replacement: Lenovo + model_replacement: $1 + - regex: \b(?:Lenovo|LENOVO)+[ _\-]?([^,;:/ ]+) + device_replacement: Lenovo $1 + brand_replacement: Lenovo + model_replacement: $1 - regex: '; {0,2}(MFC\d+)[A-Z]{2}([^;,/]*),?(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Lexibook' - model_replacement: '$1$2' - - ######### - # LG - # @ref: http://www.lg.com/uk/mobile - ######### - - regex: '; {0,2}(E[34][0-9]{2}|LS[6-8][0-9]{2}|VS[6-9][0-9]+[^;/]{1,30}|Nexus 4|Nexus 5X?|GT540f?|Optimus (?:2X|G|4X HD)|OptimusX4HD) {0,2}(?:Build|;)' - device_replacement: '$1' - brand_replacement: 'LG' - model_replacement: '$1' + device_replacement: $1$2 + brand_replacement: Lexibook + model_replacement: $1$2 + - regex: ; {0,2}(E[34][0-9]{2}|LS[6-8][0-9]{2}|VS[6-9][0-9]+[^;/]{1,30}|Nexus 4|Nexus + 5X?|GT540f?|Optimus (?:2X|G|4X HD)|OptimusX4HD) {0,2}(?:Build|;) + device_replacement: $1 + brand_replacement: LG + model_replacement: $1 - regex: '[;:] {0,2}(L-\d+[A-Z]|LGL\d+[A-Z]?)(?:/V\d+|) {0,2}(?:Build|[;\)])' - device_replacement: '$1' - brand_replacement: 'LG' - model_replacement: '$1' - - regex: '; {0,2}(LG-)([A-Z]{1,2}\d{2,}[^,;/\)\(]*?)(?:Build| V\d+|[,;/\)\(]|$)' - device_replacement: '$1$2' - brand_replacement: 'LG' - model_replacement: '$2' - - regex: '; {0,2}(LG[ \-]|LG)([^;/]{1,100})[;/]? Build' - device_replacement: '$1$2' - brand_replacement: 'LG' - model_replacement: '$2' - - regex: '^(LG)-([^;/]{1,100})/ Mozilla/.{0,200}; Android' - device_replacement: '$1 $2' - brand_replacement: 'LG' - model_replacement: '$2' - - regex: '(Web0S); Linux/(SmartTV)' - device_replacement: 'LG $1 $2' - brand_replacement: 'LG' - model_replacement: '$1 $2' - - ######### - # Malata - # @ref: http://www.malata.com/en/products.aspx?classid=680 - ######### + device_replacement: $1 + brand_replacement: LG + model_replacement: $1 + - regex: ; {0,2}(LG-)([A-Z]{1,2}\d{2,}[^,;/\)\(]*?)(?:Build| V\d+|[,;/\)\(]|$) + device_replacement: $1$2 + brand_replacement: LG + model_replacement: $2 + - regex: ; {0,2}(LG[ \-]|LG)([^;/]{1,100})[;/]? Build + device_replacement: $1$2 + brand_replacement: LG + model_replacement: $2 + - regex: ^(LG)-([^;/]{1,100})/ Mozilla/.{0,200}; Android + device_replacement: $1 $2 + brand_replacement: LG + model_replacement: $2 + - regex: (Web0S); Linux/(SmartTV) + device_replacement: LG $1 $2 + brand_replacement: LG + model_replacement: $1 $2 - regex: '; {0,2}((?:SMB|smb)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Malata' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Malata + model_replacement: $1 - regex: '; {0,2}(?:Malata|MALATA) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Malata' - model_replacement: '$1' - - ######### - # Manta - # @ref: http://www.manta.com.pl/en - ######### - - regex: '; {0,2}(MS[45][0-9]{3}|MID0[568][NS]?|MID[1-9]|MID[78]0[1-9]|MID970[1-9]|MID100[1-9])(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Manta' - model_replacement: '$1' - - ######### - # Match - # @ref: http://www.match.net.cn/products.asp - ######### - - regex: '; {0,2}(M1052|M806|M9000|M9100|M9701|MID100|MID120|MID125|MID130|MID135|MID140|MID701|MID710|MID713|MID727|MID728|MID731|MID732|MID733|MID735|MID736|MID737|MID760|MID800|MID810|MID820|MID830|MID833|MID835|MID860|MID900|MID930|MID933|MID960|MID980)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Match' - model_replacement: '$1' - - ######### - # Maxx - # @ref: http://www.maxxmobile.in/ - # @models: Maxx MSD7-Play, Maxx MX245+ Trance, Maxx AX8 Race, Maxx MSD7 3G- AX50, Maxx Genx Droid 7 - AX40, Maxx AX5 Duo, - # Maxx AX3 Duo, Maxx AX3, Maxx AX8 Note II (Note 2), Maxx AX8 Note I, Maxx AX8, Maxx AX5 Plus, Maxx MSD7 Smarty, - # Maxx AX9Z Race, - # Maxx MT150, Maxx MQ601, Maxx M2020, Maxx Sleek MX463neo, Maxx MX525, Maxx MX192-Tune, Maxx Genx Droid 7 AX353, - # @note: Need more User-Agents!!! - ######### - - regex: '; {0,2}(GenxDroid7|MSD7.{0,200}?|AX\d.{0,200}?|Tab 701|Tab 722)(?: Build|\) AppleWebKit)' - device_replacement: 'Maxx $1' - brand_replacement: 'Maxx' - model_replacement: '$1' - - ######### - # Mediacom - # @ref: http://www.mediacomeurope.it/ - ######### + device_replacement: $1 + brand_replacement: Malata + model_replacement: $1 + - regex: '; {0,2}(MS[45][0-9]{3}|MID0[568][NS]?|MID[1-9]|MID[78]0[1-9]|MID970[1-9]|MID100[1-9])(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Manta + model_replacement: $1 + - regex: '; {0,2}(M1052|M806|M9000|M9100|M9701|MID100|MID120|MID125|MID130|MID135|MID140|MID701|MID710|MID713|MID727|MID728|MID731|MID732|MID733|MID735|MID736|MID737|MID760|MID800|MID810|MID820|MID830|MID833|MID835|MID860|MID900|MID930|MID933|MID960|MID980)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Match + model_replacement: $1 + - regex: '; {0,2}(GenxDroid7|MSD7.{0,200}?|AX\d.{0,200}?|Tab 701|Tab 722)(?: Build|\) + AppleWebKit)' + device_replacement: Maxx $1 + brand_replacement: Maxx + model_replacement: $1 - regex: '; {0,2}(M-PP[^;/]{1,30}|PhonePad ?\d{2,}[^;/]{1,30}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Mediacom $1' - brand_replacement: 'Mediacom' - model_replacement: '$1' + device_replacement: Mediacom $1 + brand_replacement: Mediacom + model_replacement: $1 - regex: '; {0,2}(M-MP[^;/]{1,30}|SmartPad ?\d{2,}[^;/]{1,30}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Mediacom $1' - brand_replacement: 'Mediacom' - model_replacement: '$1' - - ######### - # Medion - # @ref: http://www.medion.com/en/ - ######### + device_replacement: Mediacom $1 + brand_replacement: Mediacom + model_replacement: $1 - regex: '; {0,2}(?:MD_|)LIFETAB[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Medion Lifetab $1' - brand_replacement: 'Medion' - model_replacement: 'Lifetab $1' + regex_flag: i + device_replacement: Medion Lifetab $1 + brand_replacement: Medion + model_replacement: Lifetab $1 - regex: '; {0,2}MEDION ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Medion $1' - brand_replacement: 'Medion' - model_replacement: '$1' - - ######### - # Meizu - # @ref: http://www.meizu.com - ######### + device_replacement: Medion $1 + brand_replacement: Medion + model_replacement: $1 - regex: '; {0,2}(M030|M031|M035|M040|M065|m9)(?: Build|\) AppleWebKit)' - device_replacement: 'Meizu $1' - brand_replacement: 'Meizu' - model_replacement: '$1' - - regex: '; {0,2}(?:meizu_|MEIZU )(.{1,200}?) {0,2}(?:Build|[;\)])' - device_replacement: 'Meizu $1' - brand_replacement: 'Meizu' - model_replacement: '$1' - - ######### - # Meta - # @ref: https://www.meta.com - ######### - - regex: 'Quest 2' - device_replacement: 'Quest' - brand_replacement: 'Meta' - model_replacement: 'Quest 2' - - - regex: 'Quest Pro' - device_replacement: 'Quest' - brand_replacement: 'Meta' - model_replacement: 'Quest Pro' - - - regex: 'Quest' - device_replacement: 'Quest' - brand_replacement: 'Meta' - model_replacement: 'Quest' - - ######### - # Micromax - # @ref: http://www.micromaxinfo.com - ######### - - regex: '; {0,2}(?:Micromax[ _](A111|A240)|(A111|A240)) Build' - regex_flag: 'i' - device_replacement: 'Micromax $1$2' - brand_replacement: 'Micromax' - model_replacement: '$1$2' - - regex: '; {0,2}Micromax[ _](A\d{2,3}[^;/]*) Build' - regex_flag: 'i' - device_replacement: 'Micromax $1' - brand_replacement: 'Micromax' - model_replacement: '$1' - # be carefull here with Acer e.g. A500 - - regex: '; {0,2}(A\d{2}|A[12]\d{2}|A90S|A110Q) Build' - regex_flag: 'i' - device_replacement: 'Micromax $1' - brand_replacement: 'Micromax' - model_replacement: '$1' - - regex: '; {0,2}Micromax[ _](P\d{3}[^;/]*) Build' - regex_flag: 'i' - device_replacement: 'Micromax $1' - brand_replacement: 'Micromax' - model_replacement: '$1' - - regex: '; {0,2}(P\d{3}|P\d{3}\(Funbook\)) Build' - regex_flag: 'i' - device_replacement: 'Micromax $1' - brand_replacement: 'Micromax' - model_replacement: '$1' - - ######### - # Mito - # @ref: http://new.mitomobile.com/ - ######### + device_replacement: Meizu $1 + brand_replacement: Meizu + model_replacement: $1 + - regex: ; {0,2}(?:meizu_|MEIZU )(.{1,200}?) {0,2}(?:Build|[;\)]) + device_replacement: Meizu $1 + brand_replacement: Meizu + model_replacement: $1 + - regex: Quest 3 + device_replacement: Quest + brand_replacement: Meta + model_replacement: Quest 3 + - regex: Quest 2 + device_replacement: Quest + brand_replacement: Meta + model_replacement: Quest 2 + - regex: Quest Pro + device_replacement: Quest + brand_replacement: Meta + model_replacement: Quest Pro + - regex: Quest + device_replacement: Quest + brand_replacement: Meta + model_replacement: Quest + - regex: ; {0,2}(?:Micromax[ _](A111|A240)|(A111|A240)) Build + regex_flag: i + device_replacement: Micromax $1$2 + brand_replacement: Micromax + model_replacement: $1$2 + - regex: ; {0,2}Micromax[ _](A\d{2,3}[^;/]*) Build + regex_flag: i + device_replacement: Micromax $1 + brand_replacement: Micromax + model_replacement: $1 + - regex: ; {0,2}(A\d{2}|A[12]\d{2}|A90S|A110Q) Build + regex_flag: i + device_replacement: Micromax $1 + brand_replacement: Micromax + model_replacement: $1 + - regex: ; {0,2}Micromax[ _](P\d{3}[^;/]*) Build + regex_flag: i + device_replacement: Micromax $1 + brand_replacement: Micromax + model_replacement: $1 + - regex: ; {0,2}(P\d{3}|P\d{3}\(Funbook\)) Build + regex_flag: i + device_replacement: Micromax $1 + brand_replacement: Micromax + model_replacement: $1 - regex: '; {0,2}(MITO)[ _\-]?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Mito' - model_replacement: '$2' - - ######### - # Mobistel - # @ref: http://www.mobistel.com/ - ######### - - regex: '; {0,2}(Cynus)[ _](F5|T\d|.{1,200}?) {0,2}(?:Build|[;/\)])' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Mobistel' - model_replacement: '$1 $2' - - ######### - # Modecom - # @ref: http://www.modecom.eu/tablets/portal/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Mito + model_replacement: $2 + - regex: ; {0,2}(Cynus)[ _](F5|T\d|.{1,200}?) {0,2}(?:Build|[;/\)]) + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Mobistel + model_replacement: $1 $2 - regex: '; {0,2}(MODECOM |)(FreeTab) ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1$2 $3' - brand_replacement: 'Modecom' - model_replacement: '$2 $3' + regex_flag: i + device_replacement: $1$2 $3 + brand_replacement: Modecom + model_replacement: $2 $3 - regex: '; {0,2}(MODECOM )([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Modecom' - model_replacement: '$2' - - ######### - # Motorola - # @ref: http://www.motorola.com/us/shop-all-mobile-phones/ - ######### - - regex: '; {0,2}(MZ\d{3}\+?|MZ\d{3} 4G|Xoom|XOOM[^;/]*) Build' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: '$1' - - regex: '; {0,2}(Milestone )(XT[^;/]*) Build' - device_replacement: 'Motorola $1$2' - brand_replacement: 'Motorola' - model_replacement: '$2' - - regex: '; {0,2}(Motoroi ?x|Droid X|DROIDX) Build' - regex_flag: 'i' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: 'DROID X' - - regex: '; {0,2}(Droid[^;/]*|DROID[^;/]*|Milestone[^;/]*|Photon|Triumph|Devour|Titanium) Build' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: '$1' - - regex: '; {0,2}(A555|A85[34][^;/]*|A95[356]|ME[58]\d{2}\+?|ME600|ME632|ME722|MB\d{3}\+?|MT680|MT710|MT870|MT887|MT917|WX435|WX453|WX44[25]|XT\d{3,4}[A-Z\+]*|CL[iI]Q|CL[iI]Q XT) Build' - device_replacement: '$1' - brand_replacement: 'Motorola' - model_replacement: '$1' - - regex: '; {0,2}(Motorola MOT-|Motorola[ _\-]|MOT\-?)([^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'Motorola' - model_replacement: '$2' - - regex: '; {0,2}(Moto[_ ]?|MOT\-)([^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'Motorola' - model_replacement: '$2' - - ######### - # MpMan - # @ref: http://www.mpmaneurope.com - ######### - - regex: '; {0,2}((?:MP[DQ]C|MPG\d{1,4}|MP\d{3,4}|MID(?:(?:10[234]|114|43|7[247]|8[24]|7)C|8[01]1))[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Mpman' - model_replacement: '$1' - - ######### - # MSI - # @ref: http://www.msi.com/product/windpad/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Modecom + model_replacement: $2 + - regex: ; {0,2}(MZ\d{3}\+?|MZ\d{3} 4G|Xoom|XOOM[^;/]*) Build + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: $1 + - regex: ; {0,2}(Milestone )(XT[^;/]*) Build + device_replacement: Motorola $1$2 + brand_replacement: Motorola + model_replacement: $2 + - regex: ; {0,2}(Motoroi ?x|Droid X|DROIDX) Build + regex_flag: i + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: DROID X + - regex: ; {0,2}(Droid[^;/]*|DROID[^;/]*|Milestone[^;/]*|Photon|Triumph|Devour|Titanium) + Build + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: $1 + - regex: ; {0,2}(A555|A85[34][^;/]*|A95[356]|ME[58]\d{2}\+?|ME600|ME632|ME722|MB\d{3}\+?|MT680|MT710|MT870|MT887|MT917|WX435|WX453|WX44[25]|XT\d{3,4}[A-Z\+]*|CL[iI]Q|CL[iI]Q + XT) Build + device_replacement: $1 + brand_replacement: Motorola + model_replacement: $1 + - regex: ; {0,2}(Motorola MOT-|Motorola[ _\-]|MOT\-?)([^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: Motorola + model_replacement: $2 + - regex: ; {0,2}(Moto[_ ]?|MOT\-)([^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: Motorola + model_replacement: $2 + - regex: '; {0,2}((?:MP[DQ]C|MPG\d{1,4}|MP\d{3,4}|MID(?:(?:10[234]|114|43|7[247]|8[24]|7)C|8[01]1))[^;/]*)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Mpman + model_replacement: $1 - regex: '; {0,2}(?:MSI[ _]|)(Primo\d+|Enjoy[ _\-][^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'Msi' - model_replacement: '$1' - - ######### - # Multilaser - # http://www.multilaser.com.br/listagem_produtos.php?cat=5 - ######### + regex_flag: i + device_replacement: $1 + brand_replacement: Msi + model_replacement: $1 - regex: '; {0,2}Multilaser[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Multilaser' - model_replacement: '$1' - - ######### - # MyPhone - # @ref: http://myphone.com.ph/ - ######### + device_replacement: $1 + brand_replacement: Multilaser + model_replacement: $1 - regex: '; {0,2}(My)[_]?(Pad)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2 $3' - brand_replacement: 'MyPhone' - model_replacement: '$1$2 $3' + device_replacement: $1$2 $3 + brand_replacement: MyPhone + model_replacement: $1$2 $3 - regex: '; {0,2}(My)\|?(Phone)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2 $3' - brand_replacement: 'MyPhone' - model_replacement: '$3' + device_replacement: $1$2 $3 + brand_replacement: MyPhone + model_replacement: $3 - regex: '; {0,2}(A\d+)[ _](Duo|)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'MyPhone' - model_replacement: '$1 $2' - - ######### - # Mytab - # @ref: http://www.mytab.eu/en/category/mytab-products/ - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: MyPhone + model_replacement: $1 $2 - regex: '; {0,2}(myTab[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Mytab' - model_replacement: '$1' - - ######### - # Nabi - # @ref: https://www.nabitablet.com - ######### + device_replacement: $1 + brand_replacement: Mytab + model_replacement: $1 - regex: '; {0,2}(NABI2?-)([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Nabi' - model_replacement: '$2' - - ######### - # Nec Medias - # @ref: http://www.n-keitai.com/ - ######### + device_replacement: $1$2 + brand_replacement: Nabi + model_replacement: $2 - regex: '; {0,2}(N-\d+[CDE])(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Nec' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Nec + model_replacement: $1 - regex: '; ?(NEC-)(.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Nec' - model_replacement: '$2' + device_replacement: $1$2 + brand_replacement: Nec + model_replacement: $2 - regex: '; {0,2}(LT-NA7)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Nec' - model_replacement: 'Lifetouch Note' - - ######### - # Nextbook - # @ref: http://nextbookusa.com - ######### - - regex: '; {0,2}(NXM\d+[A-Za-z0-9_]{0,50}|Next\d[A-Za-z0-9_ \-]{0,50}|NEXT\d[A-Za-z0-9_ \-]{0,50}|Nextbook [A-Za-z0-9_ ]{0,50}|DATAM803HC|M805)(?: Build|[\);])' - device_replacement: '$1' - brand_replacement: 'Nextbook' - model_replacement: '$1' - - ######### - # Nokia - # @ref: http://www.nokia.com - ######### - - regex: '; {0,2}(Nokia)([ _\-]{0,5})([^;/]{0,50}) Build' - regex_flag: 'i' - device_replacement: '$1$2$3' - brand_replacement: 'Nokia' - model_replacement: '$3' + device_replacement: $1 + brand_replacement: Nec + model_replacement: Lifetouch Note + - regex: '; {0,2}(NXM\d+[A-Za-z0-9_]{0,50}|Next\d[A-Za-z0-9_ \-]{0,50}|NEXT\d[A-Za-z0-9_ + \-]{0,50}|Nextbook [A-Za-z0-9_ ]{0,50}|DATAM803HC|M805)(?: Build|[\);])' + device_replacement: $1 + brand_replacement: Nextbook + model_replacement: $1 + - regex: ; {0,2}(Nokia)([ _\-]{0,5})([^;/]{0,50}) Build + regex_flag: i + device_replacement: $1$2$3 + brand_replacement: Nokia + model_replacement: $3 - regex: '; {0,2}(TA\-\d{4})(?: Build|\) AppleWebKit)' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1' - - ######### - # Nook - # @ref: - # TODO nook browser/1.0 - ######### + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1 - regex: '; {0,2}(Nook ?|Barnes & Noble Nook |BN )([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Nook' - model_replacement: '$2' - - regex: '; {0,2}(NOOK |)(BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Nook' - model_replacement: '$2' - - regex: '; Build/(Nook)' - device_replacement: '$1' - brand_replacement: 'Nook' - model_replacement: 'Tablet' - - ######### - # Olivetti - # @ref: http://www.olivetti.de/EN/Page/t02/view_html?idp=348 - ######### + device_replacement: $1$2 + brand_replacement: Nook + model_replacement: $2 + - regex: '; {0,2}(NOOK |)(BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD + Zoom2)(?: Build|\) AppleWebKit)' + device_replacement: $1$2 + brand_replacement: Nook + model_replacement: $2 + - regex: ; Build/(Nook) + device_replacement: $1 + brand_replacement: Nook + model_replacement: Tablet - regex: '; {0,2}(OP110|OliPad[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Olivetti $1' - brand_replacement: 'Olivetti' - model_replacement: '$1' - - ######### - # Omega - # @ref: http://omega-technology.eu/en/produkty/346/tablets - # @note: MID tablets might get matched by CobyKyros first - # @models: (T107|MID(?:700[2-5]|7031|7108|7132|750[02]|8001|8500|9001|971[12]) - ######### + device_replacement: Olivetti $1 + brand_replacement: Olivetti + model_replacement: $1 - regex: '; {0,2}OMEGA[ _\-](MID[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Omega $1' - brand_replacement: 'Omega' - model_replacement: '$1' - - regex: '^(MID7500|MID\d+) Mozilla/5\.0 \(iPad;' - device_replacement: 'Omega $1' - brand_replacement: 'Omega' - model_replacement: '$1' - - ######### - # OpenPeak - # @ref: https://support.google.com/googleplay/answer/1727131?hl=en - ######### + device_replacement: Omega $1 + brand_replacement: Omega + model_replacement: $1 + - regex: ^(MID7500|MID\d+) Mozilla/5\.0 \(iPad; + device_replacement: Omega $1 + brand_replacement: Omega + model_replacement: $1 - regex: '; {0,2}((?:CIUS|cius)[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'Openpeak $1' - brand_replacement: 'Openpeak' - model_replacement: '$1' - - ######### - # Oppo - # @ref: http://en.oppo.com/products/ - ######### - - regex: '; {0,2}(Find ?(?:5|7a)|R8[012]\d{1,2}|T703\d?|U70\d{1,2}T?|X90\d{1,2}|[AFR]\d{1,2}[a-z]{1,2})(?: Build|\) AppleWebKit)' - device_replacement: 'Oppo $1' - brand_replacement: 'Oppo' - model_replacement: '$1' + device_replacement: Openpeak $1 + brand_replacement: Openpeak + model_replacement: $1 + - regex: '; {0,2}(Find ?(?:5|7a)|R8[012]\d{1,2}|T703\d?|U70\d{1,2}T?|X90\d{1,2}|[AFR]\d{1,2}[a-z]{1,2})(?: + Build|\) AppleWebKit)' + device_replacement: Oppo $1 + brand_replacement: Oppo + model_replacement: $1 - regex: '; {0,2}OPPO ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Oppo $1' - brand_replacement: 'Oppo' - model_replacement: '$1' + device_replacement: Oppo $1 + brand_replacement: Oppo + model_replacement: $1 - regex: '; {0,2}(CPH\d{1,4}|RMX\d{1,4}|P[A-Z]{3}\d{2})(?: Build|\) AppleWebKit)' - device_replacement: 'Oppo $1' - brand_replacement: 'Oppo' + device_replacement: Oppo $1 + brand_replacement: Oppo - regex: '; {0,2}(A1601)(?: Build|\) AppleWebKit)' - device_replacement: 'Oppo F1s' - brand_replacement: 'Oppo' - model_replacement: '$1' - - ######### - # Odys - # @ref: http://odys.de - ######### + device_replacement: Oppo F1s + brand_replacement: Oppo + model_replacement: $1 - regex: '; {0,2}(?:Odys\-|ODYS\-|ODYS )([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Odys $1' - brand_replacement: 'Odys' - model_replacement: '$1' + device_replacement: Odys $1 + brand_replacement: Odys + model_replacement: $1 - regex: '; {0,2}(SELECT) ?(7)(?: Build|\) AppleWebKit)' - device_replacement: 'Odys $1 $2' - brand_replacement: 'Odys' - model_replacement: '$1 $2' + device_replacement: Odys $1 $2 + brand_replacement: Odys + model_replacement: $1 $2 - regex: '; {0,2}(PEDI)_(PLUS)_(W)(?: Build|\) AppleWebKit)' - device_replacement: 'Odys $1 $2 $3' - brand_replacement: 'Odys' - model_replacement: '$1 $2 $3' - # Weltbild - Tablet PC 4 = Cat Phoenix = Odys Tablet PC 4? - - regex: '; {0,2}(AEON|BRAVIO|FUSION|FUSION2IN1|Genio|EOS10|IEOS[^;/]*|IRON|Loox|LOOX|LOOX Plus|Motion|NOON|NOON_PRO|NEXT|OPOS|PEDI[^;/]*|PRIME[^;/]*|STUDYTAB|TABLO|Tablet-PC-4|UNO_X8|XELIO[^;/]*|Xelio ?\d+ ?[Pp]ro|XENO10|XPRESS PRO)(?: Build|\) AppleWebKit)' - device_replacement: 'Odys $1' - brand_replacement: 'Odys' - model_replacement: '$1' - - ######### - # OnePlus - # @ref https://oneplus.net/ - ######### + device_replacement: Odys $1 $2 $3 + brand_replacement: Odys + model_replacement: $1 $2 $3 + - regex: '; {0,2}(AEON|BRAVIO|FUSION|FUSION2IN1|Genio|EOS10|IEOS[^;/]*|IRON|Loox|LOOX|LOOX + Plus|Motion|NOON|NOON_PRO|NEXT|OPOS|PEDI[^;/]*|PRIME[^;/]*|STUDYTAB|TABLO|Tablet-PC-4|UNO_X8|XELIO[^;/]*|Xelio + ?\d+ ?[Pp]ro|XENO10|XPRESS PRO)(?: Build|\) AppleWebKit)' + device_replacement: Odys $1 + brand_replacement: Odys + model_replacement: $1 - regex: '; (ONE [a-zA-Z]\d+)(?: Build|\) AppleWebKit)' - device_replacement: 'OnePlus $1' - brand_replacement: 'OnePlus' - model_replacement: '$1' + device_replacement: OnePlus $1 + brand_replacement: OnePlus + model_replacement: $1 - regex: '; (ONEPLUS [a-zA-Z]\d+)(?: Build|\) AppleWebKit)' - device_replacement: 'OnePlus $1' - brand_replacement: 'OnePlus' - model_replacement: '$1' - - regex: '; {0,2}(HD1903|GM1917|IN2025|LE2115|LE2127|HD1907|BE2012|BE2025|BE2026|BE2028|BE2029|DE2117|DE2118|EB2101|GM1900|GM1910|GM1915|HD1905|HD1925|IN2015|IN2017|IN2019|KB2005|KB2007|LE2117|LE2125|BE2015|GM1903|HD1900|HD1901|HD1910|HD1913|IN2010|IN2013|IN2020|LE2111|LE2120|LE2121|LE2123|BE2011|IN2023|KB2003|LE2113|NE2215|DN2101)(?: Build|\) AppleWebKit)' - device_replacement: 'OnePlus $1' - brand_replacement: 'OnePlus' - model_replacement: 'OnePlus $1' + device_replacement: OnePlus $1 + brand_replacement: OnePlus + model_replacement: $1 + - regex: '; {0,2}(HD1903|GM1917|IN2025|LE2115|LE2127|HD1907|BE2012|BE2025|BE2026|BE2028|BE2029|DE2117|DE2118|EB2101|GM1900|GM1910|GM1915|HD1905|HD1925|IN2015|IN2017|IN2019|KB2005|KB2007|LE2117|LE2125|BE2015|GM1903|HD1900|HD1901|HD1910|HD1913|IN2010|IN2013|IN2020|LE2111|LE2120|LE2121|LE2123|BE2011|IN2023|KB2003|LE2113|NE2215|DN2101)(?: + Build|\) AppleWebKit)' + device_replacement: OnePlus $1 + brand_replacement: OnePlus + model_replacement: OnePlus $1 - regex: '; (OnePlus[ a-zA-z0-9]{0,50});((?: Build|.{0,50}\) AppleWebKit))' - device_replacement: '$1' - brand_replacement: 'OnePlus' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: OnePlus + model_replacement: $1 - regex: '; (OnePlus[ a-zA-z0-9]{0,50})((?: Build|\) AppleWebKit))' - device_replacement: '$1' - brand_replacement: 'OnePlus' - model_replacement: '$1' - - ######### - # Orion - # @ref: http://www.orion.ua/en/products/computer-products/tablet-pcs.html - ######### + device_replacement: $1 + brand_replacement: OnePlus + model_replacement: $1 - regex: '; {0,2}(TP-\d+)(?: Build|\) AppleWebKit)' - device_replacement: 'Orion $1' - brand_replacement: 'Orion' - model_replacement: '$1' - - ######### - # PackardBell - # @ref: http://www.packardbell.com/pb/en/AE/content/productgroup/tablets - ######### + device_replacement: Orion $1 + brand_replacement: Orion + model_replacement: $1 - regex: '; {0,2}(G100W?)(?: Build|\) AppleWebKit)' - device_replacement: 'PackardBell $1' - brand_replacement: 'PackardBell' - model_replacement: '$1' - - ######### - # Panasonic - # @ref: http://panasonic.jp/mobile/ - # @models: T11, T21, T31, P11, P51, Eluga Power, Eluga DL1 - # @models: (tab) Toughpad FZ-A1, Toughpad JT-B1 - ######### + device_replacement: PackardBell $1 + brand_replacement: PackardBell + model_replacement: $1 - regex: '; {0,2}(Panasonic)[_ ]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - # Toughpad + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(FZ-A1B|JT-B1)(?: Build|\) AppleWebKit)' - device_replacement: 'Panasonic $1' - brand_replacement: 'Panasonic' - model_replacement: '$1' - # Eluga Power + device_replacement: Panasonic $1 + brand_replacement: Panasonic + model_replacement: $1 - regex: '; {0,2}(dL1|DL1)(?: Build|\) AppleWebKit)' - device_replacement: 'Panasonic $1' - brand_replacement: 'Panasonic' - model_replacement: '$1' - - ######### - # Pantech - # @href: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=PANTECH - # @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: '; {0,2}(SKY[ _]|)(IM\-[AT]\d{3}[^;/]{1,100}).{0,30} Build/' - device_replacement: 'Pantech $1$2' - brand_replacement: 'Pantech' - model_replacement: '$1$2' + device_replacement: Panasonic $1 + brand_replacement: Panasonic + model_replacement: $1 + - regex: ; {0,2}(SKY[ _]|)(IM\-[AT]\d{3}[^;/]{1,100}).{0,30} Build/ + device_replacement: Pantech $1$2 + brand_replacement: Pantech + model_replacement: $1$2 - regex: '; {0,2}((?:ADR8995|ADR910L|ADR930L|ADR930VW|PTL21|P8000)(?: 4G|)) Build/' - device_replacement: '$1' - brand_replacement: 'Pantech' - model_replacement: '$1' - - regex: '; {0,2}Pantech([^;/]{1,30}).{0,200}? Build/' - device_replacement: 'Pantech $1' - brand_replacement: 'Pantech' - model_replacement: '$1' - - ######### - # Papayre - # @ref: http://grammata.es/ - ######### + device_replacement: $1 + brand_replacement: Pantech + model_replacement: $1 + - regex: ; {0,2}Pantech([^;/]{1,30}).{0,200}? Build/ + device_replacement: Pantech $1 + brand_replacement: Pantech + model_replacement: $1 - regex: '; {0,2}(papyre)[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Papyre' - model_replacement: '$2' - - ######### - # Pearl - # @ref: http://www.pearl.de/c-1540.shtml - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Papyre + model_replacement: $2 - regex: '; {0,2}(?:Touchlet )?(X10\.[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Pearl $1' - brand_replacement: 'Pearl' - model_replacement: '$1' - - ######### - # Phicomm - # @ref: http://www.phicomm.com.cn/ - ######### + device_replacement: Pearl $1 + brand_replacement: Pearl + model_replacement: $1 - regex: '; PHICOMM (i800)(?: Build|\) AppleWebKit)' - device_replacement: 'Phicomm $1' - brand_replacement: 'Phicomm' - model_replacement: '$1' + device_replacement: Phicomm $1 + brand_replacement: Phicomm + model_replacement: $1 - regex: '; PHICOMM ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Phicomm $1' - brand_replacement: 'Phicomm' - model_replacement: '$1' + device_replacement: Phicomm $1 + brand_replacement: Phicomm + model_replacement: $1 - regex: '; {0,2}(FWS\d{3}[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Phicomm $1' - brand_replacement: 'Phicomm' - model_replacement: '$1' - - ######### - # Philips - # @ref: http://www.support.philips.com/support/catalog/products.jsp?_dyncharset=UTF-8&country=&categoryid=MOBILE_PHONES_SMART_SU_CN_CARE&userLanguage=en&navCount=2&groupId=PC_PRODUCTS_AND_PHONES_GR_CN_CARE&catalogType=&navAction=push&userCountry=cn&title=Smartphones&cateId=MOBILE_PHONES_CA_CN_CARE - # @TODO: Philips Tablets User-Agents missing! - # @ref: http://www.support.philips.com/support/catalog/products.jsp?_dyncharset=UTF-8&country=&categoryid=ENTERTAINMENT_TABLETS_SU_CN_CARE&userLanguage=en&navCount=0&groupId=&catalogType=&navAction=push&userCountry=cn&title=Entertainment+Tablets&cateId=TABLETS_CA_CN_CARE - ######### - # @note: this a best guess according to available philips models. Need more User-Agents - - regex: '; {0,2}(D633|D822|D833|T539|T939|V726|W335|W336|W337|W3568|W536|W5510|W626|W632|W6350|W6360|W6500|W732|W736|W737|W7376|W820|W832|W8355|W8500|W8510|W930)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Philips' - model_replacement: '$1' + device_replacement: Phicomm $1 + brand_replacement: Phicomm + model_replacement: $1 + - regex: '; {0,2}(D633|D822|D833|T539|T939|V726|W335|W336|W337|W3568|W536|W5510|W626|W632|W6350|W6360|W6500|W732|W736|W737|W7376|W820|W832|W8355|W8500|W8510|W930)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Philips + model_replacement: $1 - regex: '; {0,2}(?:Philips|PHILIPS)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Philips $1' - brand_replacement: 'Philips' - model_replacement: '$1' - - ######### - # Pipo - # @ref: http://www.pipo.cn/En/ - ######### - - regex: 'Android 4\..{0,200}; {0,2}(M[12356789]|U[12368]|S[123])\ ?(pro)?(?: Build|\) AppleWebKit)' - device_replacement: 'Pipo $1$2' - brand_replacement: 'Pipo' - model_replacement: '$1$2' - - ######### - # Ployer - # @ref: http://en.ployer.cn/ - ######### + device_replacement: Philips $1 + brand_replacement: Philips + model_replacement: $1 + - regex: 'Android 4\..{0,200}; {0,2}(M[12356789]|U[12368]|S[123])\ ?(pro)?(?: Build|\) + AppleWebKit)' + device_replacement: Pipo $1$2 + brand_replacement: Pipo + model_replacement: $1$2 - regex: '; {0,2}(MOMO[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Ployer' - model_replacement: '$1' - - ######### - # Polaroid/ Acho - # @ref: http://polaroidstore.com/store/start.asp?category_id=382&category_id2=0&order=title&filter1=&filter2=&filter3=&view=all - ######### - - regex: '; {0,2}(?:Polaroid[ _]|)((?:MIDC\d{3,}|PMID\d{2,}|PTAB\d{3,})[^;/]{0,30}?)(\/[^;/]{0,30}|)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Polaroid' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Ployer + model_replacement: $1 + - regex: '; {0,2}(?:Polaroid[ _]|)((?:MIDC\d{3,}|PMID\d{2,}|PTAB\d{3,})[^;/]{0,30}?)(\/[^;/]{0,30}|)(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Polaroid + model_replacement: $1 - regex: '; {0,2}(?:Polaroid )(Tablet)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Polaroid' - model_replacement: '$1' - - ######### - # Pomp - # @ref: http://pompmobileshop.com/ - ######### - #~ TODO - - regex: '; {0,2}(POMP)[ _\-](.{1,200}?) {0,2}(?:Build|[;/\)])' - device_replacement: '$1 $2' - brand_replacement: 'Pomp' - model_replacement: '$2' - - ######### - # Positivo - # @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/ - ######### + device_replacement: $1 + brand_replacement: Polaroid + model_replacement: $1 + - regex: ; {0,2}(POMP)[ _\-](.{1,200}?) {0,2}(?:Build|[;/\)]) + device_replacement: $1 $2 + brand_replacement: Pomp + model_replacement: $2 - regex: '; {0,2}(TB07STA|TB10STA|TB07FTA|TB10FTA)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Positivo' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Positivo + model_replacement: $1 - regex: '; {0,2}(?:Positivo |)((?:YPY|Ypy)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Positivo' - model_replacement: '$1' - - ######### - # POV - # @ref: http://www.pointofview-online.com/default2.php - # @TODO: Smartphone Models MOB-3515, MOB-5045-B missing - ######### + device_replacement: $1 + brand_replacement: Positivo + model_replacement: $1 - regex: '; {0,2}(MOB-[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'POV' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: POV + model_replacement: $1 - regex: '; {0,2}POV[ _\-]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'POV $1' - brand_replacement: 'POV' - model_replacement: '$1' - - regex: '; {0,2}((?:TAB-PLAYTAB|TAB-PROTAB|PROTAB|PlayTabPro|Mobii[ _\-]|TAB-P)[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'POV $1' - brand_replacement: 'POV' - model_replacement: '$1' - - ######### - # Prestigio - # @ref: http://www.prestigio.com/catalogue/MultiPhones - # @ref: http://www.prestigio.com/catalogue/MultiPads - ######### + device_replacement: POV $1 + brand_replacement: POV + model_replacement: $1 + - regex: '; {0,2}((?:TAB-PLAYTAB|TAB-PROTAB|PROTAB|PlayTabPro|Mobii[ _\-]|TAB-P)[^;/]*)(?: + Build|\) AppleWebKit)' + device_replacement: POV $1 + brand_replacement: POV + model_replacement: $1 - regex: '; {0,2}(?:Prestigio |)((?:PAP|PMP)\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Prestigio $1' - brand_replacement: 'Prestigio' - model_replacement: '$1' - - ######### - # Proscan - # @ref: http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr= - ######### + device_replacement: Prestigio $1 + brand_replacement: Prestigio + model_replacement: $1 - regex: '; {0,2}(PLT[0-9]{4}.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Proscan' - model_replacement: '$1' - - ######### - # QMobile - # @ref: http://www.qmobile.com.pk/ - ######### + device_replacement: $1 + brand_replacement: Proscan + model_replacement: $1 - regex: '; {0,2}(A2|A5|A8|A900)_?(Classic|)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Qmobile' - model_replacement: '$1 $2' + device_replacement: $1 $2 + brand_replacement: Qmobile + model_replacement: $1 $2 - regex: '; {0,2}(Q[Mm]obile)_([^_]+)_([^_]+?)(?: Build|\) AppleWebKit)' - device_replacement: 'Qmobile $2 $3' - brand_replacement: 'Qmobile' - model_replacement: '$2 $3' + device_replacement: Qmobile $2 $3 + brand_replacement: Qmobile + model_replacement: $2 $3 - regex: '; {0,2}(Q\-?[Mm]obile)[_ ](A[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Qmobile $2' - brand_replacement: 'Qmobile' - model_replacement: '$2' - - ######### - # Qmobilevn - # @ref: http://qmobile.vn/san-pham.html - ######### + device_replacement: Qmobile $2 + brand_replacement: Qmobile + model_replacement: $2 - regex: '; {0,2}(Q\-Smart)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Qmobilevn' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: Qmobilevn + model_replacement: $2 - regex: '; {0,2}(Q\-?[Mm]obile)[ _\-](S[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Qmobilevn' - model_replacement: '$2' - - ######### - # Quanta - # @ref: ? - ######### + device_replacement: $1 $2 + brand_replacement: Qmobilevn + model_replacement: $2 - regex: '; {0,2}(TA1013)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Quanta' - model_replacement: '$1' - - ######### - # RCA - # @ref: http://rcamobilephone.com/ - ######### + device_replacement: $1 + brand_replacement: Quanta + model_replacement: $1 - regex: '; (RCT\w+)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'RCA' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: RCA + model_replacement: $1 - regex: '; RCA (\w+)(?: Build|\) AppleWebKit)' - device_replacement: 'RCA $1' - brand_replacement: 'RCA' - model_replacement: '$1' - - ######### - # Rockchip - # @ref: http://www.rock-chips.com/a/cn/product/index.html - # @note: manufacturer sells chipsets - I assume that these UAs are dev-boards - ######### + device_replacement: RCA $1 + brand_replacement: RCA + model_replacement: $1 - regex: '; {0,2}(RK\d+),?(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Rockchip' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Rockchip + model_replacement: $1 - regex: ' Build/(RK\d+)' - device_replacement: '$1' - brand_replacement: 'Rockchip' - model_replacement: '$1' - - ######### - # Samsung Android Devices - # @ref: http://www.samsung.com/us/mobile/cell-phones/all-products - ######### - - regex: '; {0,2}(SAMSUNG |Samsung |)((?:Galaxy (?:Note II|S\d)|GT-I9082|GT-I9205|GT-N7\d{3}|SM-N9005)[^;/]{0,100})\/?[^;/]{0,50} Build/' - device_replacement: 'Samsung $1$2' - brand_replacement: 'Samsung' - model_replacement: '$2' + device_replacement: $1 + brand_replacement: Rockchip + model_replacement: $1 + - regex: ; {0,2}(SAMSUNG |Samsung |)((?:Galaxy (?:Note II|S\d)|GT-I9082|GT-I9205|GT-N7\d{3}|SM-N9005)[^;/]{0,100})\/?[^;/]{0,50} + Build/ + device_replacement: Samsung $1$2 + brand_replacement: Samsung + model_replacement: $2 - regex: '; {0,2}(Google |)(Nexus [Ss](?: 4G|)) Build/' - device_replacement: 'Samsung $1$2' - brand_replacement: 'Samsung' - model_replacement: '$2' - - regex: '; {0,2}(SAMSUNG |Samsung )([^\/]{0,50})\/[^ ]{0,50} Build/' - device_replacement: 'Samsung $2' - brand_replacement: 'Samsung' - model_replacement: '$2' - - regex: '; {0,2}(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: '; {0,2}(SAMSUNG[ _\-]|)(?:SAMSUNG[ _\-])([^;/]{1,100}) Build' - device_replacement: 'Samsung $2' - brand_replacement: 'Samsung' - model_replacement: '$2' - - regex: '; {0,2}(SAMSUNG-|)(GT\-[BINPS]\d{4}[^\/]{0,50})(\/[^ ]{0,50}) Build' - device_replacement: 'Samsung $1$2$3' - brand_replacement: 'Samsung' - model_replacement: '$2' - - regex: '(?:; {0,2}|^)((?:GT\-[BIiNPS]\d{4}|I9\d{2}0[A-Za-z\+]?\b)[^;/\)]*?)(?:Build|Linux|MIUI|[;/\)])' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - regex: '; (SAMSUNG-)([A-Za-z0-9\-]{0,50}).{0,200} Build/' - device_replacement: 'Samsung $1$2' - brand_replacement: 'Samsung' - model_replacement: '$2' - - regex: '; {0,2}((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9 ]{1,50})(/?[^ ]*|) Build' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - regex: '; {0,2}((?:SC)\-[A-Za-z0-9 ]{1,50})(/?[^ ]*|)\)' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' + device_replacement: Samsung $1$2 + brand_replacement: Samsung + model_replacement: $2 + - regex: ; {0,2}(SAMSUNG |Samsung )([^\/]{0,50})\/[^ ]{0,50} Build/ + device_replacement: Samsung $2 + brand_replacement: Samsung + model_replacement: $2 + - regex: '; {0,2}(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: ; {0,2}(SAMSUNG[ _\-]|)(?:SAMSUNG[ _\-])([^;/]{1,100}) Build + device_replacement: Samsung $2 + brand_replacement: Samsung + model_replacement: $2 + - regex: ; {0,2}(SAMSUNG-|)(GT\-[BINPS]\d{4}[^\/]{0,50})(\/[^ ]{0,50}) Build + device_replacement: Samsung $1$2$3 + brand_replacement: Samsung + model_replacement: $2 + - regex: (?:; {0,2}|^)((?:GT\-[BIiNPS]\d{4}|I9\d{2}0[A-Za-z\+]?\b)[^;/\)]*?)(?:Build|Linux|MIUI|[;/\)]) + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: ; (SAMSUNG-)([A-Za-z0-9\-]{0,50}).{0,200} Build/ + device_replacement: Samsung $1$2 + brand_replacement: Samsung + model_replacement: $2 + - regex: ; {0,2}((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9 ]{1,50})(/?[^ ]*|) Build + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: ; {0,2}((?:SC)\-[A-Za-z0-9 ]{1,50})(/?[^ ]*|)\) + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 - regex: ' ((?:SCH)\-[A-Za-z0-9 ]{1,50})(/?[^ ]*|) Build' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - regex: '; {0,2}(Behold ?(?:2|II)|YP\-G[^;/]{1,100}|EK-GC100|SCL21|I9300) Build' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - regex: '; {0,2}((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9]{5,6})[\)]' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - ######### - # Sharp - # @ref: http://www.sharp-phone.com/en/index.html - # @ref: http://www.android.com/devices/?country=all&m=sharp - ######### + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: ; {0,2}(Behold ?(?:2|II)|YP\-G[^;/]{1,100}|EK-GC100|SCL21|I9300) Build + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: ; {0,2}((?:SCH|SGH|SHV|SHW|SPH|SC|SM)\-[A-Za-z0-9]{5,6})[\)] + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 - regex: '; {0,2}(SH\-?\d\d[^;/]{1,100}|SBM\d[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sharp' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Sharp + model_replacement: $1 - regex: '; {0,2}(SHARP[ -])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Sharp' - model_replacement: '$2' - - ######### - # Simvalley - # @ref: http://www.simvalley-mobile.de/ - ######### + device_replacement: $1$2 + brand_replacement: Sharp + model_replacement: $2 - regex: '; {0,2}(SPX[_\-]\d[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Simvalley' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Simvalley + model_replacement: $1 - regex: '; {0,2}(SX7\-PEARL\.GmbH)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Simvalley' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Simvalley + model_replacement: $1 - regex: '; {0,2}(SP[T]?\-\d{2}[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Simvalley' - model_replacement: '$1' - - ######### - # SK Telesys - # @ref: http://www.sk-w.com/phone/phone_list.jsp - # @ref: http://www.android.com/devices/?country=all&m=sk-telesys - ######### + device_replacement: $1 + brand_replacement: Simvalley + model_replacement: $1 - regex: '; {0,2}(SK\-.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'SKtelesys' - model_replacement: '$1' - - ######### - # Skytex - # @ref: http://skytex.com/android - ######### + device_replacement: $1 + brand_replacement: SKtelesys + model_replacement: $1 - regex: '; {0,2}(?:SKYTEX|SX)-([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Skytex' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Skytex + model_replacement: $1 - regex: '; {0,2}(IMAGINE [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Skytex' - model_replacement: '$1' - - ######### - # SmartQ - # @ref: http://en.smartdevices.com.cn/Products/ - # @models: Z8, X7, U7H, U7, T30, T20, Ten3, V5-II, T7-3G, SmartQ5, K7, S7, Q8, T19, Ten2, Ten, R10, T7, R7, V5, V7, SmartQ7 - ######### + device_replacement: $1 + brand_replacement: Skytex + model_replacement: $1 - regex: '; {0,2}(SmartQ) ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Smartbitt - # @ref: http://www.smartbitt.com/ - # @missing: SBT Useragents - ######### + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(WF7C|WF10C|SBT[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Smartbitt' - model_replacement: '$1' - - ######### - # Softbank (Operator Branded Devices) - # @ref: http://www.ipentec.com/document/document.aspx?page=android-useragent - ######### - - regex: '; {0,2}(SBM(?:003SH|005SH|006SH|007SH|102SH)) Build' - device_replacement: '$1' - brand_replacement: 'Sharp' - model_replacement: '$1' - - regex: '; {0,2}(003P|101P|101P11C|102P) Build' - device_replacement: '$1' - brand_replacement: 'Panasonic' - model_replacement: '$1' - - regex: '; {0,2}(00\dZ) Build/' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' - - regex: '; HTC(X06HT) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: '$1' - - regex: '; {0,2}(001HT|X06HT) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: '$1' - - regex: '; {0,2}(201M) Build' - device_replacement: '$1' - brand_replacement: 'Motorola' - model_replacement: 'XT902' - - ######### - # Trekstor - # @ref: http://www.trekstor.co.uk/surftabs-en.html - # @note: Must come before SonyEricsson - ######### - - regex: '; {0,2}(ST\d{4}.{0,200})Build/ST' - device_replacement: 'Trekstor $1' - brand_replacement: 'Trekstor' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Smartbitt + model_replacement: $1 + - regex: ; {0,2}(SBM(?:003SH|005SH|006SH|007SH|102SH)) Build + device_replacement: $1 + brand_replacement: Sharp + model_replacement: $1 + - regex: ; {0,2}(003P|101P|101P11C|102P) Build + device_replacement: $1 + brand_replacement: Panasonic + model_replacement: $1 + - regex: ; {0,2}(00\dZ) Build/ + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 + - regex: ; HTC(X06HT) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: $1 + - regex: ; {0,2}(001HT|X06HT) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: $1 + - regex: ; {0,2}(201M) Build + device_replacement: $1 + brand_replacement: Motorola + model_replacement: XT902 + - regex: ; {0,2}(ST\d{4}.{0,200})Build/ST + device_replacement: Trekstor $1 + brand_replacement: Trekstor + model_replacement: $1 - regex: '; {0,2}(ST\d{4}.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Trekstor $1' - brand_replacement: 'Trekstor' - model_replacement: '$1' - - ######### - # SonyEricsson - # @note: Must come before nokia since they also use symbian - # @ref: http://www.android.com/devices/?country=all&m=sony-ericssons - # @TODO: type! - ######### - # android matchers - - regex: '; {0,2}(Sony ?Ericsson ?)([^;/]{1,100}) Build' - device_replacement: '$1$2' - brand_replacement: 'SonyEricsson' - model_replacement: '$2' - - regex: '; {0,2}((?: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' - # TODO X\d+ is wrong - - regex: '; {0,2}(Xperia (?:A8|Arc|Acro|Active|Live with Walkman|Mini|Neo|Play|Pro|Ray|X\d+)[^;/]{0,50}) Build' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'SonyEricsson' - model_replacement: '$1' - - ######### - # Sony - # @ref: http://www.sonymobile.co.jp/index.html - # @ref: http://www.sonymobile.com/global-en/products/phones/ - # @ref: http://www.sony.jp/tablet/ - ######### + device_replacement: Trekstor $1 + brand_replacement: Trekstor + model_replacement: $1 + - regex: ; {0,2}(Sony ?Ericsson ?)([^;/]{1,100}) Build + device_replacement: $1$2 + brand_replacement: SonyEricsson + model_replacement: $2 + - regex: ; {0,2}((?: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 + - regex: ; {0,2}(Xperia (?:A8|Arc|Acro|Active|Live with Walkman|Mini|Neo|Play|Pro|Ray|X\d+)[^;/]{0,50}) + Build + regex_flag: i + device_replacement: $1 + brand_replacement: SonyEricsson + model_replacement: $1 - regex: '; Sony (Tablet[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Sony $1' - brand_replacement: 'Sony' - model_replacement: '$1' + device_replacement: Sony $1 + brand_replacement: Sony + model_replacement: $1 - regex: '; Sony ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Sony $1' - brand_replacement: 'Sony' - model_replacement: '$1' + device_replacement: Sony $1 + brand_replacement: Sony + model_replacement: $1 - regex: '; {0,2}(Sony)([A-Za-z0-9\-]+)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(Xperia [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1' - - regex: '; {0,2}(C(?:1[0-9]|2[0-9]|53|55|6[0-9])[0-9]{2}|D[25]\d{3}|D6[56]\d{2})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 + - regex: '; {0,2}(C(?:1[0-9]|2[0-9]|53|55|6[0-9])[0-9]{2}|D[25]\d{3}|D6[56]\d{2})(?: + Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 - regex: '; {0,2}(SGP\d{3}|SGPT\d{2})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 - regex: '; {0,2}(NW-Z1000Series)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1' - - ########## - # Sony PlayStation - # @ref: http://playstation.com - # The Vita spoofs the Kindle - ########## - - regex: 'PLAYSTATION 3' - device_replacement: 'PlayStation 3' - brand_replacement: 'Sony' - model_replacement: 'PlayStation 3' - - regex: '(PlayStation (?:Portable|Vita|\d+))' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1' - - ######### - # Spice - # @ref: http://www.spicemobilephones.co.in/ - ######### - - regex: '; {0,2}((?:CSL_Spice|Spice|SPICE|CSL)[ _\-]?|)([Mm][Ii])([ _\-]|)(\d{3}[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2$3$4' - brand_replacement: 'Spice' - model_replacement: 'Mi$4' - - ######### - # Sprint (Operator Branded Devices) - # @ref: - ######### - - regex: '; {0,2}(Sprint )(.{1,200}?) {0,2}(?:Build|[;/])' - device_replacement: '$1$2' - brand_replacement: 'Sprint' - model_replacement: '$2' + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 + - regex: PLAYSTATION 3 + device_replacement: PlayStation 3 + brand_replacement: Sony + model_replacement: PlayStation 3 + - regex: (PlayStation (?:Portable|Vita|\d+)) + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 + - regex: '; {0,2}((?:CSL_Spice|Spice|SPICE|CSL)[ _\-]?|)([Mm][Ii])([ _\-]|)(\d{3}[^;/]*)(?: + Build|\) AppleWebKit)' + device_replacement: $1$2$3$4 + brand_replacement: Spice + model_replacement: Mi$4 + - regex: ; {0,2}(Sprint )(.{1,200}?) {0,2}(?:Build|[;/]) + device_replacement: $1$2 + brand_replacement: Sprint + model_replacement: $2 - regex: '\b(Sprint)[: ]([^;,/ ]+)' - device_replacement: '$1$2' - brand_replacement: 'Sprint' - model_replacement: '$2' - - ######### - # Tagi - # @ref: ?? - ######### + device_replacement: $1$2 + brand_replacement: Sprint + model_replacement: $2 - regex: '; {0,2}(TAGI[ ]?)(MID) ?([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2$3' - brand_replacement: 'Tagi' - model_replacement: '$2$3' - - ######### - # Tecmobile - # @ref: http://www.tecmobile.com/ - ######### + device_replacement: $1$2$3 + brand_replacement: Tagi + model_replacement: $2$3 - regex: '; {0,2}(Oyster500|Opal 800)(?: Build|\) AppleWebKit)' - device_replacement: 'Tecmobile $1' - brand_replacement: 'Tecmobile' - model_replacement: '$1' - - ######### - # Tecno - # @ref: www.tecno-mobile.com/‎ - ######### + device_replacement: Tecmobile $1 + brand_replacement: Tecmobile + model_replacement: $1 - regex: '; {0,2}(TECNO[ _])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Tecno' - model_replacement: '$2' - - ######### - # Telechips, Techvision evaluation boards - # @ref: - ######### + device_replacement: $1$2 + brand_replacement: Tecno + model_replacement: $2 - regex: '; {0,2}Android for (Telechips|Techvision) ([^ ]+) ' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Telstra - # @ref: http://www.telstra.com.au/home-phone/thub-2/ - # @ref: https://support.google.com/googleplay/answer/1727131?hl=en - ######### + regex_flag: i + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(T-Hub2)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Telstra' - model_replacement: '$1' - - ######### - # Terra - # @ref: http://www.wortmann.de/ - ######### + device_replacement: $1 + brand_replacement: Telstra + model_replacement: $1 - regex: '; {0,2}(PAD) ?(100[12])(?: Build|\) AppleWebKit)' - device_replacement: 'Terra $1$2' - brand_replacement: 'Terra' - model_replacement: '$1$2' - - ######### - # Texet - # @ref: http://www.texet.ru/tablet/ - ######### + device_replacement: Terra $1$2 + brand_replacement: Terra + model_replacement: $1$2 - regex: '; {0,2}(T[BM]-\d{3}[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Texet' - model_replacement: '$1' - - ######### - # Thalia - # @ref: http://www.thalia.de/shop/tolino-shine-ereader/show/ - ######### + device_replacement: $1 + brand_replacement: Texet + model_replacement: $1 - regex: '; {0,2}(tolino [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Thalia' - model_replacement: '$1' - - regex: '; {0,2}Build/.{0,200} (TOLINO_BROWSER)' - device_replacement: '$1' - brand_replacement: 'Thalia' - model_replacement: 'Tolino Shine' - - ######### - # Thl - # @ref: http://en.thl.com.cn/Mobile - # @ref: http://thlmobilestore.com - ######### + device_replacement: $1 + brand_replacement: Thalia + model_replacement: $1 + - regex: ; {0,2}Build/.{0,200} (TOLINO_BROWSER) + device_replacement: $1 + brand_replacement: Thalia + model_replacement: Tolino Shine - regex: '; {0,2}(?:CJ[ -])?(ThL|THL)[ -]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Thl' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: Thl + model_replacement: $2 - regex: '; {0,2}(T100|T200|T5|W100|W200|W8s)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Thl' - model_replacement: '$1' - - ######### - # T-Mobile (Operator Branded Devices) - ######### - # @ref: https://en.wikipedia.org/wiki/HTC_Hero - - regex: '; {0,2}(T-Mobile[ _]G2[ _]Touch) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'Hero' - # @ref: https://en.wikipedia.org/wiki/HTC_Desire_Z - - regex: '; {0,2}(T-Mobile[ _]G2) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'Desire Z' - - regex: '; {0,2}(T-Mobile myTouch Q) Build' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: 'U8730' - - regex: '; {0,2}(T-Mobile myTouch) Build' - device_replacement: '$1' - brand_replacement: 'Huawei' - model_replacement: 'U8680' - - regex: '; {0,2}(T-Mobile_Espresso) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'Espresso' - - regex: '; {0,2}(T-Mobile G1) Build' - device_replacement: '$1' - brand_replacement: 'HTC' - model_replacement: 'Dream' - - regex: '\b(T-Mobile ?|)(myTouch)[ _]?([34]G)[ _]?([^\/]*) (?:Mozilla|Build)' - device_replacement: '$1$2 $3 $4' - brand_replacement: 'HTC' - model_replacement: '$2 $3 $4' - - regex: '\b(T-Mobile)_([^_]+)_(.{0,200}) Build' - device_replacement: '$1 $2 $3' - brand_replacement: 'Tmobile' - model_replacement: '$2 $3' - - regex: '\b(T-Mobile)[_ ]?(.{0,200}?)Build' - device_replacement: '$1 $2' - brand_replacement: 'Tmobile' - model_replacement: '$2' - - ######### - # Tomtec - # @ref: http://www.tom-tec.eu/pages/tablets.php - ######### + device_replacement: $1 + brand_replacement: Thl + model_replacement: $1 + - regex: ; {0,2}(T-Mobile[ _]G2[ _]Touch) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: Hero + - regex: ; {0,2}(T-Mobile[ _]G2) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: Desire Z + - regex: ; {0,2}(T-Mobile myTouch Q) Build + device_replacement: $1 + brand_replacement: Huawei + model_replacement: U8730 + - regex: ; {0,2}(T-Mobile myTouch) Build + device_replacement: $1 + brand_replacement: Huawei + model_replacement: U8680 + - regex: ; {0,2}(T-Mobile_Espresso) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: Espresso + - regex: ; {0,2}(T-Mobile G1) Build + device_replacement: $1 + brand_replacement: HTC + model_replacement: Dream + - regex: \b(T-Mobile ?|)(myTouch)[ _]?([34]G)[ _]?([^\/]*) (?:Mozilla|Build) + device_replacement: $1$2 $3 $4 + brand_replacement: HTC + model_replacement: $2 $3 $4 + - regex: \b(T-Mobile)_([^_]+)_(.{0,200}) Build + device_replacement: $1 $2 $3 + brand_replacement: Tmobile + model_replacement: $2 $3 + - regex: \b(T-Mobile)[_ ]?(.{0,200}?)Build + device_replacement: $1 $2 + brand_replacement: Tmobile + model_replacement: $2 - regex: ' (ATP[0-9]{4})(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Tomtec' - model_replacement: '$1' - - ######### - # Tooky - # @ref: http://www.tookymobile.com/ - ######### + device_replacement: $1 + brand_replacement: Tomtec + model_replacement: $1 - regex: ' ?(TOOKY)[ _\-]([^;/]{1,100}) ?(?:Build|;)' - regex_flag: 'i' - device_replacement: '$1 $2' - brand_replacement: 'Tooky' - model_replacement: '$2' - - ######### - # Toshiba - # @ref: http://www.toshiba.co.jp/ - # @missing: LT170, Thrive 7, TOSHIBA STB10 - ######### - - regex: '\b(TOSHIBA_AC_AND_AZ|TOSHIBA_FOLIO_AND_A|FOLIO_AND_A)' - device_replacement: '$1' - brand_replacement: 'Toshiba' - model_replacement: 'Folio 100' + regex_flag: i + device_replacement: $1 $2 + brand_replacement: Tooky + model_replacement: $2 + - regex: \b(TOSHIBA_AC_AND_AZ|TOSHIBA_FOLIO_AND_A|FOLIO_AND_A) + device_replacement: $1 + brand_replacement: Toshiba + model_replacement: Folio 100 - regex: '; {0,2}([Ff]olio ?100)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Toshiba' - model_replacement: 'Folio 100' - - regex: '; {0,2}(AT[0-9]{2,3}(?:\-A|LE\-A|PE\-A|SE|a|)|AT7-A|AT1S0|Hikari-iFrame/WDPF-[^;/]{1,100}|THRiVE|Thrive)(?: Build|\) AppleWebKit)' - device_replacement: 'Toshiba $1' - brand_replacement: 'Toshiba' - model_replacement: '$1' - - ######### - # Touchmate - # @ref: http://touchmatepc.com/new/ - ######### + device_replacement: $1 + brand_replacement: Toshiba + model_replacement: Folio 100 + - regex: '; {0,2}(AT[0-9]{2,3}(?:\-A|LE\-A|PE\-A|SE|a|)|AT7-A|AT1S0|Hikari-iFrame/WDPF-[^;/]{1,100}|THRiVE|Thrive)(?: + Build|\) AppleWebKit)' + device_replacement: Toshiba $1 + brand_replacement: Toshiba + model_replacement: $1 - regex: '; {0,2}(TM-MID\d+[^;/]{1,50}|TOUCHMATE|MID-750)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Touchmate' - model_replacement: '$1' - # @todo: needs verification user-agents missing + device_replacement: $1 + brand_replacement: Touchmate + model_replacement: $1 - regex: '; {0,2}(TM-SM\d+[^;/]{1,50}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Touchmate' - model_replacement: '$1' - - ######### - # Treq - # @ref: http://www.treq.co.id/product - ######### + device_replacement: $1 + brand_replacement: Touchmate + model_replacement: $1 - regex: '; {0,2}(A10 [Bb]asic2?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Treq' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Treq + model_replacement: $1 - regex: '; {0,2}(TREQ[ _\-])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1$2' - brand_replacement: 'Treq' - model_replacement: '$2' - - ######### - # Umeox - # @ref: http://umeox.com/ - # @models: A936|A603|X-5|X-3 - ######### - # @todo: guessed markers + regex_flag: i + device_replacement: $1$2 + brand_replacement: Treq + model_replacement: $2 - regex: '; {0,2}(X-?5|X-?3)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Umeox' - model_replacement: '$1' - # @todo: guessed markers + device_replacement: $1 + brand_replacement: Umeox + model_replacement: $1 - regex: '; {0,2}(A502\+?|A936|A603|X1|X2)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Umeox' - model_replacement: '$1' - - ######### - # Vernee - # @ref: http://vernee.cc/ - # @models: Thor - Thor E - ######### - - regex: '; thor Build/' - device_replacement: 'Thor' - brand_replacement: 'Vernee' - model_replacement: 'Thor' - # Regex to modidy for Thor Plus (don't find example UA) - - regex: '; Thor (E)? Build/' - device_replacement: 'Thor $1' - brand_replacement: 'Vernee' - model_replacement: 'Thor' - - regex: '; Apollo Lite Build/' - device_replacement: 'Apollo Lite' - brand_replacement: 'Vernee' - model_replacement: 'Apollo' - - ######### - # Versus - # @ref: http://versusuk.com/support.html - ######### + device_replacement: $1 + brand_replacement: Umeox + model_replacement: $1 + - regex: ; thor Build/ + device_replacement: Thor + brand_replacement: Vernee + model_replacement: Thor + - regex: ; Thor (E)? Build/ + device_replacement: Thor $1 + brand_replacement: Vernee + model_replacement: Thor + - regex: ; Apollo Lite Build/ + device_replacement: Apollo Lite + brand_replacement: Vernee + model_replacement: Apollo - regex: '(TOUCH(?:TAB|PAD).{1,200}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Versus $1' - brand_replacement: 'Versus' - model_replacement: '$1' - - ######### - # Vertu - # @ref: http://www.vertu.com/ - ######### + regex_flag: i + device_replacement: Versus $1 + brand_replacement: Versus + model_replacement: $1 - regex: '(VERTU) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'Vertu' - model_replacement: '$2' - - ######### - # Videocon - # @ref: http://www.videoconmobiles.com - ######### - - regex: '; {0,2}(Videocon)[ _\-]([^;/]{1,100}?) {0,2}(?:Build|;)' - device_replacement: '$1 $2' - brand_replacement: 'Videocon' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: Vertu + model_replacement: $2 + - regex: ; {0,2}(Videocon)[ _\-]([^;/]{1,100}?) {0,2}(?:Build|;) + device_replacement: $1 $2 + brand_replacement: Videocon + model_replacement: $2 - regex: ' (VT\d{2}[A-Za-z]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Videocon' - model_replacement: '$1' - - ######### - # Viewsonic - # @ref: http://viewsonic.com - ######### + device_replacement: $1 + brand_replacement: Videocon + model_replacement: $1 - regex: '; {0,2}((?:ViewPad|ViewPhone|VSD)[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Viewsonic' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Viewsonic + model_replacement: $1 - regex: '; {0,2}(ViewSonic-)([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'Viewsonic' - model_replacement: '$2' + device_replacement: $1$2 + brand_replacement: Viewsonic + model_replacement: $2 - regex: '; {0,2}(GTablet.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Viewsonic' - model_replacement: '$1' - - ######### - # vivo - # @ref: http://vivo.cn/ - ######### + device_replacement: $1 + brand_replacement: Viewsonic + model_replacement: $1 - regex: '; {0,2}([Vv]ivo)[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'vivo' - model_replacement: '$2' - - ######### - # Vodafone (Operator Branded Devices) - # @ref: ?? - ######### + device_replacement: $1 $2 + brand_replacement: vivo + model_replacement: $2 - regex: '(Vodafone) (.{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Walton - # @ref: http://www.waltonbd.com/ - ######### + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 - regex: '; {0,2}(?:Walton[ _\-]|)(Primo[ _\-][^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Walton $1' - brand_replacement: 'Walton' - model_replacement: '$1' - - ######### - # Wiko - # @ref: http://fr.wikomobile.com/collection.php?s=Smartphones - ######### - - regex: '; {0,2}(?:WIKO[ \-]|)(CINK\+?|BARRY|BLOOM|DARKFULL|DARKMOON|DARKNIGHT|DARKSIDE|FIZZ|HIGHWAY|IGGY|OZZY|RAINBOW|STAIRWAY|SUBLIM|WAX|CINK [^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Wiko $1' - brand_replacement: 'Wiko' - model_replacement: '$1' - - ######### - # WellcoM - # @ref: ?? - ######### + regex_flag: i + device_replacement: Walton $1 + brand_replacement: Walton + model_replacement: $1 + - regex: '; {0,2}(?:WIKO[ \-]|)(CINK\+?|BARRY|BLOOM|DARKFULL|DARKMOON|DARKNIGHT|DARKSIDE|FIZZ|HIGHWAY|IGGY|OZZY|RAINBOW|STAIRWAY|SUBLIM|WAX|CINK + [^;/]{1,100}?)(?: Build|\) AppleWebKit)' + regex_flag: i + device_replacement: Wiko $1 + brand_replacement: Wiko + model_replacement: $1 - regex: '; {0,2}WellcoM-([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Wellcom $1' - brand_replacement: 'Wellcom' - model_replacement: '$1' - - ########## - # WeTab - # @ref: http://wetab.mobi/ - ########## - - regex: '(?:(WeTab)-Browser|; (wetab) Build)' - device_replacement: '$1' - brand_replacement: 'WeTab' - model_replacement: 'WeTab' - - ######### - # Wolfgang - # @ref: http://wolfgangmobile.com/ - ######### + device_replacement: Wellcom $1 + brand_replacement: Wellcom + model_replacement: $1 + - regex: (?:(WeTab)-Browser|; (wetab) Build) + device_replacement: $1 + brand_replacement: WeTab + model_replacement: WeTab - regex: '; {0,2}(AT-AS[^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Wolfgang $1' - brand_replacement: 'Wolfgang' - model_replacement: '$1' - - ######### - # Woxter - # @ref: http://www.woxter.es/es-es/categories/index - ######### + device_replacement: Wolfgang $1 + brand_replacement: Wolfgang + model_replacement: $1 - regex: '; {0,2}(?:Woxter|Wxt) ([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'Woxter $1' - brand_replacement: 'Woxter' - model_replacement: '$1' - - ######### - # Yarvik Zania - # @ref: http://yarvik.com - ######### - - regex: '; {0,2}(?: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|\) AppleWebKit)' - device_replacement: 'Yarvik $1' - brand_replacement: 'Yarvik' - model_replacement: '$1' - - ######### - # Yifang - # @note: Needs to be at the very last as manufacturer builds for other brands. - # @ref: http://www.yifangdigital.com/ - # @models: M1010, M1011, M1007, M1008, M1005, M899, M899LP, M909, M8000, - # M8001, M8002, M8003, M849, M815, M816, M819, M805, M878, M780LPW, - # M778, M7000, M7000AD, M7000NBD, M7001, M7002, M7002KBD, M777, M767, - # M789, M799, M769, M757, M755, M753, M752, M739, M729, M723, M712, M727 - ######### + device_replacement: Woxter $1 + brand_replacement: Woxter + model_replacement: $1 + - regex: '; {0,2}(?: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|\) AppleWebKit)' + device_replacement: Yarvik $1 + brand_replacement: Yarvik + model_replacement: $1 - regex: '; {0,2}([A-Z]{2,4})(M\d{3,}[A-Z]{2})([^;\)\/]*)(?: Build|[;\)])' - device_replacement: 'Yifang $1$2$3' - brand_replacement: 'Yifang' - model_replacement: '$2' - - ######### - # XiaoMi - # @ref: http://www.xiaomi.com/event/buyphone - ######### - - regex: '; {0,2}((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note |)[^;/]*) (Build|MIUI)/' - device_replacement: 'XiaoMi $1' - brand_replacement: 'XiaoMi' - model_replacement: '$1' - - regex: '; {0,2}((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note |)[^;/\)]*)' - device_replacement: 'XiaoMi $1' - brand_replacement: 'XiaoMi' - model_replacement: '$1' - - regex: '; {0,2}(MIX) (Build|MIUI)/' - device_replacement: 'XiaoMi $1' - brand_replacement: 'XiaoMi' - model_replacement: '$1' - - regex: '; {0,2}((MIX) ([^;/]*)) (Build|MIUI)/' - device_replacement: 'XiaoMi $1' - brand_replacement: 'XiaoMi' - model_replacement: '$1' - - ######### - # Xolo - # @ref: http://www.xolo.in/ - ######### + device_replacement: Yifang $1$2$3 + brand_replacement: Yifang + model_replacement: $2 + - regex: ; {0,2}((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note |)[^;/]*) (Build|MIUI)/ + device_replacement: XiaoMi $1 + brand_replacement: XiaoMi + model_replacement: $1 + - regex: ; {0,2}((Mi|MI|HM|MI-ONE|Redmi)[ -](NOTE |Note |)[^;/\)]*) + device_replacement: XiaoMi $1 + brand_replacement: XiaoMi + model_replacement: $1 + - regex: ; {0,2}(MIX) (Build|MIUI)/ + device_replacement: XiaoMi $1 + brand_replacement: XiaoMi + model_replacement: $1 + - regex: ; {0,2}((MIX) ([^;/]*)) (Build|MIUI)/ + device_replacement: XiaoMi $1 + brand_replacement: XiaoMi + model_replacement: $1 - regex: '; {0,2}XOLO[ _]([^;/]{0,30}tab.{0,30})(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Xolo $1' - brand_replacement: 'Xolo' - model_replacement: '$1' + regex_flag: i + device_replacement: Xolo $1 + brand_replacement: Xolo + model_replacement: $1 - regex: '; {0,2}XOLO[ _]([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Xolo $1' - brand_replacement: 'Xolo' - model_replacement: '$1' + regex_flag: i + device_replacement: Xolo $1 + brand_replacement: Xolo + model_replacement: $1 - regex: '; {0,2}(q\d0{2,3}[a-z]?)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: 'Xolo $1' - brand_replacement: 'Xolo' - model_replacement: '$1' - - ######### - # Xoro - # @ref: http://www.xoro.de/produkte/ - ######### + regex_flag: i + device_replacement: Xolo $1 + brand_replacement: Xolo + model_replacement: $1 - regex: '; {0,2}(PAD ?[79]\d+[^;/]{0,50}|TelePAD\d+[^;/])(?: Build|\) AppleWebKit)' - device_replacement: 'Xoro $1' - brand_replacement: 'Xoro' - model_replacement: '$1' - - ######### - # Zopo - # @ref: http://www.zopomobiles.com/products.html - ######### - - regex: '; {0,2}(?:(?:ZOPO|Zopo)[ _]([^;/]{1,100}?)|(ZP ?(?:\d{2}[^;/]{1,100}|C2))|(C[2379]))(?: Build|\) AppleWebKit)' - device_replacement: '$1$2$3' - brand_replacement: 'Zopo' - model_replacement: '$1$2$3' - - ######### - # ZiiLabs - # @ref: http://www.ziilabs.com/products/platforms/androidreferencetablets.php - ######### + device_replacement: Xoro $1 + brand_replacement: Xoro + model_replacement: $1 + - regex: '; {0,2}(?:(?:ZOPO|Zopo)[ _]([^;/]{1,100}?)|(ZP ?(?:\d{2}[^;/]{1,100}|C2))|(C[2379]))(?: + Build|\) AppleWebKit)' + device_replacement: $1$2$3 + brand_replacement: Zopo + model_replacement: $1$2$3 - regex: '; {0,2}(ZiiLABS) (Zii[^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'ZiiLabs' - model_replacement: '$2' + device_replacement: $1 $2 + brand_replacement: ZiiLabs + model_replacement: $2 - regex: '; {0,2}(Zii)_([^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'ZiiLabs' - model_replacement: '$2' - - ######### - # ZTE - # @ref: http://www.ztedevices.com/ - ######### - - regex: '; {0,2}(ARIZONA|(?:ATLAS|Atlas) W|D930|Grand (?:[SX][^;]{0,200}?|Era|Memo[^;]{0,200}?)|JOE|(?:Kis|KIS)\b[^;]{0,200}?|Libra|Light [^;]{0,200}?|N8[056][01]|N850L|N8000|N9[15]\d{2}|N9810|NX501|Optik|(?:Vip )Racer[^;]{0,200}?|RacerII|RACERII|San Francisco[^;]{0,200}?|V9[AC]|V55|V881|Z[679][0-9]{2}[A-z]?)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' + device_replacement: $1 $2 + brand_replacement: ZiiLabs + model_replacement: $2 + - regex: '; {0,2}(ARIZONA|(?:ATLAS|Atlas) W|D930|Grand (?:[SX][^;]{0,200}?|Era|Memo[^;]{0,200}?)|JOE|(?:Kis|KIS)\b[^;]{0,200}?|Libra|Light + [^;]{0,200}?|N8[056][01]|N850L|N8000|N9[15]\d{2}|N9810|NX501|Optik|(?:Vip )Racer[^;]{0,200}?|RacerII|RACERII|San + Francisco[^;]{0,200}?|V9[AC]|V55|V881|Z[679][0-9]{2}[A-z]?)(?: Build|\) AppleWebKit)' + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 - regex: '; {0,2}([A-Z]\d+)_USA_[^;]{0,200}(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 - regex: '; {0,2}(SmartTab\d+)[^;]{0,50}(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 - regex: '; {0,2}(?:Blade|BLADE|ZTE-BLADE)([^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'ZTE Blade$1' - brand_replacement: 'ZTE' - model_replacement: 'Blade$1' + device_replacement: ZTE Blade$1 + brand_replacement: ZTE + model_replacement: Blade$1 - regex: '; {0,2}(?:Skate|SKATE|ZTE-SKATE)([^;/]*)(?: Build|\) AppleWebKit)' - device_replacement: 'ZTE Skate$1' - brand_replacement: 'ZTE' - model_replacement: 'Skate$1' + device_replacement: ZTE Skate$1 + brand_replacement: ZTE + model_replacement: Skate$1 - regex: '; {0,2}(Orange |Optimus )(Monte Carlo|San Francisco)(?: Build|\) AppleWebKit)' - device_replacement: '$1$2' - brand_replacement: 'ZTE' - model_replacement: '$1$2' - - regex: '; {0,2}(?:ZXY-ZTE_|ZTE\-U |ZTE[\- _]|ZTE-C[_ ])([^;/]{1,100}?)(?: Build|\) AppleWebKit)' - device_replacement: 'ZTE $1' - brand_replacement: 'ZTE' - model_replacement: '$1' - # operator specific + device_replacement: $1$2 + brand_replacement: ZTE + model_replacement: $1$2 + - regex: '; {0,2}(?:ZXY-ZTE_|ZTE\-U |ZTE[\- _]|ZTE-C[_ ])([^;/]{1,100}?)(?: Build|\) + AppleWebKit)' + device_replacement: ZTE $1 + brand_replacement: ZTE + model_replacement: $1 - regex: '; (BASE) (lutea|Lutea 2|Tab[^;]{0,200}?)(?: Build|\) AppleWebKit)' - device_replacement: '$1 $2' - brand_replacement: 'ZTE' - model_replacement: '$1 $2' - - regex: '; (Avea inTouch 2|soft stone|tmn smart a7|Movistar[ _]Link)(?: Build|\) AppleWebKit)' - regex_flag: 'i' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' - - regex: '; {0,2}(vp9plus)\)' - device_replacement: '$1' - brand_replacement: 'ZTE' - model_replacement: '$1' - - ########## - # Zync - # @ref: http://www.zync.in/index.php/our-products/tablet-phablets - ########## - - regex: '; ?(Cloud[ _]Z5|z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900)(?: Build|\) AppleWebKit)' - device_replacement: '$1' - brand_replacement: 'Zync' - model_replacement: '$1' - - ########## - # Kindle - # @note: Needs to be after Sony Playstation Vita as this UA contains Silk/3.2 - # @ref: https://developer.amazon.com/sdk/fire/specifications.html - # @ref: http://amazonsilk.wordpress.com/useful-bits/silk-user-agent/ - ########## - - regex: '; ?(KFOT|Kindle Fire) Build\b' - device_replacement: 'Kindle Fire' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire' - - regex: '; ?(KFOTE|Amazon Kindle Fire2) Build\b' - device_replacement: 'Kindle Fire 2' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire 2' - - regex: '; ?(KFTT) Build\b' - device_replacement: 'Kindle Fire HD' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HD 7"' - - regex: '; ?(KFJWI) Build\b' - device_replacement: 'Kindle Fire HD 8.9" WiFi' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HD 8.9" WiFi' - - regex: '; ?(KFJWA) Build\b' - device_replacement: 'Kindle Fire HD 8.9" 4G' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HD 8.9" 4G' - - regex: '; ?(KFSOWI) Build\b' - device_replacement: 'Kindle Fire HD 7" WiFi' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HD 7" WiFi' - - regex: '; ?(KFTHWI) Build\b' - device_replacement: 'Kindle Fire HDX 7" WiFi' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HDX 7" WiFi' - - regex: '; ?(KFTHWA) Build\b' - device_replacement: 'Kindle Fire HDX 7" 4G' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HDX 7" 4G' - - regex: '; ?(KFAPWI) Build\b' - device_replacement: 'Kindle Fire HDX 8.9" WiFi' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HDX 8.9" WiFi' - - regex: '; ?(KFAPWA) Build\b' - device_replacement: 'Kindle Fire HDX 8.9" 4G' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire HDX 8.9" 4G' - - regex: '; ?Amazon ([^;/]{1,100}) Build\b' - device_replacement: '$1' - brand_replacement: 'Amazon' - model_replacement: '$1' - - regex: '; ?(Kindle) Build\b' - device_replacement: 'Kindle' - brand_replacement: 'Amazon' - model_replacement: 'Kindle' - - regex: '; ?(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|) Build\b' - device_replacement: 'Kindle Fire' - brand_replacement: 'Amazon' - model_replacement: 'Kindle Fire$2' + device_replacement: $1 $2 + brand_replacement: ZTE + model_replacement: $1 $2 + - regex: '; (Avea inTouch 2|soft stone|tmn smart a7|Movistar[ _]Link)(?: Build|\) + AppleWebKit)' + regex_flag: i + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 + - regex: ; {0,2}(vp9plus)\) + device_replacement: $1 + brand_replacement: ZTE + model_replacement: $1 + - regex: '; ?(Cloud[ _]Z5|z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900)(?: Build|\) + AppleWebKit)' + device_replacement: $1 + brand_replacement: Zync + model_replacement: $1 + - regex: ; ?(KFOT|Kindle Fire) Build\b + device_replacement: Kindle Fire + brand_replacement: Amazon + model_replacement: Kindle Fire + - regex: ; ?(KFOTE|Amazon Kindle Fire2) Build\b + device_replacement: Kindle Fire 2 + brand_replacement: Amazon + model_replacement: Kindle Fire 2 + - regex: ; ?(KFTT) Build\b + device_replacement: Kindle Fire HD + brand_replacement: Amazon + model_replacement: Kindle Fire HD 7" + - regex: ; ?(KFJWI) Build\b + device_replacement: Kindle Fire HD 8.9" WiFi + brand_replacement: Amazon + model_replacement: Kindle Fire HD 8.9" WiFi + - regex: ; ?(KFJWA) Build\b + device_replacement: Kindle Fire HD 8.9" 4G + brand_replacement: Amazon + model_replacement: Kindle Fire HD 8.9" 4G + - regex: ; ?(KFSOWI) Build\b + device_replacement: Kindle Fire HD 7" WiFi + brand_replacement: Amazon + model_replacement: Kindle Fire HD 7" WiFi + - regex: ; ?(KFTHWI) Build\b + device_replacement: Kindle Fire HDX 7" WiFi + brand_replacement: Amazon + model_replacement: Kindle Fire HDX 7" WiFi + - regex: ; ?(KFTHWA) Build\b + device_replacement: Kindle Fire HDX 7" 4G + brand_replacement: Amazon + model_replacement: Kindle Fire HDX 7" 4G + - regex: ; ?(KFAPWI) Build\b + device_replacement: Kindle Fire HDX 8.9" WiFi + brand_replacement: Amazon + model_replacement: Kindle Fire HDX 8.9" WiFi + - regex: ; ?(KFAPWA) Build\b + device_replacement: Kindle Fire HDX 8.9" 4G + brand_replacement: Amazon + model_replacement: Kindle Fire HDX 8.9" 4G + - regex: ; ?Amazon ([^;/]{1,100}) Build\b + device_replacement: $1 + brand_replacement: Amazon + model_replacement: $1 + - regex: ; ?(Kindle) Build\b + device_replacement: Kindle + brand_replacement: Amazon + model_replacement: Kindle + - regex: ; ?(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+)|) Build\b + device_replacement: Kindle Fire + brand_replacement: Amazon + model_replacement: Kindle Fire$2 - regex: ' (Kindle)/(\d+\.\d+)' - device_replacement: 'Kindle' - brand_replacement: 'Amazon' - model_replacement: '$1 $2' + device_replacement: Kindle + brand_replacement: Amazon + model_replacement: $1 $2 - regex: ' (Silk|Kindle)/(\d+)\.' - device_replacement: 'Kindle' - brand_replacement: 'Amazon' - model_replacement: 'Kindle' - - ######### - # Devices from chinese manufacturer(s) - # @note: identified by x-wap-profile http://218.249.47.94/Xianghe/.{0,200} - ######### - - regex: '(sprd)\-([^/]{1,50})/' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - # @ref: http://eshinechina.en.alibaba.com/ - - regex: '; {0,2}(H\d{2}00\+?) Build' - device_replacement: '$1' - brand_replacement: 'Hero' - model_replacement: '$1' - - regex: '; {0,2}(iphone|iPhone5) Build/' - device_replacement: 'Xianghe $1' - brand_replacement: 'Xianghe' - model_replacement: '$1' - - regex: '; {0,2}(e\d{4}[a-z]?_?v\d+|v89_[^;/]{1,100})[^;/]{1,30} Build/' - device_replacement: 'Xianghe $1' - brand_replacement: 'Xianghe' - model_replacement: '$1' - - ######### - # Cellular - # @ref: - # @note: Operator branded devices - ######### - - regex: '\bUSCC[_\-]?([^ ;/\)]+)' - device_replacement: '$1' - brand_replacement: 'Cellular' - model_replacement: '$1' - - ###################################################################### - # Windows Phone Parsers - ###################################################################### - - ######### - # Alcatel Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:ALCATEL)[^;]{0,200}; {0,2}([^;,\)]+)' - device_replacement: 'Alcatel $1' - brand_replacement: 'Alcatel' - model_replacement: '$1' - - ######### - # Asus Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|WpsLondonTest; ?|)(?:ASUS|Asus)[^;]{0,200}; {0,2}([^;,\)]+)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' - - ######### - # Dell Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:DELL|Dell)[^;]{0,200}; {0,2}([^;,\)]+)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: '$1' - - ######### - # HTC Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|WpsLondonTest; ?|)(?:HTC|Htc|HTC_blocked[^;]{0,200})[^;]{0,200}; {0,2}(?:HTC|)([^;,\)]+)' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - ######### - # Huawei Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:HUAWEI)[^;]{0,200}; {0,2}(?:HUAWEI |)([^;,\)]+)' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - ######### - # LG Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:LG|Lg)[^;]{0,200}; {0,2}(?:LG[ \-]|)([^;,\)]+)' - device_replacement: 'LG $1' - brand_replacement: 'LG' - model_replacement: '$1' - - ######### - # Noka Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:rv:11; |)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(?:NOKIA ?|Nokia ?|LUMIA ?|[Ll]umia ?|)(\d{3,10}[^;\)]*)' - device_replacement: 'Lumia $1' - brand_replacement: 'Nokia' - model_replacement: 'Lumia $1' - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(RM-\d{3,})' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1' - - regex: '(?:Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)]|WPDesktop;) ?(?:ARM; ?Touch; ?|Touch; ?|)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(?:NOKIA ?|Nokia ?|LUMIA ?|[Ll]umia ?|)([^;\)]+)' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1' - - ######### - # Microsoft Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|)(?:Microsoft(?: Corporation|))[^;]{0,200}; {0,2}([^;,\)]+)' - device_replacement: 'Microsoft $1' - brand_replacement: 'Microsoft' - model_replacement: '$1' - - ######### - # Samsung Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|WpsLondonTest; ?|)(?:SAMSUNG)[^;]{0,200}; {0,2}(?:SAMSUNG |)([^;,\.\)]+)' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - ######### - # Toshiba Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|WpsLondonTest; ?|)(?:TOSHIBA|FujitsuToshibaMobileCommun)[^;]{0,200}; {0,2}([^;,\)]+)' - device_replacement: 'Toshiba $1' - brand_replacement: 'Toshiba' - model_replacement: '$1' - - ######### - # Generic Windows Phones - ######### - - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; ?|Touch; ?|WpsLondonTest; ?|)([^;]{1,200}); {0,2}([^;,\)]+)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ###################################################################### - # Other Devices Parser - ###################################################################### - - ######### - # Samsung Bada Phones - ######### - - regex: '(?:^|; )SAMSUNG\-([A-Za-z0-9\-]{1,50}).{0,200} Bada/' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - ######### - # Firefox OS - ######### - - regex: '\(Mobile; ALCATEL ?(One|ONE) ?(Touch|TOUCH) ?([^;/]{1,100}?)(?:/[^;]{1,200}|); rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} Firefox/' - device_replacement: 'Alcatel $1 $2 $3' - brand_replacement: 'Alcatel' - model_replacement: 'One Touch $3' - - regex: '\(Mobile; (?:ZTE([^;]{1,200})|(OpenC)); rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} Firefox/' - device_replacement: 'ZTE $1$2' - brand_replacement: 'ZTE' - model_replacement: '$1$2' - - ######### - # KaiOS - ######### - - regex: '\(Mobile; ALCATEL([A-Za-z0-9\-]+); rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} Firefox/[^\/]{1,200} KaiOS/' - device_replacement: 'Alcatel $1' - brand_replacement: 'Alcatel' - model_replacement: '$1' - - regex: '\(Mobile; LYF\/([A-Za-z0-9\-]{1,100})\/.{0,100};.{0,100}rv:[^\)]{1,100}\) Gecko/[^\/]{1,100} Firefox/[^\/]{1,100} KAIOS/' - device_replacement: 'LYF $1' - brand_replacement: 'LYF' - model_replacement: '$1' - - regex: '\(Mobile; Nokia_([A-Za-z0-9\-]{1,100})_.{1,100}; rv:[^\)]{1,100}\) Gecko/[^\/]{1,100} Firefox/[^\/]{1,100} KAIOS/' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1' - - ########## - # NOKIA - # @note: NokiaN8-00 comes before iphone. Sometimes spoofs iphone - ########## - - regex: 'Nokia(N[0-9]+)([A-Za-z_\-][A-Za-z0-9_\-]*)' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1$2' - - regex: '(?:NOKIA|Nokia)(?:\-| {0,2})(?:([A-Za-z0-9]+)\-[0-9a-f]{32}|([A-Za-z0-9\-]+)(?:UCBrowser)|([A-Za-z0-9\-]+))' - device_replacement: 'Nokia $1$2$3' - brand_replacement: 'Nokia' - model_replacement: '$1$2$3' - - regex: 'Lumia ([A-Za-z0-9\-]+)' - device_replacement: 'Lumia $1' - brand_replacement: 'Nokia' - model_replacement: 'Lumia $1' - # UCWEB Browser on Symbian - - regex: '\(Symbian; U; S60 V5; [A-z]{2}\-[A-z]{2}; (SonyEricsson|Samsung|Nokia|LG)([^;/]{1,100}?)\)' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - # Nokia Symbian - - regex: '\(Symbian(?:/3|); U; ([^;]{1,200});' - device_replacement: 'Nokia $1' - brand_replacement: 'Nokia' - model_replacement: '$1' - - ########## - # BlackBerry - # @ref: http://www.useragentstring.com/pages/BlackBerry/ - ########## - - regex: 'BB10; ([A-Za-z0-9\- ]+)\)' - device_replacement: 'BlackBerry $1' - brand_replacement: 'BlackBerry' - model_replacement: '$1' - - regex: 'Play[Bb]ook.{1,200}RIM Tablet OS' - device_replacement: 'BlackBerry Playbook' - brand_replacement: 'BlackBerry' - model_replacement: 'Playbook' - - regex: 'Black[Bb]erry ([0-9]+);' - device_replacement: 'BlackBerry $1' - brand_replacement: 'BlackBerry' - model_replacement: '$1' - - regex: 'Black[Bb]erry([0-9]+)' - device_replacement: 'BlackBerry $1' - brand_replacement: 'BlackBerry' - model_replacement: '$1' - - regex: 'Black[Bb]erry;' - device_replacement: 'BlackBerry' - brand_replacement: 'BlackBerry' - - ########## - # PALM / HP - # @note: some palm devices must come before iphone. sometimes spoofs iphone in ua - ########## - - regex: '(Pre|Pixi)/\d+\.\d+' - device_replacement: 'Palm $1' - brand_replacement: 'Palm' - model_replacement: '$1' - - regex: 'Palm([0-9]+)' - device_replacement: 'Palm $1' - brand_replacement: 'Palm' - model_replacement: '$1' - - regex: 'Treo([A-Za-z0-9]+)' - device_replacement: 'Palm Treo $1' - brand_replacement: 'Palm' - model_replacement: 'Treo $1' - - regex: 'webOS.{0,200}(P160U(?:NA|))/(\d+).(\d+)' - device_replacement: 'HP Veer' - brand_replacement: 'HP' - model_replacement: 'Veer' - - regex: '(Touch[Pp]ad)/\d+\.\d+' - device_replacement: 'HP TouchPad' - brand_replacement: 'HP' - model_replacement: 'TouchPad' - - regex: 'HPiPAQ([A-Za-z0-9]{1,20})/\d+\.\d+' - device_replacement: 'HP iPAQ $1' - brand_replacement: 'HP' - model_replacement: 'iPAQ $1' - - regex: 'PDA; (PalmOS)/sony/model ([a-z]+)/Revision' - device_replacement: '$1' - brand_replacement: 'Sony' - model_replacement: '$1 $2' - - ########## - # AppleTV - # No built in browser that I can tell - # Stack Overflow indicated iTunes-AppleTV/4.1 as a known UA for app available and I'm seeing it in live traffic - ########## - - regex: '(Apple\s?TV)' - device_replacement: 'AppleTV' - brand_replacement: 'Apple' - model_replacement: 'AppleTV' - - ######### - # Tesla Model S - ######### - - regex: '(QtCarBrowser)' - device_replacement: 'Tesla Model S' - brand_replacement: 'Tesla' - model_replacement: 'Model S' - - ########## - # iSTUFF - # @note: complete but probably catches spoofs - # ipad and ipod must be parsed before iphone - # cannot determine specific device type from ua string. (3g, 3gs, 4, etc) - ########## - # @note: on some ua the device can be identified e.g. iPhone5,1 - - regex: '(iPhone|iPad|iPod)(\d+,\d+)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1$2' - # @note: iPad needs to be before iPhone - - regex: '(iPad)(?:;| Simulator;)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1' - - regex: '(iPod)(?:;| touch;| Simulator;)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1' - - regex: '(iPhone)(?:;| Simulator;)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1' - - regex: '(Watch)(\d+,\d+)' - device_replacement: 'Apple $1' - brand_replacement: 'Apple' - model_replacement: '$1$2' - - regex: '(Apple Watch)(?:;| Simulator;)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1' - - regex: '(HomePod)(?:;| Simulator;)' - device_replacement: '$1' - brand_replacement: 'Apple' - model_replacement: '$1' - - regex: 'iPhone' - device_replacement: 'iPhone' - brand_replacement: 'Apple' - model_replacement: 'iPhone' - # @note: desktop applications show device info - - regex: 'CFNetwork/.{0,100} Darwin/\d.{0,100}\(((?:Mac|iMac|PowerMac|PowerBook)[^\d]*)(\d+)(?:,|%2C)(\d+)' - device_replacement: '$1$2,$3' - brand_replacement: 'Apple' - model_replacement: '$1$2,$3' - # @note: newer desktop applications don't show device info - # This is here so as to not have them recorded as iOS-Device - - regex: 'CFNetwork/.{0,100} Darwin/\d+\.\d+\.\d+ \(x86_64\)' - device_replacement: 'Mac' - brand_replacement: 'Apple' - model_replacement: 'Mac' - # @note: iOS applications do not show device info - - regex: 'CFNetwork/.{0,100} Darwin/\d' - device_replacement: 'iOS-Device' - brand_replacement: 'Apple' - model_replacement: 'iOS-Device' - - ########################## - # Outlook on iOS >= 2.62.0 - ########################## - - regex: 'Outlook-(iOS)/\d+\.\d+\.prod\.iphone' - brand_replacement: 'Apple' - device_replacement: 'iPhone' - model_replacement: 'iPhone' - - ########## - # Acer - ########## - - regex: 'acer_([A-Za-z0-9]+)_' - device_replacement: 'Acer $1' - brand_replacement: 'Acer' - model_replacement: '$1' - - ########## - # Alcatel - ########## - - regex: '(?:ALCATEL|Alcatel)-([A-Za-z0-9\-]+)' - device_replacement: 'Alcatel $1' - brand_replacement: 'Alcatel' - model_replacement: '$1' - - ########## - # Amoi - ########## - - regex: '(?:Amoi|AMOI)\-([A-Za-z0-9]+)' - device_replacement: 'Amoi $1' - brand_replacement: 'Amoi' - model_replacement: '$1' - - ########## - # Asus - ########## - - regex: '(?:; |\/|^)((?:Transformer (?:Pad|Prime) |Transformer |PadFone[ _]?)[A-Za-z0-9]*)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' - - regex: '(?:asus.{0,200}?ASUS|Asus|ASUS|asus)[\- ;]*((?:Transformer (?:Pad|Prime) |Transformer |Padfone |Nexus[ _]|)[A-Za-z0-9]+)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' - - regex: '(?:ASUS)_([A-Za-z0-9\-]+)' - device_replacement: 'Asus $1' - brand_replacement: 'Asus' - model_replacement: '$1' - - - ########## - # Bird - ########## - - regex: '\bBIRD[ \-\.]([A-Za-z0-9]+)' - device_replacement: 'Bird $1' - brand_replacement: 'Bird' - model_replacement: '$1' - - ########## - # Dell - ########## - - regex: '\bDell ([A-Za-z0-9]+)' - device_replacement: 'Dell $1' - brand_replacement: 'Dell' - model_replacement: '$1' - - ########## - # DoCoMo - ########## - - regex: 'DoCoMo/2\.0 ([A-Za-z0-9]+)' - device_replacement: 'DoCoMo $1' - brand_replacement: 'DoCoMo' - model_replacement: '$1' - - regex: '^.{0,50}?([A-Za-z0-9]{1,30})_W;FOMA' - device_replacement: 'DoCoMo $1' - brand_replacement: 'DoCoMo' - model_replacement: '$1' - - regex: '^.{0,50}?([A-Za-z0-9]{1,30});FOMA' - device_replacement: 'DoCoMo $1' - brand_replacement: 'DoCoMo' - model_replacement: '$1' - - ########## - # htc - ########## - - regex: '\b(?:HTC/|HTC/[a-z0-9]{1,20}/|)HTC[ _\-;]? {0,2}(.{0,200}?)(?:-?Mozilla|fingerPrint|[;/\(\)]|$)' - device_replacement: 'HTC $1' - brand_replacement: 'HTC' - model_replacement: '$1' - - ########## - # Huawei - ########## - - regex: 'Huawei([A-Za-z0-9]+)' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: 'HUAWEI-([A-Za-z0-9]+)' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: 'HUAWEI ([A-Za-z0-9\-]+)' - device_replacement: 'Huawei $1' - brand_replacement: 'Huawei' - model_replacement: '$1' - - regex: 'vodafone([A-Za-z0-9]+)' - device_replacement: 'Huawei Vodafone $1' - brand_replacement: 'Huawei' - model_replacement: 'Vodafone $1' - - ########## - # i-mate - ########## - - regex: 'i\-mate ([A-Za-z0-9]+)' - device_replacement: 'i-mate $1' - brand_replacement: 'i-mate' - model_replacement: '$1' - - ########## - # kyocera - ########## - - regex: 'Kyocera\-([A-Za-z0-9]+)' - device_replacement: 'Kyocera $1' - brand_replacement: 'Kyocera' - model_replacement: '$1' - - regex: 'KWC\-([A-Za-z0-9]+)' - device_replacement: 'Kyocera $1' - brand_replacement: 'Kyocera' - model_replacement: '$1' - - ########## - # lenovo - ########## - - regex: 'Lenovo[_\-]([A-Za-z0-9]+)' - device_replacement: 'Lenovo $1' - brand_replacement: 'Lenovo' - model_replacement: '$1' - - ########## - # HbbTV (European and Australian standard) - # written before the LG regexes, as LG is making HbbTV too - ########## - - regex: '(HbbTV)/[0-9]+\.[0-9]+\.[0-9]+ \( ?;(LG)E ?;([^;]{0,30})' - device_replacement: '$1' - brand_replacement: '$2' - model_replacement: '$3' - - regex: '(HbbTV)/1\.1\.1.{0,200}CE-HTML/1\.\d;(Vendor/|)(THOM[^;]{0,200}?)[;\s].{0,30}(LF[^;]{1,200});?' - device_replacement: '$1' - brand_replacement: 'Thomson' - model_replacement: '$4' - - regex: '(HbbTV)(?:/1\.1\.1|) ?(?: \(;;;;;\)|); {0,2}CE-HTML(?:/1\.\d|); {0,2}([^ ]{1,30}) ([^;]{1,200});' - device_replacement: '$1' - brand_replacement: '$2' - model_replacement: '$3' - - regex: '(HbbTV)/1\.1\.1 \(;;;;;\) Maple_2011' - device_replacement: '$1' - brand_replacement: 'Samsung' - - regex: '(HbbTV)/[0-9]+\.[0-9]+\.[0-9]+ \([^;]{0,30}; ?(?:CUS:([^;]{0,200})|([^;]{1,200})) ?; ?([^;]{0,30})' - device_replacement: '$1' - brand_replacement: '$2$3' - model_replacement: '$4' - - regex: '(HbbTV)/[0-9]+\.[0-9]+\.[0-9]+' - device_replacement: '$1' - - ########## - # LGE NetCast TV - ########## - - regex: 'LGE; (?:Media\/|)([^;]{0,200});[^;]{0,200};[^;]{0,200};?\); "?LG NetCast(\.TV|\.Media|)-\d+' - device_replacement: 'NetCast$2' - brand_replacement: 'LG' - model_replacement: '$1' - - ########## - # InettvBrowser - ########## - - regex: 'InettvBrowser/[0-9]{1,30}\.[0-9A-Z]{1,30} \([^;]{0,200};(Sony)([^;]{0,200});[^;]{0,200};[^\)]{0,10}\)' - device_replacement: 'Inettv' - brand_replacement: '$1' - model_replacement: '$2' - - regex: 'InettvBrowser/[0-9]{1,30}\.[0-9A-Z]{1,30} \([^;]{0,200};([^;]{0,200});[^;]{0,200};[^\)]{0,10}\)' - device_replacement: 'Inettv' - brand_replacement: 'Generic_Inettv' - model_replacement: '$1' - - regex: '(?:InettvBrowser|TSBNetTV|NETTV|HBBTV)' - device_replacement: 'Inettv' - brand_replacement: 'Generic_Inettv' - - ########## - # lg - ########## - # LG Symbian Phones - - regex: 'Series60/\d\.\d (LG)[\-]?([A-Za-z0-9 \-]+)' - device_replacement: '$1 $2' - 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' - device_replacement: 'LG $1' - brand_replacement: 'LG' - model_replacement: '$1' - - regex: '(?:^LG[\-]?|^LGE[\-/]?)([A-Za-z]+[0-9]+[A-Za-z]*)' - device_replacement: 'LG $1' - brand_replacement: 'LG' - model_replacement: '$1' - - regex: '^LG([0-9]+[A-Za-z]*)' - device_replacement: 'LG $1' - brand_replacement: 'LG' - model_replacement: '$1' - - ########## - # microsoft - ########## - - regex: '(KIN\.[^ ]+) (\d+)\.(\d+)' - device_replacement: 'Microsoft $1' - brand_replacement: 'Microsoft' - model_replacement: '$1' - - regex: '(?:MSIE|XBMC).{0,200}\b(Xbox)\b' - device_replacement: '$1' - brand_replacement: 'Microsoft' - model_replacement: '$1' - - regex: '; ARM; Trident/6\.0; Touch[\);]' - device_replacement: 'Microsoft Surface RT' - brand_replacement: 'Microsoft' - model_replacement: 'Surface RT' - - ########## - # motorola - ########## - - regex: 'Motorola\-([A-Za-z0-9]+)' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: '$1' - - regex: 'MOTO\-([A-Za-z0-9]+)' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: '$1' - - regex: 'MOT\-([A-z0-9][A-z0-9\-]*)' - device_replacement: 'Motorola $1' - brand_replacement: 'Motorola' - model_replacement: '$1' + device_replacement: Kindle + brand_replacement: Amazon + model_replacement: Kindle + - regex: (sprd)\-([^/]{1,50})/ + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - regex: ; {0,2}(H\d{2}00\+?) Build + device_replacement: $1 + brand_replacement: Hero + model_replacement: $1 + - regex: ; {0,2}(iphone|iPhone5) Build/ + device_replacement: Xianghe $1 + brand_replacement: Xianghe + model_replacement: $1 + - regex: ; {0,2}(e\d{4}[a-z]?_?v\d+|v89_[^;/]{1,100})[^;/]{1,30} Build/ + device_replacement: Xianghe $1 + brand_replacement: Xianghe + model_replacement: $1 + - regex: \bUSCC[_\-]?([^ ;/\)]+) + device_replacement: $1 + brand_replacement: Cellular + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:ALCATEL)[^;]{0,200}; {0,2}([^;,\)]+) + device_replacement: Alcatel $1 + brand_replacement: Alcatel + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|WpsLondonTest; ?|)(?:ASUS|Asus)[^;]{0,200}; {0,2}([^;,\)]+) + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:DELL|Dell)[^;]{0,200}; {0,2}([^;,\)]+) + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|WpsLondonTest; ?|)(?:HTC|Htc|HTC_blocked[^;]{0,200})[^;]{0,200}; + {0,2}(?:HTC|)([^;,\)]+) + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:HUAWEI)[^;]{0,200}; {0,2}(?:HUAWEI |)([^;,\)]+) + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:LG|Lg)[^;]{0,200}; {0,2}(?:LG[ \-]|)([^;,\)]+) + device_replacement: LG $1 + brand_replacement: LG + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:rv:11; |)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(?:NOKIA ?|Nokia ?|LUMIA + ?|[Ll]umia ?|)(\d{3,10}[^;\)]*) + device_replacement: Lumia $1 + brand_replacement: Nokia + model_replacement: Lumia $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(RM-\d{3,}) + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1 + - regex: (?:Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)]|WPDesktop;) + ?(?:ARM; ?Touch; ?|Touch; ?|)(?:NOKIA|Nokia)[^;]{0,200}; {0,2}(?:NOKIA ?|Nokia + ?|LUMIA ?|[Ll]umia ?|)([^;\)]+) + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1 + - regex: 'Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|)(?:Microsoft(?: Corporation|))[^;]{0,200}; {0,2}([^;,\)]+)' + device_replacement: Microsoft $1 + brand_replacement: Microsoft + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|WpsLondonTest; ?|)(?:SAMSUNG)[^;]{0,200}; {0,2}(?:SAMSUNG |)([^;,\.\)]+) + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|WpsLondonTest; ?|)(?:TOSHIBA|FujitsuToshibaMobileCommun)[^;]{0,200}; + {0,2}([^;,\)]+) + device_replacement: Toshiba $1 + brand_replacement: Toshiba + model_replacement: $1 + - regex: Windows Phone [^;]{1,30}; .{0,100}?IEMobile/[^;\)]+[;\)] ?(?:ARM; ?Touch; + ?|Touch; ?|WpsLondonTest; ?|)([^;]{1,200}); {0,2}([^;,\)]+) + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - regex: (?:^|; )SAMSUNG\-([A-Za-z0-9\-]{1,50}).{0,200} Bada/ + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: \(Mobile; ALCATEL ?(One|ONE) ?(Touch|TOUCH) ?([^;/]{1,100}?)(?:/[^;]{1,200}|); + rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} Firefox/ + device_replacement: Alcatel $1 $2 $3 + brand_replacement: Alcatel + model_replacement: One Touch $3 + - regex: \(Mobile; (?:ZTE([^;]{1,200})|(OpenC)); rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} + Firefox/ + device_replacement: ZTE $1$2 + brand_replacement: ZTE + model_replacement: $1$2 + - regex: \(Mobile; ALCATEL([A-Za-z0-9\-]+); rv:[^\)]{1,200}\) Gecko/[^\/]{1,200} + Firefox/[^\/]{1,200} KaiOS/ + device_replacement: Alcatel $1 + brand_replacement: Alcatel + model_replacement: $1 + - regex: \(Mobile; LYF\/([A-Za-z0-9\-]{1,100})\/.{0,100};.{0,100}rv:[^\)]{1,100}\) + Gecko/[^\/]{1,100} Firefox/[^\/]{1,100} KAIOS/ + device_replacement: LYF $1 + brand_replacement: LYF + model_replacement: $1 + - regex: \(Mobile; Nokia_([A-Za-z0-9\-]{1,100})_.{1,100}; rv:[^\)]{1,100}\) Gecko/[^\/]{1,100} + Firefox/[^\/]{1,100} KAIOS/ + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1 + - regex: Nokia(N[0-9]+)([A-Za-z_\-][A-Za-z0-9_\-]*) + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1$2 + - regex: (?:NOKIA|Nokia)(?:\-| {0,2})(?:([A-Za-z0-9]+)\-[0-9a-f]{32}|([A-Za-z0-9\-]+)(?:UCBrowser)|([A-Za-z0-9\-]+)) + device_replacement: Nokia $1$2$3 + brand_replacement: Nokia + model_replacement: $1$2$3 + - regex: Lumia ([A-Za-z0-9\-]+) + device_replacement: Lumia $1 + brand_replacement: Nokia + model_replacement: Lumia $1 + - regex: \(Symbian; U; S60 V5; [A-z]{2}\-[A-z]{2}; (SonyEricsson|Samsung|Nokia|LG)([^;/]{1,100}?)\) + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - regex: \(Symbian(?:/3|); U; ([^;]{1,200}); + device_replacement: Nokia $1 + brand_replacement: Nokia + model_replacement: $1 + - regex: BB10; ([A-Za-z0-9\- ]+)\) + device_replacement: BlackBerry $1 + brand_replacement: BlackBerry + model_replacement: $1 + - regex: Play[Bb]ook.{1,200}RIM Tablet OS + device_replacement: BlackBerry Playbook + brand_replacement: BlackBerry + model_replacement: Playbook + - regex: Black[Bb]erry ([0-9]+); + device_replacement: BlackBerry $1 + brand_replacement: BlackBerry + model_replacement: $1 + - regex: Black[Bb]erry([0-9]+) + device_replacement: BlackBerry $1 + brand_replacement: BlackBerry + model_replacement: $1 + - regex: Black[Bb]erry; + device_replacement: BlackBerry + brand_replacement: BlackBerry + - regex: (Pre|Pixi)/\d+\.\d+ + device_replacement: Palm $1 + brand_replacement: Palm + model_replacement: $1 + - regex: Palm([0-9]+) + device_replacement: Palm $1 + brand_replacement: Palm + model_replacement: $1 + - regex: Treo([A-Za-z0-9]+) + device_replacement: Palm Treo $1 + brand_replacement: Palm + model_replacement: Treo $1 + - regex: webOS.{0,200}(P160U(?:NA|))/(\d+).(\d+) + device_replacement: HP Veer + brand_replacement: HP + model_replacement: Veer + - regex: (Touch[Pp]ad)/\d+\.\d+ + device_replacement: HP TouchPad + brand_replacement: HP + model_replacement: TouchPad + - regex: HPiPAQ([A-Za-z0-9]{1,20})/\d+\.\d+ + device_replacement: HP iPAQ $1 + brand_replacement: HP + model_replacement: iPAQ $1 + - regex: PDA; (PalmOS)/sony/model ([a-z]+)/Revision + device_replacement: $1 + brand_replacement: Sony + model_replacement: $1 $2 + - regex: (Apple\s?TV) + device_replacement: AppleTV + brand_replacement: Apple + model_replacement: AppleTV + - regex: (QtCarBrowser) + device_replacement: Tesla Model S + brand_replacement: Tesla + model_replacement: Model S + - regex: (iPhone|iPad|iPod)(\d+,\d+) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1$2 + - regex: (iPad)(?:;| Simulator;) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1 + - regex: (iPod)(?:;| touch;| Simulator;) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1 + - regex: (iPhone)(?:;| Simulator;) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1 + - regex: (Watch)(\d+,\d+) + device_replacement: Apple $1 + brand_replacement: Apple + model_replacement: $1$2 + - regex: (Apple Watch)(?:;| Simulator;) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1 + - regex: (HomePod)(?:;| Simulator;) + device_replacement: $1 + brand_replacement: Apple + model_replacement: $1 + - regex: iPhone + device_replacement: iPhone + brand_replacement: Apple + model_replacement: iPhone + - regex: CFNetwork/.{0,100} Darwin/\d.{0,100}\(((?:Mac|iMac|PowerMac|PowerBook)[^\d]*)(\d+)(?:,|%2C)(\d+) + device_replacement: $1$2,$3 + brand_replacement: Apple + model_replacement: $1$2,$3 + - regex: CFNetwork/.{0,100} Darwin/\d+\.\d+\.\d+ \(x86_64\) + device_replacement: Mac + brand_replacement: Apple + model_replacement: Mac + - regex: CFNetwork/.{0,100} Darwin/\d + device_replacement: iOS-Device + brand_replacement: Apple + model_replacement: iOS-Device + - regex: Outlook-(iOS)/\d+\.\d+\.prod\.iphone + brand_replacement: Apple + device_replacement: iPhone + model_replacement: iPhone + - regex: acer_([A-Za-z0-9]+)_ + device_replacement: Acer $1 + brand_replacement: Acer + model_replacement: $1 + - regex: (?:ALCATEL|Alcatel)-([A-Za-z0-9\-]+) + device_replacement: Alcatel $1 + brand_replacement: Alcatel + model_replacement: $1 + - regex: (?:Amoi|AMOI)\-([A-Za-z0-9]+) + device_replacement: Amoi $1 + brand_replacement: Amoi + model_replacement: $1 + - regex: (?:; |\/|^)((?:Transformer (?:Pad|Prime) |Transformer |PadFone[ _]?)[A-Za-z0-9]*) + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 + - regex: (?:asus.{0,200}?ASUS|Asus|ASUS|asus)[\- ;]*((?:Transformer (?:Pad|Prime) + |Transformer |Padfone |Nexus[ _]|)[A-Za-z0-9]+) + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 + - regex: (?:ASUS)_([A-Za-z0-9\-]+) + device_replacement: Asus $1 + brand_replacement: Asus + model_replacement: $1 + - regex: \bBIRD[ \-\.]([A-Za-z0-9]+) + device_replacement: Bird $1 + brand_replacement: Bird + model_replacement: $1 + - regex: \bDell ([A-Za-z0-9]+) + device_replacement: Dell $1 + brand_replacement: Dell + model_replacement: $1 + - regex: DoCoMo/2\.0 ([A-Za-z0-9]+) + device_replacement: DoCoMo $1 + brand_replacement: DoCoMo + model_replacement: $1 + - regex: ^.{0,50}?([A-Za-z0-9]{1,30})_W;FOMA + device_replacement: DoCoMo $1 + brand_replacement: DoCoMo + model_replacement: $1 + - regex: ^.{0,50}?([A-Za-z0-9]{1,30});FOMA + device_replacement: DoCoMo $1 + brand_replacement: DoCoMo + model_replacement: $1 + - regex: \b(?:HTC/|HTC/[a-z0-9]{1,20}/|)HTC[ _\-;]? {0,2}(.{0,200}?)(?:-?Mozilla|fingerPrint|[;/\(\)]|$) + device_replacement: HTC $1 + brand_replacement: HTC + model_replacement: $1 + - regex: Huawei([A-Za-z0-9]+) + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: HUAWEI-([A-Za-z0-9]+) + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: HUAWEI ([A-Za-z0-9\-]+) + device_replacement: Huawei $1 + brand_replacement: Huawei + model_replacement: $1 + - regex: vodafone([A-Za-z0-9]+) + device_replacement: Huawei Vodafone $1 + brand_replacement: Huawei + model_replacement: Vodafone $1 + - regex: i\-mate ([A-Za-z0-9]+) + device_replacement: i-mate $1 + brand_replacement: i-mate + model_replacement: $1 + - regex: Kyocera\-([A-Za-z0-9]+) + device_replacement: Kyocera $1 + brand_replacement: Kyocera + model_replacement: $1 + - regex: KWC\-([A-Za-z0-9]+) + device_replacement: Kyocera $1 + brand_replacement: Kyocera + model_replacement: $1 + - regex: Lenovo[_\-]([A-Za-z0-9]+) + device_replacement: Lenovo $1 + brand_replacement: Lenovo + model_replacement: $1 + - regex: (HbbTV)/[0-9]+\.[0-9]+\.[0-9]+ \( ?;(LG)E ?;([^;]{0,30}) + device_replacement: $1 + brand_replacement: $2 + model_replacement: $3 + - regex: (HbbTV)/1\.1\.1.{0,200}CE-HTML/1\.\d;(Vendor/|)(THOM[^;]{0,200}?)[;\s].{0,30}(LF[^;]{1,200});? + device_replacement: $1 + brand_replacement: Thomson + model_replacement: $4 + - regex: '(HbbTV)(?:/1\.1\.1|) ?(?: \(;;;;;\)|); {0,2}CE-HTML(?:/1\.\d|); {0,2}([^ + ]{1,30}) ([^;]{1,200});' + device_replacement: $1 + brand_replacement: $2 + model_replacement: $3 + - regex: (HbbTV)/1\.1\.1 \(;;;;;\) Maple_2011 + device_replacement: $1 + brand_replacement: Samsung + - regex: (HbbTV)/[0-9]+\.[0-9]+\.[0-9]+ \([^;]{0,30}; ?(?:CUS:([^;]{0,200})|([^;]{1,200})) + ?; ?([^;]{0,30}) + device_replacement: $1 + brand_replacement: $2$3 + model_replacement: $4 + - regex: (HbbTV)/[0-9]+\.[0-9]+\.[0-9]+ + device_replacement: $1 + - regex: LGE; (?:Media\/|)([^;]{0,200});[^;]{0,200};[^;]{0,200};?\); "?LG NetCast(\.TV|\.Media|)-\d+ + device_replacement: NetCast$2 + brand_replacement: LG + model_replacement: $1 + - regex: InettvBrowser/[0-9]{1,30}\.[0-9A-Z]{1,30} \([^;]{0,200};(Sony)([^;]{0,200});[^;]{0,200};[^\)]{0,10}\) + device_replacement: Inettv + brand_replacement: $1 + model_replacement: $2 + - regex: InettvBrowser/[0-9]{1,30}\.[0-9A-Z]{1,30} \([^;]{0,200};([^;]{0,200});[^;]{0,200};[^\)]{0,10}\) + device_replacement: Inettv + brand_replacement: Generic_Inettv + model_replacement: $1 + - regex: (?:InettvBrowser|TSBNetTV|NETTV|HBBTV) + device_replacement: Inettv + brand_replacement: Generic_Inettv + - regex: Series60/\d\.\d (LG)[\-]?([A-Za-z0-9 \-]+) + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - 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 + - regex: (?:^LG[\-]?|^LGE[\-/]?)([A-Za-z]+[0-9]+[A-Za-z]*) + device_replacement: LG $1 + brand_replacement: LG + model_replacement: $1 + - regex: ^LG([0-9]+[A-Za-z]*) + device_replacement: LG $1 + brand_replacement: LG + model_replacement: $1 + - regex: (KIN\.[^ ]+) (\d+)\.(\d+) + device_replacement: Microsoft $1 + brand_replacement: Microsoft + model_replacement: $1 + - regex: (?:MSIE|XBMC).{0,200}\b(Xbox)\b + device_replacement: $1 + brand_replacement: Microsoft + model_replacement: $1 + - regex: ; ARM; Trident/6\.0; Touch[\);] + device_replacement: Microsoft Surface RT + brand_replacement: Microsoft + model_replacement: Surface RT + - regex: Motorola\-([A-Za-z0-9]+) + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: $1 + - regex: MOTO\-([A-Za-z0-9]+) + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: $1 + - regex: MOT\-([A-z0-9][A-z0-9\-]*) + device_replacement: Motorola $1 + brand_replacement: Motorola + model_replacement: $1 - regex: '; (moto[ a-zA-z0-9()]{0,50});((?: Build|.{0,50}\) AppleWebKit))' - device_replacement: '$1' - brand_replacement: 'Motorola' - model_replacement: '$1' + device_replacement: $1 + brand_replacement: Motorola + model_replacement: $1 - regex: '; {0,2}(moto)(.{0,50})(?: Build|\) AppleWebKit)' - device_replacement: 'Motorola$2' - brand_replacement: 'Motorola' - model_replacement: '$2' - - - ########## - # nintendo - ########## - - regex: 'Nintendo WiiU' - device_replacement: 'Nintendo Wii U' - brand_replacement: 'Nintendo' - model_replacement: 'Wii U' - - regex: 'Nintendo (DS|3DS|DSi|Wii);' - device_replacement: 'Nintendo $1' - brand_replacement: 'Nintendo' - model_replacement: '$1' - - ########## - # pantech - ########## - - regex: '(?:Pantech|PANTECH)[ _-]?([A-Za-z0-9\-]+)' - device_replacement: 'Pantech $1' - brand_replacement: 'Pantech' - model_replacement: '$1' - - ########## - # philips - ########## - - regex: 'Philips([A-Za-z0-9]+)' - device_replacement: 'Philips $1' - brand_replacement: 'Philips' - model_replacement: '$1' - - regex: 'Philips ([A-Za-z0-9]+)' - device_replacement: 'Philips $1' - brand_replacement: 'Philips' - model_replacement: '$1' - - ########## - # Samsung - ########## - # Samsung Smart-TV + device_replacement: Motorola$2 + brand_replacement: Motorola + model_replacement: $2 + - regex: Nintendo WiiU + device_replacement: Nintendo Wii U + brand_replacement: Nintendo + model_replacement: Wii U + - regex: Nintendo (Switch|DS|3DS|DSi|Wii); + device_replacement: Nintendo $1 + brand_replacement: Nintendo + model_replacement: $1 + - regex: (?:Pantech|PANTECH)[ _-]?([A-Za-z0-9\-]+) + device_replacement: Pantech $1 + brand_replacement: Pantech + model_replacement: $1 + - regex: Philips([A-Za-z0-9]+) + device_replacement: Philips $1 + brand_replacement: Philips + model_replacement: $1 + - regex: Philips ([A-Za-z0-9]+) + device_replacement: Philips $1 + brand_replacement: Philips + model_replacement: $1 - regex: '(SMART-TV); .{0,200} Tizen ' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - # Samsung Symbian Devices - - regex: 'SymbianOS/9\.\d.{0,200} Samsung[/\-]([A-Za-z0-9 \-]+)' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - regex: '(Samsung)(SGH)(i[0-9]+)' - device_replacement: '$1 $2$3' - brand_replacement: '$1' - model_replacement: '$2-$3' - - regex: 'SAMSUNG-ANDROID-MMS/([^;/]{1,100})' - device_replacement: '$1' - brand_replacement: 'Samsung' - model_replacement: '$1' - # Other Samsung - #- regex: 'SAMSUNG(?:; |-)([A-Za-z0-9\-]+)' - - regex: 'SAMSUNG(?:; |[ -/])([A-Za-z0-9\-]+)' - regex_flag: 'i' - device_replacement: 'Samsung $1' - brand_replacement: 'Samsung' - model_replacement: '$1' - - ########## - # Sega - ########## - - regex: '(Dreamcast)' - device_replacement: 'Sega $1' - brand_replacement: 'Sega' - model_replacement: '$1' - - ########## - # Siemens mobile - ########## - - regex: '^SIE-([A-Za-z0-9]+)' - device_replacement: 'Siemens $1' - brand_replacement: 'Siemens' - model_replacement: '$1' - - ########## - # Softbank - ########## - - regex: 'Softbank/[12]\.0/([A-Za-z0-9]+)' - device_replacement: 'Softbank $1' - brand_replacement: 'Softbank' - model_replacement: '$1' - - ########## - # SonyEricsson - ########## - - regex: 'SonyEricsson ?([A-Za-z0-9\-]+)' - device_replacement: 'Ericsson $1' - brand_replacement: 'SonyEricsson' - model_replacement: '$1' - - ########## - # Sony - ########## - - regex: 'Android [^;]{1,200}; ([^ ]+) (Sony)/' - device_replacement: '$2 $1' - brand_replacement: '$2' - model_replacement: '$1' - - regex: '(Sony)(?:BDP\/|\/|)([^ /;\)]+)[ /;\)]' - device_replacement: '$1 $2' - brand_replacement: '$1' - model_replacement: '$2' - - ######### - # Puffin Browser Device detect - # A=Android, I=iOS, P=Phone, T=Tablet - # AT=Android+Tablet - ######### - - regex: 'Puffin/[\d\.]+IT' - device_replacement: 'iPad' - brand_replacement: 'Apple' - model_replacement: 'iPad' - - regex: 'Puffin/[\d\.]+IP' - device_replacement: 'iPhone' - brand_replacement: 'Apple' - model_replacement: 'iPhone' - - regex: 'Puffin/[\d\.]+AT' - device_replacement: 'Generic Tablet' - brand_replacement: 'Generic' - model_replacement: 'Tablet' - - regex: 'Puffin/[\d\.]+AP' - device_replacement: 'Generic Smartphone' - brand_replacement: 'Generic' - model_replacement: 'Smartphone' - - ######### - # Android General Device Matching (far from perfect) - ######### - - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; WOWMobile (.{1,200})( Build[/ ]|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{0,2} {0,2}; {0,2}(.{1,200}?)( Build[/ ]|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[A-Za-z]{2}[_\-][A-Za-z]{0,2}\-? {0,2}; {0,2}(.{1,200}?)( Build[/ ]|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[A-Za-z]{0,2}\- {0,2}; {0,2}(.{1,200}?)( Build[/ ]|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - # No build info at all - "Build" follows locale immediately - - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[a-z]{0,2}[_\-]?[A-Za-z]{0,2};?( Build[/ ]|\))' - device_replacement: 'Generic Smartphone' - brand_replacement: 'Generic' - model_replacement: 'Smartphone' - - regex: 'Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,3}\-?[A-Za-z]{2}; {0,2}(.{1,50}?)( Build[/ ]|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - regex: 'Android \d+?(?:\.\d+|)(?:\.\d+|); ([^;]{1,100}?)(?: Build|\) AppleWebKit).{1,200}? Mobile Safari' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - regex: 'Android \d+?(?:\.\d+|)(?:\.\d+|); ([^;]{1,100}?)(?: Build|\) AppleWebKit).{1,200}? Safari' - brand_replacement: 'Generic_Android_Tablet' - model_replacement: '$1' + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: SymbianOS/9\.\d.{0,200} Samsung[/\-]([A-Za-z0-9 \-]+) + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: (Samsung)(SGH)(i[0-9]+) + device_replacement: $1 $2$3 + brand_replacement: $1 + model_replacement: $2-$3 + - regex: SAMSUNG-ANDROID-MMS/([^;/]{1,100}) + device_replacement: $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: SAMSUNG(?:; |[ -/])([A-Za-z0-9\-]+) + regex_flag: i + device_replacement: Samsung $1 + brand_replacement: Samsung + model_replacement: $1 + - regex: (Dreamcast) + device_replacement: Sega $1 + brand_replacement: Sega + model_replacement: $1 + - regex: ^SIE-([A-Za-z0-9]+) + device_replacement: Siemens $1 + brand_replacement: Siemens + model_replacement: $1 + - regex: Softbank/[12]\.0/([A-Za-z0-9]+) + device_replacement: Softbank $1 + brand_replacement: Softbank + model_replacement: $1 + - regex: SonyEricsson ?([A-Za-z0-9\-]+) + device_replacement: Ericsson $1 + brand_replacement: SonyEricsson + model_replacement: $1 + - regex: Android [^;]{1,200}; ([^ ]+) (Sony)/ + device_replacement: $2 $1 + brand_replacement: $2 + model_replacement: $1 + - regex: (Sony)(?:BDP\/|\/|)([^ /;\)]+)[ /;\)] + device_replacement: $1 $2 + brand_replacement: $1 + model_replacement: $2 + - regex: Puffin/[\d\.]+IT + device_replacement: iPad + brand_replacement: Apple + model_replacement: iPad + - regex: Puffin/[\d\.]+IP + device_replacement: iPhone + brand_replacement: Apple + model_replacement: iPhone + - regex: Puffin/[\d\.]+AT + device_replacement: Generic Tablet + brand_replacement: Generic + model_replacement: Tablet + - regex: Puffin/[\d\.]+AP + device_replacement: Generic Smartphone + brand_replacement: Generic + model_replacement: Smartphone + - regex: Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{0,2}; WOWMobile (.{1,200})( + Build[/ ]|\)) + brand_replacement: Generic_Android + model_replacement: $1 + - regex: Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{0,2} {0,2}; {0,2}(.{1,200}?)( + Build[/ ]|\)) + brand_replacement: Generic_Android + model_replacement: $1 + - regex: Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[A-Za-z]{2}[_\-][A-Za-z]{0,2}\-? + {0,2}; {0,2}(.{1,200}?)( Build[/ ]|\)) + brand_replacement: Generic_Android + model_replacement: $1 + - regex: Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[A-Za-z]{0,2}\- {0,2}; {0,2}(.{1,200}?)( + Build[/ ]|\)) + brand_replacement: Generic_Android + model_replacement: $1 + - regex: Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,2}[a-z]{0,2}[_\-]?[A-Za-z]{0,2};?( + Build[/ ]|\)) + device_replacement: Generic Smartphone + brand_replacement: Generic + model_replacement: Smartphone + - regex: Android[\- ][\d]+(?:\.[\d]+)(?:\.[\d]+|); {0,3}\-?[A-Za-z]{2}; {0,2}(.{1,50}?)( + Build[/ ]|\)) + brand_replacement: Generic_Android + model_replacement: $1 + - regex: 'Android \d+?(?:\.\d+|)(?:\.\d+|); ([^;]{1,100}?)(?: Build|\) AppleWebKit).{1,200}? + Mobile Safari' + brand_replacement: Generic_Android + model_replacement: $1 + - regex: 'Android \d+?(?:\.\d+|)(?:\.\d+|); ([^;]{1,100}?)(?: Build|\) AppleWebKit).{1,200}? + Safari' + brand_replacement: Generic_Android_Tablet + model_replacement: $1 - regex: 'Android \d+?(?:\.\d+|)(?:\.\d+|); ([^;]{1,100}?)(?: Build|\))' - brand_replacement: 'Generic_Android' - model_replacement: '$1' - - ########## - # Google TV - ########## - - regex: '(GoogleTV)' - brand_replacement: 'Generic_Inettv' - model_replacement: '$1' - - ########## - # WebTV - ########## - - regex: '(WebTV)/\d+.\d+' - brand_replacement: 'Generic_Inettv' - model_replacement: '$1' - # Roku Digital-Video-Players https://www.roku.com/ - - regex: '^(Roku)/DVP-\d+\.\d+' - brand_replacement: 'Generic_Inettv' - model_replacement: '$1' - - ########## - # Generic Tablet - ########## - - regex: '(Android 3\.\d|Opera Tablet|Tablet; .{1,100}Firefox/|Android.{0,100}(?:Tab|Pad))' - regex_flag: 'i' - device_replacement: 'Generic Tablet' - brand_replacement: 'Generic' - model_replacement: 'Tablet' - - ########## - # Generic Smart Phone - ########## - - regex: '(Symbian|\bS60(Version|V\d)|\bS60\b|\((Series 60|Windows Mobile|Palm OS|Bada); Opera Mini|Windows CE|Opera Mobi|BREW|Brew|Mobile; .{1,200}Firefox/|iPhone OS|Android|MobileSafari|Windows {0,2}Phone|\(webOS/|PalmOS)' - device_replacement: 'Generic Smartphone' - brand_replacement: 'Generic' - model_replacement: 'Smartphone' - - regex: '(hiptop|avantgo|plucker|xiino|blazer|elaine)' - regex_flag: 'i' - device_replacement: 'Generic Smartphone' - brand_replacement: 'Generic' - model_replacement: 'Smartphone' - - ########## - # Spiders (this is a hack...) - ########## - - regex: '^.{0,100}(bot|BUbiNG|zao|borg|DBot|oegp|silk|Xenu|zeal|^NING|CCBot|crawl|htdig|lycos|slurp|teoma|voila|yahoo|Sogou|CiBra|Nutch|^Java/|^JNLP/|Daumoa|Daum|Genieo|ichiro|larbin|pompos|Scrapy|snappy|speedy|spider|msnbot|msrbot|vortex|^vortex|crawler|favicon|indexer|Riddler|scooter|scraper|scrubby|WhatWeb|WinHTTP|bingbot|BingPreview|openbot|gigabot|furlbot|polybot|seekbot|^voyager|archiver|Icarus6j|mogimogi|Netvibes|blitzbot|altavista|charlotte|findlinks|Retreiver|TLSProber|WordPress|SeznamBot|ProoXiBot|wsr\-agent|Squrl Java|EtaoSpider|PaperLiBot|SputnikBot|A6\-Indexer|netresearch|searchsight|baiduspider|YisouSpider|ICC\-Crawler|http%20client|Python-urllib|dataparksearch|converacrawler|Screaming Frog|AppEngine-Google|YahooCacheSystem|fast\-webcrawler|Sogou Pic Spider|semanticdiscovery|Innovazion Crawler|facebookexternalhit|Google.{0,200}/\+/web/snippet|Google-HTTP-Java-Client|BlogBridge|IlTrovatore-Setaccio|InternetArchive|GomezAgent|WebThumbnail|heritrix|NewsGator|PagePeeker|Reaper|ZooShot|holmes|NL-Crawler|Pingdom|StatusCake|WhatsApp|masscan|Google Web Preview|Qwantify|Yeti|OgScrper)' - regex_flag: 'i' - device_replacement: 'Spider' - brand_replacement: 'Spider' - model_replacement: 'Desktop' - - ########## - # Generic Feature Phone - # take care to do case insensitive matching - ########## - - regex: '^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\-|airn|alav|asus|attw|au\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bmobile|bell|bird|bw\-n|bw\-u|beck|benq|bilb|blac|c55/|cdm\-|chtm|capi|comp|cond|dall|dbte|dc\-s|dica|ds\-d|ds12|dait|devi|dmob|doco|dopo|dorado|el(?:38|39|48|49|50|55|58|68)|el[3456]\d{2}dual|erk0|esl8|ex300|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\-|fly_|g\-mo|g1 u|g560|gf\-5|grun|gene|go.w|good|grad|hcit|hd\-m|hd\-p|hd\-t|hei\-|hp i|hpip|hs\-c|htc |htc\-|htca|htcg)' - regex_flag: 'i' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - regex: '^(htcp|htcs|htct|htc_|haie|hita|huaw|hutc|i\-20|i\-go|i\-ma|i\-mobile|i230|iac|iac\-|iac/|ig01|im1k|inno|iris|jata|kddi|kgt|kgt/|kpt |kwc\-|klon|lexi|lg g|lg\-a|lg\-b|lg\-c|lg\-d|lg\-f|lg\-g|lg\-k|lg\-l|lg\-m|lg\-o|lg\-p|lg\-s|lg\-t|lg\-u|lg\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\-|lge/|leno|m1\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\-|nem\-|newg|neon)' - regex_flag: 'i' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - regex: '^(netf|noki|nzph|o2 x|o2\-x|opwv|owg1|opti|oran|ot\-s|p800|pand|pg\-1|pg\-2|pg\-3|pg\-6|pg\-8|pg\-c|pg13|phil|pn\-2|pt\-g|palm|pana|pire|pock|pose|psio|qa\-a|qc\-2|qc\-3|qc\-5|qc\-7|qc07|qc12|qc21|qc32|qc60|qci\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\-|scp\-|sdk/|se47|sec\-|sec0|sec1|semc|sgh\-|shar|sie\-|sk\-0|sl45|slid|smb3|smt5|sp01|sph\-|spv |spv\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\-mo|t218|t250|t600|t610|t618|tcl\-|tdg\-|telm|tim\-|ts70|tsm\-|tsm3|tsm5|tx\-9|tagt)' - regex_flag: 'i' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - regex: '^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vertu|vite|voda|vulc|w3c |w3c\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\-|your|zte\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\-|webc|whit|wmlb|xda\-|xda_)' - regex_flag: 'i' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - regex: '^(Ice)$' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - regex: '(wap[\-\ ]browser|maui|netfront|obigo|teleca|up\.browser|midp|Opera Mini)' - regex_flag: 'i' - device_replacement: 'Generic Feature Phone' - brand_replacement: 'Generic' - model_replacement: 'Feature Phone' - - ######### - # Apple - # @ref: https://www.apple.com/mac/ - # @note: lookup Mac OS, but exclude iPad, Apple TV, a HTC phone, Kindle, LG - # @note: put this at the end, since it is hard to implement contains foo, but not contain bar1, bar 2, bar 3 in go's re2 - ######### - - regex: 'Mac OS' - device_replacement: 'Mac' - brand_replacement: 'Apple' - model_replacement: 'Mac' + brand_replacement: Generic_Android + model_replacement: $1 + - regex: (GoogleTV) + brand_replacement: Generic_Inettv + model_replacement: $1 + - regex: (WebTV)/\d+.\d+ + brand_replacement: Generic_Inettv + model_replacement: $1 + - regex: ^(Roku)/DVP-\d+\.\d+ + brand_replacement: Generic_Inettv + model_replacement: $1 + - regex: (Android 3\.\d|Opera Tablet|Tablet; .{1,100}Firefox/|Android.{0,100}(?:Tab|Pad)) + regex_flag: i + device_replacement: Generic Tablet + brand_replacement: Generic + model_replacement: Tablet + - regex: (Symbian|\bS60(Version|V\d)|\bS60\b|\((Series 60|Windows Mobile|Palm OS|Bada); + Opera Mini|Windows CE|Opera Mobi|BREW|Brew|Mobile; .{1,200}Firefox/|iPhone OS|Android|MobileSafari|Windows + {0,2}Phone|\(webOS/|PalmOS) + device_replacement: Generic Smartphone + brand_replacement: Generic + model_replacement: Smartphone + - regex: (hiptop|avantgo|plucker|xiino|blazer|elaine) + regex_flag: i + device_replacement: Generic Smartphone + brand_replacement: Generic + model_replacement: Smartphone + - regex: ^.{0,100}(bot|BUbiNG|zao|borg|DBot|oegp|silk|Xenu|zeal|^NING|CCBot|crawl|htdig|lycos|slurp|teoma|voila|yahoo|Sogou|CiBra|Nutch|^Java/|^JNLP/|Daumoa|Daum|Genieo|ichiro|larbin|pompos|Scrapy|snappy|speedy|spider|msnbot|msrbot|vortex|^vortex|crawler|favicon|indexer|Riddler|scooter|scraper|scrubby|WhatWeb|WinHTTP|bingbot|BingPreview|openbot|gigabot|furlbot|polybot|seekbot|^voyager|archiver|Icarus6j|mogimogi|Netvibes|blitzbot|altavista|charlotte|findlinks|Retreiver|TLSProber|WordPress|SeznamBot|ProoXiBot|wsr\-agent|Squrl + Java|EtaoSpider|PaperLiBot|SputnikBot|A6\-Indexer|netresearch|searchsight|baiduspider|YisouSpider|ICC\-Crawler|http%20client|Python-urllib|dataparksearch|converacrawler|Screaming + Frog|AppEngine-Google|YahooCacheSystem|fast\-webcrawler|Sogou Pic Spider|semanticdiscovery|Innovazion + Crawler|facebookexternalhit|Google.{0,200}/\+/web/snippet|Google-HTTP-Java-Client|BlogBridge|IlTrovatore-Setaccio|InternetArchive|GomezAgent|WebThumbnail|heritrix|NewsGator|PagePeeker|Reaper|ZooShot|holmes|NL-Crawler|Pingdom|StatusCake|WhatsApp|masscan|Google + Web Preview|Qwantify|Yeti|OgScrper) + regex_flag: i + device_replacement: Spider + brand_replacement: Spider + model_replacement: Desktop + - regex: ^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\-|airn|alav|asus|attw|au\-m|aur + |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bmobile|bell|bird|bw\-n|bw\-u|beck|benq|bilb|blac|c55/|cdm\-|chtm|capi|comp|cond|dall|dbte|dc\-s|dica|ds\-d|ds12|dait|devi|dmob|doco|dopo|dorado|el(?:38|39|48|49|50|55|58|68)|el[3456]\d{2}dual|erk0|esl8|ex300|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\-|fly_|g\-mo|g1 + u|g560|gf\-5|grun|gene|go.w|good|grad|hcit|hd\-m|hd\-p|hd\-t|hei\-|hp i|hpip|hs\-c|htc + |htc\-|htca|htcg) + regex_flag: i + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: ^(htcp|htcs|htct|htc_|haie|hita|huaw|hutc|i\-20|i\-go|i\-ma|i\-mobile|i230|iac|iac\-|iac/|ig01|im1k|inno|iris|jata|kddi|kgt|kgt/|kpt + |kwc\-|klon|lexi|lg g|lg\-a|lg\-b|lg\-c|lg\-d|lg\-f|lg\-g|lg\-k|lg\-l|lg\-m|lg\-o|lg\-p|lg\-s|lg\-t|lg\-u|lg\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\-|lge/|leno|m1\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot + |mot\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\-|nem\-|newg|neon) + regex_flag: i + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: ^(netf|noki|nzph|o2 x|o2\-x|opwv|owg1|opti|oran|ot\-s|p800|pand|pg\-1|pg\-2|pg\-3|pg\-6|pg\-8|pg\-c|pg13|phil|pn\-2|pt\-g|palm|pana|pire|pock|pose|psio|qa\-a|qc\-2|qc\-3|qc\-5|qc\-7|qc07|qc12|qc21|qc32|qc60|qci\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\-|scp\-|sdk/|se47|sec\-|sec0|sec1|semc|sgh\-|shar|sie\-|sk\-0|sl45|slid|smb3|smt5|sp01|sph\-|spv + |spv\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\-mo|t218|t250|t600|t610|t618|tcl\-|tdg\-|telm|tim\-|ts70|tsm\-|tsm3|tsm5|tx\-9|tagt) + regex_flag: i + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: ^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vertu|vite|voda|vulc|w3c + |w3c\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\-|your|zte\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\-|webc|whit|wmlb|xda\-|xda_) + regex_flag: i + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: ^(Ice)$ + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: (wap[\-\ ]browser|maui|netfront|obigo|teleca|up\.browser|midp|Opera Mini) + regex_flag: i + device_replacement: Generic Feature Phone + brand_replacement: Generic + model_replacement: Feature Phone + - regex: Mac OS + device_replacement: Mac + brand_replacement: Apple + model_replacement: Mac