Remove v2
|
@ -1 +0,0 @@
|
||||||
../../LICENSE
|
|
|
@ -1 +0,0 @@
|
||||||
../firefox/ReadMe.txt
|
|
|
@ -1 +0,0 @@
|
||||||
../firefox/_locales
|
|
|
@ -1 +0,0 @@
|
||||||
../firefox/common.js
|
|
|
@ -1 +0,0 @@
|
||||||
../firefox/data
|
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"manifest_version": 2,
|
|
||||||
"name": "__MSG_extensionName__",
|
|
||||||
"version": "0.4.8",
|
|
||||||
"default_locale": "en",
|
|
||||||
"description": "__MSG_extensionDescription__",
|
|
||||||
"permissions": [
|
|
||||||
"storage",
|
|
||||||
"<all_urls>",
|
|
||||||
"webNavigation",
|
|
||||||
"webRequest",
|
|
||||||
"webRequestBlocking",
|
|
||||||
"contextMenus"
|
|
||||||
],
|
|
||||||
"icons": {
|
|
||||||
"16": "data/icons/active/16.png",
|
|
||||||
"18": "data/icons/active/18.png",
|
|
||||||
"19": "data/icons/active/19.png",
|
|
||||||
"32": "data/icons/active/32.png",
|
|
||||||
"36": "data/icons/active/36.png",
|
|
||||||
"38": "data/icons/active/38.png",
|
|
||||||
"48": "data/icons/active/48.png",
|
|
||||||
"64": "data/icons/active/64.png",
|
|
||||||
"128": "data/icons/active/128.png",
|
|
||||||
"256": "data/icons/active/256.png"
|
|
||||||
},
|
|
||||||
"storage": {
|
|
||||||
"managed_schema": "schema.json"
|
|
||||||
},
|
|
||||||
"background":{
|
|
||||||
"scripts":[
|
|
||||||
"ua-parser.min.js",
|
|
||||||
"common.js"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browser_action":{
|
|
||||||
"default_icon": {
|
|
||||||
"16": "data/icons/16.png",
|
|
||||||
"32": "data/icons/32.png",
|
|
||||||
"48": "data/icons/48.png",
|
|
||||||
"64": "data/icons/64.png"
|
|
||||||
},
|
|
||||||
"default_popup": "data/popup/index.html"
|
|
||||||
},
|
|
||||||
"homepage_url": "https://add0n.com/useragent-switcher.html",
|
|
||||||
"options_ui": {
|
|
||||||
"page": "data/options/index.html",
|
|
||||||
"chrome_style": true,
|
|
||||||
"open_in_tab": true
|
|
||||||
},
|
|
||||||
"content_scripts": [{
|
|
||||||
"all_frames": true,
|
|
||||||
"run_at": "document_start",
|
|
||||||
"match_about_blank": true,
|
|
||||||
"matches": ["*://*/*"],
|
|
||||||
"js": ["data/inject.js"]
|
|
||||||
}]
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
../firefox/schema.json
|
|
1
v2/chrome/ua-parser.min.js
vendored
|
@ -1 +0,0 @@
|
||||||
../firefox/ua-parser.min.js
|
|
|
@ -1 +0,0 @@
|
||||||
../../LICENSE
|
|
|
@ -1,2 +0,0 @@
|
||||||
ua-parser.min.js:
|
|
||||||
https://github.com/faisalman/ua-parser-js/releases/tag/1.0.32
|
|
|
@ -1,211 +0,0 @@
|
||||||
{
|
|
||||||
"extensionName": {
|
|
||||||
"message": "User-Agent Switcher and Manager",
|
|
||||||
"description": "Name of the extension."
|
|
||||||
},
|
|
||||||
"extensionDescription": {
|
|
||||||
"message": "Spoof websites trying to gather information about your web navigation to deliver distinct content you may not want",
|
|
||||||
"description": "Description of the extension."
|
|
||||||
},
|
|
||||||
"userAgentSwitcherandManagerOptions": {
|
|
||||||
"message": "User-Agent Switcher and Manager :: Options"
|
|
||||||
},
|
|
||||||
"blackListMode": {
|
|
||||||
"message": "Black-List Mode"
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"message": "Description"
|
|
||||||
},
|
|
||||||
"blackListModeDescription": {
|
|
||||||
"message": "Apply the custom user-agent string to all tabs except the tabs with the following top-level hostnames (comma-separated list of hostnames). Note that even if a window-based user-agent string is set from the toolbar popup, your browser's default user-agent string is used."
|
|
||||||
},
|
|
||||||
"whiteListMode": {
|
|
||||||
"message": "White-List Mode"
|
|
||||||
},
|
|
||||||
"whiteListModeDescription": {
|
|
||||||
"message": "Only apply the custom user-agent string to the tabs with following top-level hostnames. Note that if a window-based user-agent string is set from the toolbar popup, this user-agent will overwrite the global one."
|
|
||||||
},
|
|
||||||
"customMode": {
|
|
||||||
"message": "Custom Mode"
|
|
||||||
},
|
|
||||||
"customModeDescription": {
|
|
||||||
"message": "Try to resolve the user-agent string from a JSON object; otherwise either use the default user-agent string or use the one that the user is set from the popup interface. Use \"*\" as the hostname to match all domains. You can randomly select from multiple user-agent strings by providing an array instead of a fixed string. If there is a \"_\" key in your JSON object which refers to an array of hostnames, then the extension only randomly selects the user-agent string once for each hostname inside this list. This is useful if you don't want the random user-agent to change until this browser session is over."
|
|
||||||
},
|
|
||||||
"insertSample": {
|
|
||||||
"message": "Insert a sample"
|
|
||||||
},
|
|
||||||
"cache": {
|
|
||||||
"message": "Use caching to improve performance (recommended value is true). Uncheck this option only if you are using the custom mode and also you need the user-agent string to be altered from the provided list on every single request."
|
|
||||||
},
|
|
||||||
"exactMatch": {
|
|
||||||
"message": "Use exact matching (if checked, you will need to insert all sub-domains in the white-list and black-list modes to be considered. If unchecked, all the sub-domains are passing the matching condition (e.g: www.google.com passes the matching if google.com is in the list))"
|
|
||||||
},
|
|
||||||
"faqs": {
|
|
||||||
"message": "Open FAQs page on updates"
|
|
||||||
},
|
|
||||||
"userAgentData": {
|
|
||||||
"message": "Expose \"navigator.userAgentData\" object on Chromium browsers"
|
|
||||||
},
|
|
||||||
"log": {
|
|
||||||
"message": "Display debugging info in the browser console"
|
|
||||||
},
|
|
||||||
"disableSpoofing": {
|
|
||||||
"message": "Disable Spoofing"
|
|
||||||
},
|
|
||||||
"disableSpoofingDescription": {
|
|
||||||
"message": "A comma-separated list of keywords that the extension should not spoof the user-agent header. Use this list to protect URLs that contain these protected keywords. Each keyword need to be at least 5 char long."
|
|
||||||
},
|
|
||||||
"customUserAgentParsing": {
|
|
||||||
"message": "Custom User-Agent Parsing"
|
|
||||||
},
|
|
||||||
"customUserAgentParsingDescription": {
|
|
||||||
"message": "A JSON object to bypass the internal user-agent string parsing method. The keys are the actual user-agent strings and the value of each key is an object of the keys that need to be set for the \"navigator\" object. You can use the \"[delete]\" keyword if you want a key in the \"navigator\" object to get deleted."
|
|
||||||
},
|
|
||||||
"siblingHostnames": {
|
|
||||||
"message": "Sibling Hostnames"
|
|
||||||
},
|
|
||||||
"siblingHostnamesDescription": {
|
|
||||||
"message": "A JSON array that contains one or more groups of hostnames to have a single user-agent string per group. For all hostnames in one group, the user-agent string calculation only occurs once, and all the other members use the same calculated string. This is useful to make sure a group of connected websites only access to the same user-agent string."
|
|
||||||
},
|
|
||||||
"importSettings": {
|
|
||||||
"message": "Import Settings"
|
|
||||||
},
|
|
||||||
"exportSettings": {
|
|
||||||
"message": "Export Settings"
|
|
||||||
},
|
|
||||||
"exportSettingsTitle": {
|
|
||||||
"message": "To generate minified version, press Shift key while pressing this button"
|
|
||||||
},
|
|
||||||
"help": {
|
|
||||||
"message": "FAQs Page (Help)"
|
|
||||||
},
|
|
||||||
"donate": {
|
|
||||||
"message": "Support Development"
|
|
||||||
},
|
|
||||||
"save": {
|
|
||||||
"message": "Save"
|
|
||||||
},
|
|
||||||
"managedStorage": {
|
|
||||||
"message": "This extension supports managed storage so that preferences can be altered automatically or can be pre-configured by a domain administrator. Read the FAQs page for more info."
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"message": "Options"
|
|
||||||
},
|
|
||||||
"optionsTitle": {
|
|
||||||
"message": "Open options page"
|
|
||||||
},
|
|
||||||
"restart": {
|
|
||||||
"message": "Restart"
|
|
||||||
},
|
|
||||||
"restartTitle": {
|
|
||||||
"message": "Click to reload the extension. This will cause all the window-based user-agent strings to be cleared."
|
|
||||||
},
|
|
||||||
"refreshTab": {
|
|
||||||
"message": "Refresh Tab"
|
|
||||||
},
|
|
||||||
"refreshTabTitle": {
|
|
||||||
"message": "Refresh the current page"
|
|
||||||
},
|
|
||||||
"reset": {
|
|
||||||
"message": "Reset"
|
|
||||||
},
|
|
||||||
"resetTitle": {
|
|
||||||
"message": "Reset browser's user-agent string to the default one. This will not reset window-based UA strings. To reset them, use the 'Restart' button."
|
|
||||||
},
|
|
||||||
"testUA": {
|
|
||||||
"message": "Test UA"
|
|
||||||
},
|
|
||||||
"testUATitle": {
|
|
||||||
"message": "Test your user-agent string"
|
|
||||||
},
|
|
||||||
"considerContainers": {
|
|
||||||
"message": "Consider Containers"
|
|
||||||
},
|
|
||||||
"considerContainersTitle": {
|
|
||||||
"message": "Allow the extension to access your browser's containers. If this permission is granted, tabs inside isolated containers do not follow the default container's user-agent string. You need to set this string for each new container."
|
|
||||||
},
|
|
||||||
"applyActiveWindow": {
|
|
||||||
"message": "Apply (active window)"
|
|
||||||
},
|
|
||||||
"applyActiveWindowTitle": {
|
|
||||||
"message": "Set this user-agent string for all tabs inside the current window"
|
|
||||||
},
|
|
||||||
"applyAllWindows": {
|
|
||||||
"message": "Apply (all windows)"
|
|
||||||
},
|
|
||||||
"applyAllWindowsTitle": {
|
|
||||||
"message": "Set this user-agent string as the browser's User-Agent string"
|
|
||||||
},
|
|
||||||
"applyContainer": {
|
|
||||||
"message": "Apply (container)"
|
|
||||||
},
|
|
||||||
"applyContainerTitle": {
|
|
||||||
"message": "Set this user-agent string as the current container's User-Agent string"
|
|
||||||
},
|
|
||||||
"applyContainerWindow": {
|
|
||||||
"message": "Apply (container on window)"
|
|
||||||
},
|
|
||||||
"applyContainerWindowTitle": {
|
|
||||||
"message": "Set this user-agent string for all tabs inside the current window's container"
|
|
||||||
},
|
|
||||||
"resetContainer": {
|
|
||||||
"message": "Reset (container)"
|
|
||||||
},
|
|
||||||
"resetContainerTitle": {
|
|
||||||
"message": "Reset the container's user-agent string to the default one. This will not reset window-based UA strings. To reset them, use the 'Restart' button."
|
|
||||||
},
|
|
||||||
"oscpuTitle": {
|
|
||||||
"message": "This is a readonly field. Use options page for custom parsing."
|
|
||||||
},
|
|
||||||
"appVersionTitle": {
|
|
||||||
"message": "This is a readonly field. Use options page for custom parsing."
|
|
||||||
},
|
|
||||||
"platformTitle": {
|
|
||||||
"message": "This is a readonly field. Use options page for custom parsing."
|
|
||||||
},
|
|
||||||
"vendorTitle": {
|
|
||||||
"message": "This is a readonly field. Use options page for custom parsing."
|
|
||||||
},
|
|
||||||
"productTitle": {
|
|
||||||
"message": "This is a readonly field. Use options page for custom parsing."
|
|
||||||
},
|
|
||||||
"uaTitle": {
|
|
||||||
"message": "To set a blank user-agent string, use the 'empty' keyword. To construct a custom user-agent string based on the current browser's navigator object, use ${} notation. Whatever is inside this notation is read from the 'navigator' object. For instance, to append a string to the default user-agent, use '${userAgent} THIS IS THE APPENDED STRING'"
|
|
||||||
},
|
|
||||||
"uaPlaceholder": {
|
|
||||||
"message": "Your preferred user-agent string"
|
|
||||||
},
|
|
||||||
"noMatch": {
|
|
||||||
"message": "No matching user-agent string for this query"
|
|
||||||
},
|
|
||||||
"ztoa": {
|
|
||||||
"message": "Z to A"
|
|
||||||
},
|
|
||||||
"atoz": {
|
|
||||||
"message": "A to Z"
|
|
||||||
},
|
|
||||||
"filterAmong": {
|
|
||||||
"message": "Filter among $1"
|
|
||||||
},
|
|
||||||
"filterAgents": {
|
|
||||||
"message": "Filter Agents"
|
|
||||||
},
|
|
||||||
"msgDefaultUA": {
|
|
||||||
"message": "Default UA, press the reset button instead"
|
|
||||||
},
|
|
||||||
"msgUASet": {
|
|
||||||
"message": "User-Agent is Set"
|
|
||||||
},
|
|
||||||
"msgDisabledOnContainer": {
|
|
||||||
"message": "Disabled on this container. Uses the default user-agent string."
|
|
||||||
},
|
|
||||||
"msgDisabled": {
|
|
||||||
"message": "Disabled. Uses the default user-agent string."
|
|
||||||
},
|
|
||||||
"optionsSaved": {
|
|
||||||
"message": "Options saved."
|
|
||||||
},
|
|
||||||
"dbReset": {
|
|
||||||
"message": "Double-click to reset!"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,208 +0,0 @@
|
||||||
{
|
|
||||||
"extensionName": {
|
|
||||||
"message": "User-Agent Switcher and Manager",
|
|
||||||
"description": "Name of the extension."
|
|
||||||
},
|
|
||||||
"extensionDescription": {
|
|
||||||
"message": "Подменяет User-Agent на веб-сайтах, пытающихся собрать информацию о ваших путешествиях по сети и выдать не нужное вам содержимое",
|
|
||||||
"description": "Description of the extension."
|
|
||||||
},
|
|
||||||
"userAgentSwitcherandManagerOptions": {
|
|
||||||
"message": "User-Agent Switcher and Manager :: Настройки"
|
|
||||||
},
|
|
||||||
"blackListMode": {
|
|
||||||
"message": "Режим черного списка"
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"message": "Описание"
|
|
||||||
},
|
|
||||||
"blackListModeDescription": {
|
|
||||||
"message": "Применить установленную строку User-Agent ко всем вкладкам за исключением содержащих следующие домены верхнего уровня (список доменов разделяется запятыми). Важно: даже если применяемая к окну строка User-Agent установлена из всплывающего окна, для этого списка будет использоваться строка User-Agent вашего браузера по умолчанию."
|
|
||||||
},
|
|
||||||
"whiteListMode": {
|
|
||||||
"message": "Режим белого списка"
|
|
||||||
},
|
|
||||||
"whiteListModeDescription": {
|
|
||||||
"message": "Применять установленную строку User-Agent только к вкладкам, содержащим следующие домены верхнего уровня. Важно: даже если применяемая к окну строка User-Agent установлена из всплывающего окна, данный User-Agent заменит собой глобальный."
|
|
||||||
},
|
|
||||||
"customMode": {
|
|
||||||
"message": "Режим настройки"
|
|
||||||
},
|
|
||||||
"customModeDescription": {
|
|
||||||
"message": "Пробовать считывание строки User-Agent из объекта JSON; в другом случае использовать строку User-Agent по умолчанию или установленную во всплывающем окне. Используйте \"*\" в качестве сервера для применения ко всем доменам. Вы можете случайно выбирать из нескольких строк User-Agent с помощью массива вместо фиксированной строки. Если в объекте JSON присутствует ключ \"_\", отсылающий к массиву серверов, то расширение будет случайно выбирать строку User-Agent для каждого сервера в списке. Это полезно, если вы не желаете случайно менять User-Agent до перезапуска браузера."
|
|
||||||
},
|
|
||||||
"insertSample": {
|
|
||||||
"message": "Вставить пример"
|
|
||||||
},
|
|
||||||
"cache": {
|
|
||||||
"message": "Использовать кэширование для улучшения производительности (рекомендуемое значение true). Отключите эту опцию только при использовании режима настройки, когда нужно изменять строку User-Agent с помощью списка при каждом запросе."
|
|
||||||
},
|
|
||||||
"exactMatch": {
|
|
||||||
"message": "Использовать точное совпадение (если включено, вам нужно добавлять все поддомены в черный и белый списки как задумано. Если выключено, все поддомены проходят проверку на совпадение (например, www.google.com проходит проверку, если google.com находится в списке))"
|
|
||||||
},
|
|
||||||
"faqs": {
|
|
||||||
"message": "Открывать страницу FAQ при обновлении"
|
|
||||||
},
|
|
||||||
"log": {
|
|
||||||
"message": "Отображать отладочную информацию в консоли браузера"
|
|
||||||
},
|
|
||||||
"disableSpoofing": {
|
|
||||||
"message": "Отключить подмену User-Agent"
|
|
||||||
},
|
|
||||||
"disableSpoofingDescription": {
|
|
||||||
"message": "Разделяемый запятыми список ключевых слов, на которых расширение не должно подменять заголовок User-Agent. Используйте этот список для защиты URL, содержащих эти ключевые слова. Каждое ключевое слово должно быть длиной не менее 5 символов."
|
|
||||||
},
|
|
||||||
"customUserAgentParsing": {
|
|
||||||
"message": "Парсинг установленного User-Agent"
|
|
||||||
},
|
|
||||||
"customUserAgentParsingDescription": {
|
|
||||||
"message": "Объект JSON для обхода внутреннего метода парсинга строки User-Agent. Ключи — настоящие строки User-Agent. Значение каждого ключа- объект ключей, требуемых для установки объекта \"navigator\". Вы можете использовать ключевое слово \"[delete]\", если вам нужен ключ в объекте \"navigator\" для удаления."
|
|
||||||
},
|
|
||||||
"siblingHostnames": {
|
|
||||||
"message": "Родственные домены"
|
|
||||||
},
|
|
||||||
"siblingHostnamesDescription": {
|
|
||||||
"message": "Массив JSON, содержащий одну или больше групп серверов с отдельной строкой User-Agent на группу. Для всех серверов в одной группе вычисление строки User-Agent проводится только один раз, все остальные члены группы используют ту же самую строку. С помощью этого можно убедиться, что група связанных веб-сайтов имеет доступ только к одной и той же строке User-Agent."
|
|
||||||
},
|
|
||||||
"importSettings": {
|
|
||||||
"message": "Импортировать настройки"
|
|
||||||
},
|
|
||||||
"exportSettings": {
|
|
||||||
"message": "Экспортировать настройки"
|
|
||||||
},
|
|
||||||
"exportSettingsTitle": {
|
|
||||||
"message": "Чтобы сгенерировать уменьшенную версию, нажмите эту кнопку, удерживая клавишу Shift"
|
|
||||||
},
|
|
||||||
"help": {
|
|
||||||
"message": "Страница FAQ (Помощь)"
|
|
||||||
},
|
|
||||||
"donate": {
|
|
||||||
"message": "Поддержать разработку"
|
|
||||||
},
|
|
||||||
"save": {
|
|
||||||
"message": "Сохранить"
|
|
||||||
},
|
|
||||||
"managedStorage": {
|
|
||||||
"message": "Данное расширение поддерживает Managed Storage, и эти настройки могут быть изменены автоматически или установлены изначально администратором домена. Прочтите FAQ для получения более подробной информации."
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"message": "Настройки"
|
|
||||||
},
|
|
||||||
"optionsTitle": {
|
|
||||||
"message": "Открыть страницу настроек"
|
|
||||||
},
|
|
||||||
"restart": {
|
|
||||||
"message": "Перезапустить"
|
|
||||||
},
|
|
||||||
"restartTitle": {
|
|
||||||
"message": "Нажмите, чтобы перезапустить расширение. Это очистит все строки User-Agent, примененные к окну."
|
|
||||||
},
|
|
||||||
"refreshTab": {
|
|
||||||
"message": "Обновить вкладку"
|
|
||||||
},
|
|
||||||
"refreshTabTitle": {
|
|
||||||
"message": "Обновить текущую страницу"
|
|
||||||
},
|
|
||||||
"reset": {
|
|
||||||
"message": "Сбросить"
|
|
||||||
},
|
|
||||||
"resetTitle": {
|
|
||||||
"message": "Сбросить строку User-Agent браузера на значение по умолчанию. Это не сбросит строки User-Agent, примененные к окну. Чтобы сбросить их, нажмите кнопку 'Перезапустить'."
|
|
||||||
},
|
|
||||||
"testUA": {
|
|
||||||
"message": "Тест UA"
|
|
||||||
},
|
|
||||||
"testUATitle": {
|
|
||||||
"message": "Тестировать вашу строку User-Agent"
|
|
||||||
},
|
|
||||||
"considerContainers": {
|
|
||||||
"message": "Учитывать контейнеры"
|
|
||||||
},
|
|
||||||
"considerContainersTitle": {
|
|
||||||
"message": "Позволять расширению иметь доступ к контейнерам вашего браузера. При наличии доступа вкладки внутри изолированных контейнеров не используют строку User-Agent контейнера по умолчанию. Вам нужно устанавливать эту строку для каждого нового контейнера."
|
|
||||||
},
|
|
||||||
"applyActiveWindow": {
|
|
||||||
"message": "Применить (активное окно)"
|
|
||||||
},
|
|
||||||
"applyActiveWindowTitle": {
|
|
||||||
"message": "Установить эту строку User-Agent для всех вкладок внутри текущего окна"
|
|
||||||
},
|
|
||||||
"applyAllWindows": {
|
|
||||||
"message": "Применить (все окна)"
|
|
||||||
},
|
|
||||||
"applyAllWindowsTitle": {
|
|
||||||
"message": "Установить эту строку User-Agent в качестве основной строки браузера"
|
|
||||||
},
|
|
||||||
"applyContainer": {
|
|
||||||
"message": "Применить (контейнер)"
|
|
||||||
},
|
|
||||||
"applyContainerTitle": {
|
|
||||||
"message": "Установить эту строку User-Agent в качестве строки текущего контейнера"
|
|
||||||
},
|
|
||||||
"applyContainerWindow": {
|
|
||||||
"message": "Применить (контейнер в окне)"
|
|
||||||
},
|
|
||||||
"applyContainerWindowTitle": {
|
|
||||||
"message": "Установить эту строку User-Agent для всех вкладок внутри текущего окна контейнера"
|
|
||||||
},
|
|
||||||
"resetContainer": {
|
|
||||||
"message": "Сбросить (контейнер)"
|
|
||||||
},
|
|
||||||
"resetContainerTitle": {
|
|
||||||
"message": "Сбросить строку User-Agent контейнера на значение по умолчанию. Это не сбросит строки User-Agent, примененные к окну. Чтобы сбросить их, нажмите кнопку 'Перезапустить'."
|
|
||||||
},
|
|
||||||
"oscpuTitle": {
|
|
||||||
"message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную."
|
|
||||||
},
|
|
||||||
"appVersionTitle": {
|
|
||||||
"message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную."
|
|
||||||
},
|
|
||||||
"platformTitle": {
|
|
||||||
"message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную."
|
|
||||||
},
|
|
||||||
"vendorTitle": {
|
|
||||||
"message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную."
|
|
||||||
},
|
|
||||||
"productTitle": {
|
|
||||||
"message": "Это поле только для чтения. Используйте страницу настроек для парсинга вручную."
|
|
||||||
},
|
|
||||||
"uaTitle": {
|
|
||||||
"message": "Чтобы установить пустую строку User-Agent, используйте ключевое слово 'empty'. Чтобы составить собственную строку User-Agent, основанную на текущем объекте navigator браузера, используйте нотацию ${}. Все внутри этой нотации будет прочитано из объекта 'navigator'. Например, чтобы присоединить строку к User-Agent по умолчанию, используйте '${userAgent} ПРИСОЕДИНЕННАЯ СТРОКА'"
|
|
||||||
},
|
|
||||||
"uaPlaceholder": {
|
|
||||||
"message": "Ваша предпочитаемая строка User-Agent"
|
|
||||||
},
|
|
||||||
"noMatch": {
|
|
||||||
"message": "Для данного запроса нет строк User-Agent"
|
|
||||||
},
|
|
||||||
"ztoa": {
|
|
||||||
"message": "От Z до A"
|
|
||||||
},
|
|
||||||
"atoz": {
|
|
||||||
"message": "От A до Z"
|
|
||||||
},
|
|
||||||
"filterAmong": {
|
|
||||||
"message": "Выбрать из $1"
|
|
||||||
},
|
|
||||||
"filterAgents": {
|
|
||||||
"message": "Выбрать UA"
|
|
||||||
},
|
|
||||||
"msgDefaultUA": {
|
|
||||||
"message": "User-Agent по умолчанию, вместо этого нажмите кнопку 'Сбросить'"
|
|
||||||
},
|
|
||||||
"msgUASet": {
|
|
||||||
"message": "User-Agent установлен"
|
|
||||||
},
|
|
||||||
"msgDisabledOnContainer": {
|
|
||||||
"message": "Отключено в этом контейнере. Используется строка User-Agent по умолчанию."
|
|
||||||
},
|
|
||||||
"msgDisabled": {
|
|
||||||
"message": "Отключено. Используется строка User-Agent по умолчанию."
|
|
||||||
},
|
|
||||||
"optionsSaved": {
|
|
||||||
"message": "Настройки сохранены."
|
|
||||||
},
|
|
||||||
"dbReset": {
|
|
||||||
"message": "Щелкните 2 раза левой кнопкой мыши для сброса!"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,777 +0,0 @@
|
||||||
/* global UAParser */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const DCSI = 'firefox-default';
|
|
||||||
|
|
||||||
const cache = {}; // cache how a tab's request get handled (true, false, object)
|
|
||||||
const tabs = {};
|
|
||||||
const cookieStoreIds = {};
|
|
||||||
chrome.tabs.onRemoved.addListener(id => {
|
|
||||||
delete cache[id];
|
|
||||||
delete tabs[id];
|
|
||||||
delete cookieStoreIds[id];
|
|
||||||
});
|
|
||||||
chrome.tabs.onCreated.addListener(tab => {
|
|
||||||
tabs[tab.id] = tab.windowId;
|
|
||||||
cookieStoreIds[tab.id] = tab.cookieStoreId;
|
|
||||||
});
|
|
||||||
|
|
||||||
const prefs = {
|
|
||||||
'ua': '',
|
|
||||||
'blacklist': [],
|
|
||||||
'whitelist': [],
|
|
||||||
'custom': {},
|
|
||||||
'siblings': {}, // a list of domains that are considered siblings (use same index for all)
|
|
||||||
'mode': 'blacklist',
|
|
||||||
'color': '#777',
|
|
||||||
'cache': true,
|
|
||||||
'exactMatch': false,
|
|
||||||
'userAgentData': true,
|
|
||||||
'protected': [
|
|
||||||
'google.com/recaptcha',
|
|
||||||
'gstatic.com/recaptcha',
|
|
||||||
'accounts.google.com',
|
|
||||||
'accounts.youtube.com',
|
|
||||||
'gitlab.com/users/sign_in'
|
|
||||||
],
|
|
||||||
'parser': {}, // maps ua string to a ua object,
|
|
||||||
'log': false,
|
|
||||||
'json-guid': 'na'
|
|
||||||
};
|
|
||||||
window.prefs = prefs; // access from popup
|
|
||||||
|
|
||||||
const log = (...args) => prefs.log && console.log(...args);
|
|
||||||
|
|
||||||
// expand comma-separated keys of prefs.custom and add missing keys
|
|
||||||
const expand = () => {
|
|
||||||
log('expanding custom rules');
|
|
||||||
expand.rules = {};
|
|
||||||
for (const key of Object.keys(prefs.custom)) {
|
|
||||||
for (const k of key.split(/\s*,\s*/)) {
|
|
||||||
if (k) {
|
|
||||||
expand.rules[k] = prefs.custom[key];
|
|
||||||
// make sure all siblings have the same expanded rule
|
|
||||||
const i = prefs.siblings[key];
|
|
||||||
if (i !== undefined) {
|
|
||||||
for (const [hostname, j] of Object.entries(prefs.siblings)) {
|
|
||||||
if (i === j) {
|
|
||||||
expand.rules[hostname] = expand.rules[hostname] || prefs.custom[key];
|
|
||||||
if (expand.rules._) {
|
|
||||||
const x = expand.rules._.indexOf(key);
|
|
||||||
const y = expand.rules._.indexOf(hostname);
|
|
||||||
if (x !== -1 && y === -1) {
|
|
||||||
expand.rules._.push(hostname);
|
|
||||||
}
|
|
||||||
if (x === -1 && y !== -1) {
|
|
||||||
expand.rules._.push(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
expand.rules = {};
|
|
||||||
|
|
||||||
const currentCookieStoreId = () => new Promise(resolve => chrome.tabs.query({
|
|
||||||
active: true,
|
|
||||||
currentWindow: true
|
|
||||||
}, tbs => {
|
|
||||||
resolve((tbs.length ? tbs[0].cookieStoreId : '') || DCSI);
|
|
||||||
}));
|
|
||||||
|
|
||||||
chrome.storage.local.get(prefs, ps => {
|
|
||||||
Object.assign(prefs, ps);
|
|
||||||
expand();
|
|
||||||
|
|
||||||
chrome.tabs.query({}, ts => {
|
|
||||||
ts.forEach(t => {
|
|
||||||
tabs[t.id] = t.windowId;
|
|
||||||
cookieStoreIds[t.id] = t.cookieStoreId;
|
|
||||||
});
|
|
||||||
|
|
||||||
// update prefs.ua from the managed storage
|
|
||||||
try {
|
|
||||||
chrome.storage.managed.get({
|
|
||||||
'ua': '',
|
|
||||||
'json': ''
|
|
||||||
}, rps => {
|
|
||||||
if (!chrome.runtime.lastError) {
|
|
||||||
const p = {};
|
|
||||||
if (rps.json) {
|
|
||||||
try {
|
|
||||||
const j = JSON.parse(rps.json);
|
|
||||||
if (prefs['json-guid'] !== j['json-guid'] || j['json-forced']) {
|
|
||||||
Object.assign(p, j);
|
|
||||||
console.warn('preferences are updated by an admin');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.warn('cannot parse remote JSON', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rps.ua) {
|
|
||||||
p.ua = rps.ua;
|
|
||||||
console.warn('user-agent string is updated by an admin');
|
|
||||||
}
|
|
||||||
chrome.storage.local.set(p, () => {
|
|
||||||
ua.update(undefined, undefined, DCSI);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ua.update(undefined, undefined, DCSI);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
ua.update(undefined, undefined, DCSI);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (chrome.browserAction.setBadgeBackgroundColor) { // FF for Android
|
|
||||||
chrome.browserAction.setBadgeBackgroundColor({
|
|
||||||
color: prefs.color
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// context menu
|
|
||||||
chrome.contextMenus.create({
|
|
||||||
id: 'blacklist',
|
|
||||||
title: 'Switch to "black-list" mode',
|
|
||||||
contexts: ['browser_action'],
|
|
||||||
type: 'radio',
|
|
||||||
checked: prefs.mode === 'blacklist'
|
|
||||||
}, () => chrome.runtime.lastError);
|
|
||||||
chrome.contextMenus.create({
|
|
||||||
id: 'whitelist',
|
|
||||||
title: 'Switch to "white-list" mode',
|
|
||||||
contexts: ['browser_action'],
|
|
||||||
type: 'radio',
|
|
||||||
checked: prefs.mode === 'whitelist'
|
|
||||||
}, () => chrome.runtime.lastError);
|
|
||||||
chrome.contextMenus.create({
|
|
||||||
id: 'custom',
|
|
||||||
title: 'Switch to "custom" mode',
|
|
||||||
contexts: ['browser_action'],
|
|
||||||
type: 'radio',
|
|
||||||
checked: prefs.mode === 'custom'
|
|
||||||
}, () => chrome.runtime.lastError);
|
|
||||||
});
|
|
||||||
chrome.storage.onChanged.addListener(ps => {
|
|
||||||
Object.keys(ps).forEach(key => prefs[key] = ps[key].newValue);
|
|
||||||
|
|
||||||
if (ps.ua || ps.mode || ps.userAgentData) {
|
|
||||||
currentCookieStoreId().then(cookieStoreId => {
|
|
||||||
if (ps.ua) {
|
|
||||||
if (ps.ua.newValue === '') {
|
|
||||||
delete ua._obj[cookieStoreId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ua.update(undefined, undefined, cookieStoreId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (ps.custom) {
|
|
||||||
expand();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ua = {
|
|
||||||
_obj: {},
|
|
||||||
diff(tabId, cookieStoreId = DCSI) { // returns true if there is per window object
|
|
||||||
log('ua.diff is called', tabId, cookieStoreId);
|
|
||||||
const windowId = tabs[tabId];
|
|
||||||
return windowId in (this._obj[cookieStoreId] || this._obj[DCSI] || {});
|
|
||||||
},
|
|
||||||
get windows() {
|
|
||||||
log('ua.windows is called');
|
|
||||||
const ids = [];
|
|
||||||
for (const cookieStoreId of Object.keys(this._obj)) {
|
|
||||||
ids.push(...Object.keys(this._obj[cookieStoreId]).filter(id => id !== 'global').map(s => Number(s)));
|
|
||||||
}
|
|
||||||
return ids.filter((n, i, l) => n && l.indexOf(n) === i);
|
|
||||||
},
|
|
||||||
parse: s => {
|
|
||||||
log('ua.parse is called', s);
|
|
||||||
if (prefs.parser[s]) {
|
|
||||||
log('ua.parse is resolved using parser');
|
|
||||||
return Object.assign({
|
|
||||||
userAgent: s
|
|
||||||
}, prefs.parser[s]);
|
|
||||||
}
|
|
||||||
// build ua string from the navigator object or from a custom UAParser;
|
|
||||||
// examples: ${platform}, ${browser.version|ua-parser}
|
|
||||||
s = s.replace(/\${([^}]+)}/g, (a, b) => {
|
|
||||||
const key = (parent, keys) => {
|
|
||||||
for (const key of keys) {
|
|
||||||
parent = parent[key] || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
let [childs, object] = b.split('|');
|
|
||||||
object = object || 'navigator';
|
|
||||||
|
|
||||||
let v;
|
|
||||||
if (object.startsWith('ua-parser')) {
|
|
||||||
const [a, b] = object.split('@');
|
|
||||||
object = a;
|
|
||||||
|
|
||||||
v = key((new UAParser(b || navigator.userAgent)).getResult(), childs.split('.'));
|
|
||||||
}
|
|
||||||
v = v || key(navigator, childs.split('.'));
|
|
||||||
return typeof v === 'string' ? v : 'cannot parse your ${...} replacements.';
|
|
||||||
});
|
|
||||||
const o = {};
|
|
||||||
o.userAgent = s;
|
|
||||||
o.appVersion = s
|
|
||||||
.replace(/^Mozilla\//, '')
|
|
||||||
.replace(/^Opera\//, '');
|
|
||||||
|
|
||||||
const isFF = /Firefox/.test(s);
|
|
||||||
const isCH = /Chrome/.test(s);
|
|
||||||
const isSF = /Safari/.test(s) && isCH === false;
|
|
||||||
|
|
||||||
|
|
||||||
if (isFF) {
|
|
||||||
o.appVersion = '5.0 ' + o.appVersion.replace('5.0 ', '').split(/[\s;]/)[0] + ')';
|
|
||||||
}
|
|
||||||
const p = (new UAParser(s)).getResult();
|
|
||||||
o.platform = p.os.name || '';
|
|
||||||
if (o.platform === 'Mac OS') {
|
|
||||||
o.platform = 'MacIntel';
|
|
||||||
}
|
|
||||||
o.vendor = p.device.vendor || '';
|
|
||||||
if (isSF) {
|
|
||||||
o.vendor = 'Apple Computer, Inc.';
|
|
||||||
}
|
|
||||||
else if (isFF === false) {
|
|
||||||
o.vendor = 'Google Inc.';
|
|
||||||
}
|
|
||||||
o.product = p.engine.name || '';
|
|
||||||
if (s.indexOf('Gecko') !== -1) {
|
|
||||||
o.product = 'Gecko';
|
|
||||||
}
|
|
||||||
o.userAgentData = '[delete]';
|
|
||||||
if (isFF) {
|
|
||||||
o.oscpu = ((p.os.name || '') + ' ' + (p.os.version || '')).trim();
|
|
||||||
o.productSub = '20100101';
|
|
||||||
o.buildID = '20181001000000';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
o.oscpu = '[delete]';
|
|
||||||
o.buildID = '[delete]';
|
|
||||||
o.productSub = '20030107';
|
|
||||||
|
|
||||||
if (prefs.userAgentData && p.browser && p.browser.major) {
|
|
||||||
if (['Opera', 'Chrome', 'Edge'].includes(p.browser.name)) {
|
|
||||||
o.userAgentDataBuilder = {p, ua: s};
|
|
||||||
delete o.userAgentData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.userAgent === 'empty') {
|
|
||||||
Object.keys(o).forEach(key => {
|
|
||||||
if (key !== 'userAgent') {
|
|
||||||
o[key] = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
},
|
|
||||||
object(tabId, windowId, cookieStoreId = DCSI) {
|
|
||||||
windowId = windowId || (tabId ? tabs[tabId] : 'global');
|
|
||||||
log('ua.object is called', tabId, windowId, cookieStoreId);
|
|
||||||
|
|
||||||
if (this._obj[cookieStoreId]) {
|
|
||||||
return this._obj[cookieStoreId][windowId] || this._obj[cookieStoreId].global;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
string(str, windowId, cookieStoreId) {
|
|
||||||
log('ua.string is called', str, windowId);
|
|
||||||
this._obj[cookieStoreId] = this._obj[cookieStoreId] || {};
|
|
||||||
if (str) {
|
|
||||||
this._obj[cookieStoreId][windowId] = this.parse(str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._obj[cookieStoreId][windowId] = {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip(title, tabId) {
|
|
||||||
log('ua.tooltip is called', title, tabId);
|
|
||||||
chrome.browserAction.setTitle({
|
|
||||||
title,
|
|
||||||
tabId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon(mode, tabId) {
|
|
||||||
log('ua.icon is called', mode, tabId);
|
|
||||||
chrome.browserAction.setIcon({
|
|
||||||
tabId,
|
|
||||||
path: {
|
|
||||||
'16': 'data/icons/' + (mode ? mode + '/' : '') + '16.png',
|
|
||||||
'18': 'data/icons/' + (mode ? mode + '/' : '') + '18.png',
|
|
||||||
'19': 'data/icons/' + (mode ? mode + '/' : '') + '19.png',
|
|
||||||
'32': 'data/icons/' + (mode ? mode + '/' : '') + '32.png',
|
|
||||||
'36': 'data/icons/' + (mode ? mode + '/' : '') + '36.png',
|
|
||||||
'38': 'data/icons/' + (mode ? mode + '/' : '') + '38.png',
|
|
||||||
'48': 'data/icons/' + (mode ? mode + '/' : '') + '48.png'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
toolbar: ({windowId, tabId, cookieStoreId}) => {
|
|
||||||
log('ua.toolbar is called', windowId, tabId);
|
|
||||||
if (windowId) {
|
|
||||||
chrome.tabs.query({
|
|
||||||
windowId
|
|
||||||
}, tabs => tabs.forEach(tab => {
|
|
||||||
const tabId = tab.id;
|
|
||||||
const o = ua.object(null, windowId, tab.cookieStoreId);
|
|
||||||
chrome.browserAction.setBadgeText({
|
|
||||||
tabId,
|
|
||||||
text: o && o.platform ? o.platform.slice(0, 3) : ''
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
else if (tabId) {
|
|
||||||
const o = ua.object(tabId, undefined, cookieStoreId);
|
|
||||||
chrome.browserAction.setBadgeText({
|
|
||||||
tabId,
|
|
||||||
text: o.platform ? o.platform.slice(0, 3) : 'BOT'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update(str = prefs.ua, windowId = 'global', cookieStoreId = DCSI) {
|
|
||||||
log('ua.update is called', str, windowId, cookieStoreId);
|
|
||||||
// clear caching
|
|
||||||
Object.keys(cache).forEach(key => delete cache[key]);
|
|
||||||
// remove old listeners
|
|
||||||
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
|
|
||||||
chrome.webNavigation.onCommitted.removeListener(onCommitted);
|
|
||||||
// apply new ones
|
|
||||||
if (str || prefs.mode === 'custom' || this.windows.length || Object.keys(this._obj).length) {
|
|
||||||
if (str) {
|
|
||||||
ua.string(str, windowId, cookieStoreId);
|
|
||||||
}
|
|
||||||
chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {
|
|
||||||
'urls': ['*://*/*', 'ws://*/*', 'wss://*/*']
|
|
||||||
}, ['blocking', 'requestHeaders']);
|
|
||||||
chrome.webNavigation.onCommitted.addListener(onCommitted);
|
|
||||||
ua.tooltip('[Default] ' + navigator.userAgent);
|
|
||||||
ua.icon('ignored');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ua.icon('');
|
|
||||||
ua.tooltip('[Disabled] to enable, use the popup window');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowId === 'global') {
|
|
||||||
this.toolbar({str});
|
|
||||||
}
|
|
||||||
// update per window
|
|
||||||
else {
|
|
||||||
this.windows.forEach(windowId => this.toolbar({windowId}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.ua = ua; // using from popup
|
|
||||||
// make sure to clean on window removal
|
|
||||||
if (chrome.windows) { // FF on Android
|
|
||||||
chrome.windows.onRemoved.addListener(windowId => {
|
|
||||||
let update = false;
|
|
||||||
Object.keys(ua._obj).forEach(cookieStoreId => {
|
|
||||||
if (windowId in ua._obj[cookieStoreId]) {
|
|
||||||
delete ua._obj[cookieStoreId][windowId];
|
|
||||||
// delete the entire object if it is empty
|
|
||||||
if (Object.keys(ua._obj[cookieStoreId]).length === 0) {
|
|
||||||
delete ua._obj[cookieStoreId];
|
|
||||||
}
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// if nothing is left to monitor, disable the extension
|
|
||||||
if (update) {
|
|
||||||
currentCookieStoreId().then(cookieStoreId => ua.update(undefined, undefined, cookieStoreId));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hostname(url) {
|
|
||||||
log('hostname', url);
|
|
||||||
const s = url.indexOf('//') + 2;
|
|
||||||
if (s > 1) {
|
|
||||||
let o = url.indexOf('/', s);
|
|
||||||
if (o > 0) {
|
|
||||||
return url.substring(s, o);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
o = url.indexOf('?', s);
|
|
||||||
if (o > 0) {
|
|
||||||
return url.substring(s, o);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return url.substring(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// returns true, false or an object; true: ignore, false: use from ua object.
|
|
||||||
function match({url, tabId, cookieStoreId = DCSI}) {
|
|
||||||
log('match', url, tabId, cookieStoreId);
|
|
||||||
const h = hostname(url);
|
|
||||||
|
|
||||||
if (prefs.protected.some(s => url.indexOf(s) !== -1)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefs.mode === 'blacklist') {
|
|
||||||
if (prefs.blacklist.length) {
|
|
||||||
return prefs.blacklist.some(s => {
|
|
||||||
if (s === h) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (prefs.exactMatch === false) {
|
|
||||||
return s.endsWith('.' + h) || h.endsWith('.' + s);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (prefs.mode === 'whitelist') {
|
|
||||||
if (prefs.whitelist.length) {
|
|
||||||
return prefs.whitelist.some(s => {
|
|
||||||
if (s === h) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (prefs.exactMatch === false) {
|
|
||||||
return s.endsWith('.' + h) || h.endsWith('.' + s);
|
|
||||||
}
|
|
||||||
}) === false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const [hh] = h.split(':');
|
|
||||||
const key = Object.keys(expand.rules).filter(s => {
|
|
||||||
if (s === h || s === hh) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (prefs.exactMatch === false) {
|
|
||||||
return s.endsWith('.' + h) || h.endsWith('.' + s) || s.endsWith('.' + hh) || hh.endsWith('.' + s);
|
|
||||||
}
|
|
||||||
}).shift();
|
|
||||||
let s;
|
|
||||||
// try to use an already resolved sibling hostname
|
|
||||||
const i = prefs.siblings[key];
|
|
||||||
if (i !== undefined) {
|
|
||||||
for (const [hostname, j] of Object.entries(prefs.siblings)) {
|
|
||||||
if (j === i && expand.rules[hostname] && typeof expand.rules[hostname] === 'string') {
|
|
||||||
s = expand.rules[hostname];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s = s || expand.rules[key];
|
|
||||||
// use '*' when the hostname specific key is not found
|
|
||||||
s = s || expand.rules['*'];
|
|
||||||
// if s is an array select a random string
|
|
||||||
if (Array.isArray(s)) {
|
|
||||||
s = s[Math.floor(Math.random() * s.length)];
|
|
||||||
// set session mode if key is either on _[key] or _['*'] lists
|
|
||||||
if (expand.rules._ && Array.isArray(expand.rules._)) {
|
|
||||||
if (expand.rules._.indexOf(key) !== -1) {
|
|
||||||
expand.rules[key] = s;
|
|
||||||
}
|
|
||||||
else if (expand.rules._.indexOf('*') !== -1) {
|
|
||||||
if (expand.rules[key]) {
|
|
||||||
expand.rules[key] = s;
|
|
||||||
}
|
|
||||||
else if (expand.rules['*']) {
|
|
||||||
expand.rules['*'] = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s) {
|
|
||||||
return ua.parse(s);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const o = ua.object(tabId, undefined, cookieStoreId);
|
|
||||||
return o ? !o.userAgent : true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onBeforeSendHeaders = d => {
|
|
||||||
const {tabId, url, requestHeaders, type} = d;
|
|
||||||
const cookieStoreId = d.cookieStoreId || cookieStoreIds[tabId] || DCSI;
|
|
||||||
|
|
||||||
if (type === 'main_frame' || prefs.cache === false) {
|
|
||||||
cookieStoreIds[tabId] = cookieStoreId;
|
|
||||||
cache[tabId] = match({url, tabId, cookieStoreId});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache[tabId] === true) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
if (prefs.protected.some(s => url.indexOf(s) !== -1)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const o = (cache[tabId] || ua.object(tabId, undefined, cookieStoreId));
|
|
||||||
|
|
||||||
const str = o ? o.userAgent : '';
|
|
||||||
if (str && requestHeaders.length) {
|
|
||||||
for (
|
|
||||||
let i = 0, name = requestHeaders[0].name;
|
|
||||||
i < requestHeaders.length;
|
|
||||||
i += 1, name = (requestHeaders[i] || {}).name
|
|
||||||
) {
|
|
||||||
name = name.toLowerCase();
|
|
||||||
if (name === 'user-agent') {
|
|
||||||
requestHeaders[i].value = str === 'empty' ? '' : str;
|
|
||||||
}
|
|
||||||
// https://github.com/ray-lothian/UserAgent-Switcher/issues/160
|
|
||||||
else if (name.startsWith('sec-ch-')) {
|
|
||||||
requestHeaders[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (o.userAgentDataBuilder) {
|
|
||||||
let platform = o.userAgentDataBuilder.p?.os?.name || 'Windows';
|
|
||||||
if (platform.toLowerCase().includes('mac')) {
|
|
||||||
platform = 'macOS';
|
|
||||||
}
|
|
||||||
else if (platform.toLowerCase().includes('debian')) {
|
|
||||||
platform = 'Linux';
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = o.userAgentDataBuilder.p?.browser?.major || 107;
|
|
||||||
let name = o.userAgentDataBuilder.p?.browser?.name || 'Google Chrome';
|
|
||||||
if (name === 'Chrome') {
|
|
||||||
name = 'Google Chrome';
|
|
||||||
}
|
|
||||||
|
|
||||||
requestHeaders.push({
|
|
||||||
name: 'sec-ch-ua-platform',
|
|
||||||
value: '"' + platform + '"'
|
|
||||||
}, {
|
|
||||||
name: 'sec-ch-ua',
|
|
||||||
value: `"${name}";v="${version}", "Chromium";v="${version}", "Not=A?Brand";v="24"`
|
|
||||||
}, {
|
|
||||||
name: 'sec-ch-ua-mobile',
|
|
||||||
value: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(o.userAgent) ? '?1' : '?0'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
requestHeaders: requestHeaders.filter(o => o)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const onCommitted = d => {
|
|
||||||
const {frameId, url, tabId} = d;
|
|
||||||
const cookieStoreId = d.cookieStoreId || cookieStoreIds[tabId] || DCSI;
|
|
||||||
|
|
||||||
if (url && (url.startsWith('http') || url.startsWith('ftp')) || url === 'about:blank') {
|
|
||||||
if (cache[tabId] === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const o = cache[tabId] || ua.object(tabId, undefined, cookieStoreId);
|
|
||||||
if (o && o.userAgent) {
|
|
||||||
const s = btoa(unescape(encodeURIComponent(JSON.stringify(o))));
|
|
||||||
|
|
||||||
chrome.tabs.executeScript(tabId, {
|
|
||||||
runAt: 'document_start',
|
|
||||||
frameId,
|
|
||||||
code: `{
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.textContent = \`{
|
|
||||||
document.currentScript.dataset.injected = true;
|
|
||||||
const o = JSON.parse(decodeURIComponent(escape(atob('${s}'))));
|
|
||||||
|
|
||||||
if (o.userAgentDataBuilder) {
|
|
||||||
const v = new class NavigatorUAData {
|
|
||||||
#p;
|
|
||||||
|
|
||||||
constructor({p, ua}) {
|
|
||||||
this.#p = p;
|
|
||||||
|
|
||||||
const version = p.browser.major;
|
|
||||||
const name = p.browser.name === 'Chrome' ? 'Google Chrome' : p.browser.name;
|
|
||||||
|
|
||||||
this.brands = [{
|
|
||||||
brand: name,
|
|
||||||
version
|
|
||||||
}, {
|
|
||||||
brand: 'Chromium',
|
|
||||||
version
|
|
||||||
}, {
|
|
||||||
brand: 'Not=A?Brand',
|
|
||||||
version: '24'
|
|
||||||
}];
|
|
||||||
|
|
||||||
this.mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-UA-Platform
|
|
||||||
this.platform = 'Unknown';
|
|
||||||
if (p.os && p.os.name) {
|
|
||||||
const name = p.os.name.toLowerCase();
|
|
||||||
if (name.includes('mac')) {
|
|
||||||
this.platform = 'macOS';
|
|
||||||
}
|
|
||||||
else if (name.includes('debian')) {
|
|
||||||
this.platform = 'Linux';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.platform = p.os.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toJSON() {
|
|
||||||
return {
|
|
||||||
brands: this.brands,
|
|
||||||
mobile: this.mobile,
|
|
||||||
platform: this.platform
|
|
||||||
};
|
|
||||||
}
|
|
||||||
getHighEntropyValues(hints) {
|
|
||||||
if (!hints || Array.isArray(hints) === false) {
|
|
||||||
return Promise.reject(Error("Failed to execute 'getHighEntropyValues' on 'NavigatorUAData'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const r = this.toJSON();
|
|
||||||
|
|
||||||
if (hints.includes('architecture')) {
|
|
||||||
r.architecture = this.#p?.cpu?.architecture || 'x86';
|
|
||||||
}
|
|
||||||
if (hints.includes('bitness')) {
|
|
||||||
r.bitness = '64';
|
|
||||||
}
|
|
||||||
if (hints.includes('model')) {
|
|
||||||
r.model = '';
|
|
||||||
}
|
|
||||||
if (hints.includes('platformVersion')) {
|
|
||||||
r.platformVersion = this.#p?.os?.version || '10.0.0';
|
|
||||||
}
|
|
||||||
if (hints.includes('uaFullVersion')) {
|
|
||||||
r.uaFullVersion = this.brands[0].version;
|
|
||||||
}
|
|
||||||
if (hints.includes('fullVersionList')) {
|
|
||||||
r.fullVersionList = this.brands;
|
|
||||||
}
|
|
||||||
return Promise.resolve(r);
|
|
||||||
}
|
|
||||||
}(o.userAgentDataBuilder);
|
|
||||||
|
|
||||||
navigator.__defineGetter__('userAgentData', () => {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
delete o.userAgentDataBuilder;
|
|
||||||
|
|
||||||
for (const key of Object.keys(o)) {
|
|
||||||
if (o[key] === '[delete]') {
|
|
||||||
delete Object.getPrototypeOf(window.navigator)[key];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
navigator.__defineGetter__(key, () => {
|
|
||||||
if (o[key] === 'empty') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return o[key];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}\`;
|
|
||||||
document.documentElement.appendChild(script);
|
|
||||||
if (script.dataset.injected !== 'true') {
|
|
||||||
const s = document.createElement('script');
|
|
||||||
s.src = 'data:text/javascript;charset=utf-8;base64,' + btoa(script.textContent);
|
|
||||||
document.documentElement.appendChild(s);
|
|
||||||
s.remove();
|
|
||||||
}
|
|
||||||
script.remove();
|
|
||||||
}`
|
|
||||||
}, () => {
|
|
||||||
const lastError = chrome.runtime.lastError;
|
|
||||||
if (lastError &&
|
|
||||||
lastError.message !== 'No matching message handler' && // Firefox on Windows
|
|
||||||
lastError.message !== 'document.documentElement is null' // Firefox on Windows
|
|
||||||
) {
|
|
||||||
if (frameId === 0) {
|
|
||||||
ua.tooltip('[Default] ' + navigator.userAgent, tabId);
|
|
||||||
ua.icon('ignored', tabId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (frameId === 0) {
|
|
||||||
ua.tooltip('[Custom] ' + o.userAgent, tabId);
|
|
||||||
ua.icon('active', tabId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// change the toolbar icon if there is a per window UA setting
|
|
||||||
if (frameId === 0 && ua.diff(tabId, cookieStoreId)) {
|
|
||||||
ua.toolbar({tabId, cookieStoreId});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// context menu
|
|
||||||
chrome.contextMenus.onClicked.addListener(info => chrome.storage.local.set({
|
|
||||||
mode: info.menuItemId
|
|
||||||
}));
|
|
||||||
|
|
||||||
// restore container agents
|
|
||||||
chrome.storage.local.get({
|
|
||||||
'container-uas': {}
|
|
||||||
}, prefs => {
|
|
||||||
for (const cookieStoreId of Object.keys(prefs['container-uas'])) {
|
|
||||||
ua.string(prefs['container-uas'][cookieStoreId], 'global', cookieStoreId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* message passing */
|
|
||||||
chrome.runtime.onMessage.addListener((request, sender, response) => {
|
|
||||||
if (request.method === 'parse-ua') {
|
|
||||||
response(ua.parse(request.value));
|
|
||||||
}
|
|
||||||
else if (request.method === 'get-ua') {
|
|
||||||
response(prefs.ua || '' || navigator.userAgent);
|
|
||||||
}
|
|
||||||
else if (request.method === 'request-update') {
|
|
||||||
if (request.delete) {
|
|
||||||
delete ua._obj[request.cookieStoreId];
|
|
||||||
}
|
|
||||||
ua.update(request.value, request.windowId, request.cookieStoreId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* FAQs & Feedback */
|
|
||||||
{
|
|
||||||
const {management, runtime: {onInstalled, setUninstallURL, getManifest}, storage, tabs} = chrome;
|
|
||||||
if (navigator.webdriver !== true) {
|
|
||||||
const page = getManifest().homepage_url;
|
|
||||||
const {name, version} = getManifest();
|
|
||||||
onInstalled.addListener(({reason, previousVersion}) => {
|
|
||||||
management.getSelf(({installType}) => installType === 'normal' && storage.local.get({
|
|
||||||
'faqs': true,
|
|
||||||
'last-update': 0
|
|
||||||
}, prefs => {
|
|
||||||
if (reason === 'install' || (prefs.faqs && reason === 'update')) {
|
|
||||||
const doUpdate = (Date.now() - prefs['last-update']) / 1000 / 60 / 60 / 24 > 45;
|
|
||||||
if (doUpdate && previousVersion !== version) {
|
|
||||||
tabs.query({active: true, currentWindow: true}, tbs => tabs.create({
|
|
||||||
url: page + '?version=' + version + (previousVersion ? '&p=' + previousVersion : '') + '&type=' + reason,
|
|
||||||
active: reason === 'install',
|
|
||||||
...(tbs && tbs.length && {index: tbs[0].index + 1})
|
|
||||||
}));
|
|
||||||
storage.local.set({'last-update': Date.now()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
setUninstallURL(page + '?rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version);
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5 KiB |
|
@ -1,47 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// iframe.contentWindow
|
|
||||||
if (
|
|
||||||
window !== top &&
|
|
||||||
location.href === 'about:blank'
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
top.document; // are we on the same frame?
|
|
||||||
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.textContent = `{
|
|
||||||
const nav = top.navigator;
|
|
||||||
|
|
||||||
navigator.__defineGetter__('userAgent', () => nav.userAgent);
|
|
||||||
navigator.__defineGetter__('appVersion', () => nav.appVersion);
|
|
||||||
navigator.__defineGetter__('platform', () => nav.platform);
|
|
||||||
navigator.__defineGetter__('vendor', () => nav.vendor);
|
|
||||||
|
|
||||||
document.documentElement.dataset.fgdvcre = true;
|
|
||||||
}`;
|
|
||||||
document.documentElement.appendChild(script);
|
|
||||||
script.remove();
|
|
||||||
// make sure the script is injected
|
|
||||||
if (document.documentElement.dataset.fgdvcre !== 'true') {
|
|
||||||
document.documentElement.dataset.fgdvcre = true;
|
|
||||||
const script = document.createElement('script');
|
|
||||||
Object.assign(script, {
|
|
||||||
textContent: `
|
|
||||||
[...document.querySelectorAll('iframe[sandbox]')]
|
|
||||||
.filter(i => i.contentDocument.documentElement.dataset.fgdvcre === 'true')
|
|
||||||
.forEach(i => {
|
|
||||||
const nav = i.contentWindow.navigator;
|
|
||||||
nav.__defineGetter__('userAgent', () => navigator.userAgent);
|
|
||||||
nav.__defineGetter__('appVersion', () => navigator.appVersion);
|
|
||||||
nav.__defineGetter__('platform', () => navigator.platform);
|
|
||||||
nav.__defineGetter__('vendor', () => navigator.vendor);
|
|
||||||
});
|
|
||||||
`
|
|
||||||
});
|
|
||||||
top.document.documentElement.appendChild(script);
|
|
||||||
script.remove();
|
|
||||||
}
|
|
||||||
delete document.documentElement.dataset.fgdvcre;
|
|
||||||
}
|
|
||||||
catch (e) {}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
:root {
|
|
||||||
--color: #444;
|
|
||||||
--bg-color: #fff;
|
|
||||||
--color-admin: #444;
|
|
||||||
--color-desc: #2f2f2f;
|
|
||||||
--bg-desc: #e8e8e8;
|
|
||||||
--color-note: #2f2f2f;
|
|
||||||
--bg-note: #e8e8e8;
|
|
||||||
--bg-admin: #ffffed;
|
|
||||||
--border-admin: #e8ec3a;
|
|
||||||
--color-light: #636363;
|
|
||||||
--bg-color-light: #f5f5f5;
|
|
||||||
--bg-focus: #eff6f9;
|
|
||||||
}
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--color: #d1d2cc;
|
|
||||||
--bg-color: #272d37;
|
|
||||||
--color-light: #f5f5f5;
|
|
||||||
--bg-color-light: #343946;
|
|
||||||
--bg-focus: #454b5d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
min-width: 600px;
|
|
||||||
color: var(--color);
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
}
|
|
||||||
@media (pointer: none), (pointer: coarse) {
|
|
||||||
body {
|
|
||||||
min-width: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@supports (-moz-appearance:none) {
|
|
||||||
body {
|
|
||||||
font-size: 13px;
|
|
||||||
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
|
|
||||||
margin: 10px;
|
|
||||||
min-width: unset;
|
|
||||||
}
|
|
||||||
textarea {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
button,
|
|
||||||
input[type=submit],
|
|
||||||
input[type=button] {
|
|
||||||
height: 24px;
|
|
||||||
color: #444;
|
|
||||||
background-image: linear-gradient(rgb(237, 237, 237), rgb(237, 237, 237) 38%, rgb(222, 222, 222));
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.08) 0 1px 0, rgba(255, 255, 255, 0.75) 0 1px 2px inset;
|
|
||||||
text-shadow: rgb(240, 240, 240) 0 1px 0;
|
|
||||||
border: solid 1px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
input[type=button]:disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
button,
|
|
||||||
input[type=submit],
|
|
||||||
input[type=button] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
textarea {
|
|
||||||
color: var(--color-light);
|
|
||||||
background-color: var(--bg-color-light);
|
|
||||||
border: none;
|
|
||||||
width: 100%;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
textarea:focus {
|
|
||||||
background-color: var(--bg-focus);
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
.mode-2,
|
|
||||||
.mode {
|
|
||||||
display: grid;
|
|
||||||
white-space: nowrap;
|
|
||||||
align-items: center;
|
|
||||||
grid-gap: 5px;
|
|
||||||
}
|
|
||||||
.mode {
|
|
||||||
grid-template-columns: min-content min-content min-content;
|
|
||||||
}
|
|
||||||
.mode-2 {
|
|
||||||
grid-template-columns: min-content min-content;
|
|
||||||
}
|
|
||||||
#toggle-sibling-desc,
|
|
||||||
#toggle-parser-desc,
|
|
||||||
#toggle-protected-desc,
|
|
||||||
#toggle-custom-desc,
|
|
||||||
#toggle-whitelist-desc,
|
|
||||||
#toggle-blacklist-desc {
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--color-desc);
|
|
||||||
background-color: var(--bg-desc);
|
|
||||||
padding: 1px 4px;
|
|
||||||
}
|
|
||||||
.note {
|
|
||||||
background-color: var(--bg-note);
|
|
||||||
color: var(--color-note);
|
|
||||||
padding: 5px;
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
}
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.checked {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: min-content 1fr;
|
|
||||||
grid-gap: 5px;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tools,
|
|
||||||
#backup {
|
|
||||||
display: grid;
|
|
||||||
white-space: nowrap;
|
|
||||||
grid-gap: 5px;
|
|
||||||
}
|
|
||||||
#backup {
|
|
||||||
margin: 10px 0;
|
|
||||||
grid-template-columns: min-content min-content;
|
|
||||||
}
|
|
||||||
#tools {
|
|
||||||
grid-template-columns: repeat(4, min-content) 1fr;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 600px) {
|
|
||||||
#backup {
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
#tools {
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.admin {
|
|
||||||
color: var(--color-admin);
|
|
||||||
background-color: var(--bg-admin);
|
|
||||||
border: solid 1px var(--border-admin);
|
|
||||||
padding: 10px;
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title data-localize="userAgentSwitcherandManagerOptions">User-Agent Switcher and Manager :: Options</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="index.css">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="mode">
|
|
||||||
<input type="radio" name="mode" value="blacklist" id="mode-blacklist">
|
|
||||||
<label for="mode-blacklist"><h1 data-localize="blackListMode">Black-List Mode</h1></label>
|
|
||||||
<span id="toggle-blacklist-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-blacklist-desc" class="note hidden" data-localize="blackListModeDescription">Apply the custom user-agent string to all tabs except the tabs with the following top-level hostnames (comma-separated list of hostnames). Note that even if a window-based user-agent string is set from the toolbar popup, your browser's default user-agent string is used.</p>
|
|
||||||
<textarea id="blacklist" rows="3" placeholder="e.g.: www.google.com, www.bing.com"></textarea>
|
|
||||||
|
|
||||||
<div class="mode">
|
|
||||||
<input type="radio" name="mode" value="whitelist" id="mode-whitelist">
|
|
||||||
<label for="mode-whitelist"><h1 data-localize="whiteListMode">White-List Mode</h1></label>
|
|
||||||
<span id="toggle-whitelist-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-whitelist-desc" class="note hidden" data-localize="whiteListModeDescription">Only apply the custom user-agent string to the tabs with following top-level hostnames. Note that if a window-based user-agent string is set from the toolbar popup, this user-agent will overwrite the global one.</p>
|
|
||||||
<textarea id="whitelist" rows="3" placeholder="e.g.: www.google.com, www.bing.com"></textarea>
|
|
||||||
|
|
||||||
<div class="mode">
|
|
||||||
<input type="radio" name="mode" value="custom" id="mode-custom">
|
|
||||||
<label for="mode-custom"><h1 data-localize="customMode">Custom Mode</h1></label>
|
|
||||||
<span id="toggle-custom-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-custom-desc" class="note hidden"><span data-localize="customModeDescription">Try to resolve the user-agent string from a JSON object; otherwise either use the default user-agent string or use the one that the user is set from the popup interface. Use "*" as the hostname to match all domains. You can randomly select from multiple user-agent strings by providing an array instead of a fixed string. If there is a "_" key in your JSON object which refers to an array of hostnames, then the extension only randomly selects the user-agent string once for each hostname inside this list. This is useful if you don't want the random user-agent to change until this browser session is over.</span> <a href="#" id="sample" data-localize="insertSample">Insert a sample</a>.</p>
|
|
||||||
<textarea id="custom" rows="8" wrap="off"></textarea>
|
|
||||||
|
|
||||||
<div class="checked">
|
|
||||||
<input type="checkbox" id="cache">
|
|
||||||
<label for="cache" data-localize="cache">Use caching to improve performance (recommended value is true). Uncheck this option only if you are using the custom mode and also you need the user-agent string to be altered from the provided list on every single request.</label>
|
|
||||||
<input type="checkbox" id="exactMatch">
|
|
||||||
<label for="exactMatch" data-localize="exactMatch">Use exact matching (if checked, you will need to insert all sub-domains in the white-list and black-list modes to be considered. If unchecked, all the sub-domains are passing the matching condition (e.g: www.google.com passes the matching if google.com is in the list))</label>
|
|
||||||
<input type="checkbox" id="userAgentData">
|
|
||||||
<label for="userAgentData" data-localize="userAgentData">Expose "navigator.userAgentData" object on Chromium browsers</label>
|
|
||||||
<input type="checkbox" id="faqs">
|
|
||||||
<label for="faqs" data-localize="faqs">Open FAQs page on updates</label>
|
|
||||||
<input type="checkbox" id="log">
|
|
||||||
<label for="log" data-localize="log">Display debugging info in the browser console</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mode-2">
|
|
||||||
<h1 data-localize="disableSpoofing">Disable Spoofing</h1>
|
|
||||||
<span id="toggle-protected-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-protected-desc" class="note hidden" data-localize="disableSpoofingDescription">A comma-separated list of keywords that the extension should not spoof the user-agent header. Use this list to protect URLs that contain these protected keywords. Each keyword need to be at least 5 char long.</p>
|
|
||||||
<textarea id="protected" rows="3" wrap="off"></textarea>
|
|
||||||
|
|
||||||
<div class="mode-2">
|
|
||||||
<h1 data-localize="customUserAgentParsing">Custom User-Agent Parsing</h1>
|
|
||||||
<span id="toggle-parser-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-parser-desc" class="note hidden"><span data-localize="customUserAgentParsingDescription">A JSON object to bypass the internal user-agent string parsing method. The keys are the actual user-agent strings and the value of each key is an object of the keys that need to be set for the "navigator" object. You can use the "[delete]" keyword if you want a key in the "navigator" object to get deleted.</span> <a href="#" id="sample-2" data-localize="insertSample">Insert a sample</a>.</p>
|
|
||||||
<textarea id="parser" rows="5" wrap="off"></textarea>
|
|
||||||
|
|
||||||
<div class="mode-2">
|
|
||||||
<h1 data-localize="siblingHostnames">Sibling Hostnames</h1>
|
|
||||||
<span id="toggle-sibling-desc" data-localize="description">Description</span>
|
|
||||||
</div>
|
|
||||||
<p for="toggle-sibling-desc" class="note hidden"><span data-localize="siblingHostnamesDescription">A JSON array that contains one or more groups of hostnames to have a single user-agent string per group. For all hostnames in one group, the user-agent string calculation only occurs once, and all the other members use the same calculated string. This is useful to make sure a group of connected websites only access to the same user-agent string.</span> <a href="#" id="sample-3" data-localize="insertSample">Insert a sample</a>.</p>
|
|
||||||
<textarea id="siblings" rows="5" wrap="off"></textarea>
|
|
||||||
|
|
||||||
<div class="admin" data-localize="managedStorage">This extension supports managed storage. All the preferences can be pre-configured by the domain administrator</div>
|
|
||||||
<div id="backup">
|
|
||||||
<button id="import" data-localize="importSettings">Import Settings</button>
|
|
||||||
<button data-localized-title="exportSettingsTitle" title="To generate minified version, press Shift key while pressing this button" id="export" data-localize="exportSettings">Export Settings</button>
|
|
||||||
</div>
|
|
||||||
<div id="tools">
|
|
||||||
<button id="help" data-localize="help">FAQs Page (Help)</button>
|
|
||||||
<button id="donate" data-localize="donate">Support Development</button>
|
|
||||||
<button id="reset" data-localize="reset">Reset</button>
|
|
||||||
<button id="save" data-localize="save">Save</button>
|
|
||||||
<span id="status"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="index.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,286 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// localization
|
|
||||||
document.querySelectorAll('[data-localize]').forEach(e => {
|
|
||||||
const ref = e.dataset.localize;
|
|
||||||
const translated = chrome.i18n.getMessage(ref);
|
|
||||||
if (translated) {
|
|
||||||
e.textContent = translated;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.querySelectorAll('[data-localized-title]').forEach(e => {
|
|
||||||
const ref = e.dataset.localizedTitle;
|
|
||||||
const translated = chrome.i18n.getMessage(ref);
|
|
||||||
if (translated) {
|
|
||||||
e.title = translated;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function notify(msg, period = 750) {
|
|
||||||
// Update status to let user know options were saved.
|
|
||||||
const status = document.getElementById('status');
|
|
||||||
status.textContent = msg;
|
|
||||||
clearTimeout(notify.id);
|
|
||||||
notify.id = setTimeout(() => status.textContent = '', period);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepare(str) {
|
|
||||||
return str.split(/\s*,\s*/)
|
|
||||||
.map(s => s.replace('http://', '')
|
|
||||||
.replace('https://', '').split('/')[0].trim())
|
|
||||||
.filter((h, i, l) => h && l.indexOf(h) === i);
|
|
||||||
}
|
|
||||||
|
|
||||||
function save() {
|
|
||||||
let custom = {};
|
|
||||||
const c = document.getElementById('custom').value;
|
|
||||||
try {
|
|
||||||
custom = JSON.parse(c);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
window.setTimeout(() => {
|
|
||||||
notify('Custom JSON error: ' + e.message, 5000);
|
|
||||||
alert('Custom JSON error: ' + e.message);
|
|
||||||
document.getElementById('custom').value = c;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
let parser = {};
|
|
||||||
const p = document.getElementById('parser').value;
|
|
||||||
try {
|
|
||||||
parser = JSON.parse(p);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
window.setTimeout(() => {
|
|
||||||
notify('Parser JSON error: ' + e.message, 5000);
|
|
||||||
alert('Parser JSON error: ' + e.message);
|
|
||||||
document.getElementById('parser').value = p;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
let siblings = {};
|
|
||||||
const s = document.getElementById('siblings').value;
|
|
||||||
try {
|
|
||||||
siblings = JSON.parse(s);
|
|
||||||
siblings = siblings.reduce((p, c, i) => {
|
|
||||||
c.forEach(hostname => p[hostname] = i);
|
|
||||||
return p;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
window.setTimeout(() => {
|
|
||||||
notify('Sibling JSON error: ' + e.message, 5000);
|
|
||||||
alert('Sibling JSON error: ' + e.message);
|
|
||||||
document.getElementById('siblings').value = s;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.storage.local.set({
|
|
||||||
exactMatch: document.getElementById('exactMatch').checked,
|
|
||||||
faqs: document.getElementById('faqs').checked,
|
|
||||||
userAgentData: document.getElementById('userAgentData').checked,
|
|
||||||
log: document.getElementById('log').checked,
|
|
||||||
cache: document.getElementById('cache').checked,
|
|
||||||
blacklist: prepare(document.getElementById('blacklist').value),
|
|
||||||
whitelist: prepare(document.getElementById('whitelist').value),
|
|
||||||
custom,
|
|
||||||
parser,
|
|
||||||
siblings,
|
|
||||||
mode: document.querySelector('[name="mode"]:checked').value,
|
|
||||||
protected: document.getElementById('protected').value.split(/\s*,\s*/).filter(s => s.length > 4)
|
|
||||||
}, () => {
|
|
||||||
restore();
|
|
||||||
notify(chrome.i18n.getMessage('optionsSaved'));
|
|
||||||
|
|
||||||
chrome.contextMenus.update(document.querySelector('[name="mode"]:checked').value, {
|
|
||||||
checked: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function restore() {
|
|
||||||
chrome.storage.local.get({
|
|
||||||
exactMatch: false,
|
|
||||||
faqs: true,
|
|
||||||
userAgentData: true,
|
|
||||||
log: false,
|
|
||||||
cache: true,
|
|
||||||
mode: 'blacklist',
|
|
||||||
whitelist: [],
|
|
||||||
blacklist: [],
|
|
||||||
custom: {},
|
|
||||||
parser: {},
|
|
||||||
siblings: {},
|
|
||||||
protected: [
|
|
||||||
'google.com/recaptcha',
|
|
||||||
'gstatic.com/recaptcha',
|
|
||||||
'accounts.google.com',
|
|
||||||
'accounts.youtube.com',
|
|
||||||
'gitlab.com/users/sign_in'
|
|
||||||
]
|
|
||||||
}, prefs => {
|
|
||||||
document.getElementById('exactMatch').checked = prefs.exactMatch;
|
|
||||||
document.getElementById('faqs').checked = prefs.faqs;
|
|
||||||
document.getElementById('userAgentData').checked = prefs.userAgentData;
|
|
||||||
document.getElementById('log').checked = prefs.log;
|
|
||||||
document.getElementById('cache').checked = prefs.cache;
|
|
||||||
document.querySelector(`[name="mode"][value="${prefs.mode}"`).checked = true;
|
|
||||||
document.getElementById('blacklist').value = prefs.blacklist.join(', ');
|
|
||||||
document.getElementById('whitelist').value = prefs.whitelist.join(', ');
|
|
||||||
document.getElementById('custom').value = JSON.stringify(prefs.custom, null, 2);
|
|
||||||
document.getElementById('parser').value = JSON.stringify(prefs.parser, null, 2);
|
|
||||||
document.getElementById('siblings').value = JSON.stringify(Object.entries(prefs.siblings).reduce((p, [hostname, index]) => {
|
|
||||||
p[index] = p[index] || [];
|
|
||||||
p[index].push(hostname);
|
|
||||||
return p;
|
|
||||||
}, []), null, 2);
|
|
||||||
document.getElementById('protected').value = prefs.protected.join(', ');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
document.addEventListener('DOMContentLoaded', restore);
|
|
||||||
document.getElementById('save').addEventListener('click', save);
|
|
||||||
|
|
||||||
document.getElementById('sample').addEventListener('click', e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
document.getElementById('custom').value = JSON.stringify({
|
|
||||||
'www.google.com': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
|
|
||||||
'www.bing.com, www.yahoo.com, www.wikipedia.org': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0',
|
|
||||||
'www.example.com': ['random-useragent-1', 'random-user-agent-2'],
|
|
||||||
'*': 'useragent-for-all-hostnames'
|
|
||||||
}, null, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('sample-2').addEventListener('click', e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
document.getElementById('parser').value = JSON.stringify({
|
|
||||||
'my-custom-useragent': {
|
|
||||||
'appVersion': 'custom app version',
|
|
||||||
'platform': 'custom platform',
|
|
||||||
'vendor': '[delete]',
|
|
||||||
'product': 'custom product',
|
|
||||||
'oscpu': 'custom oscpu',
|
|
||||||
'custom-variable': 'this is a custom variable'
|
|
||||||
}
|
|
||||||
}, null, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('sample-3').addEventListener('click', e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
document.getElementById('siblings').value = JSON.stringify([[
|
|
||||||
'www.google.com', 'www.youtube.com', 'www.youtube.be'
|
|
||||||
], [
|
|
||||||
'www.gmx.com', 'www.mail.com'
|
|
||||||
]], null, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('donate').addEventListener('click', () => {
|
|
||||||
chrome.tabs.create({
|
|
||||||
url: chrome.runtime.getManifest().homepage_url + '?rd=donate'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('reset').addEventListener('click', e => {
|
|
||||||
if (e.detail === 1) {
|
|
||||||
notify(chrome.i18n.getMessage('dbReset'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
localStorage.clear();
|
|
||||||
chrome.storage.local.clear(() => {
|
|
||||||
chrome.runtime.reload();
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('help').addEventListener('click', () => {
|
|
||||||
chrome.tabs.create({
|
|
||||||
url: chrome.runtime.getManifest().homepage_url
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// export
|
|
||||||
document.getElementById('export').addEventListener('click', e => {
|
|
||||||
const guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
||||||
const r = Math.random() * 16 | 0;
|
|
||||||
const v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
||||||
return v.toString(16);
|
|
||||||
});
|
|
||||||
|
|
||||||
chrome.storage.local.get(null, prefs => {
|
|
||||||
for (const key of Object.keys(prefs)) {
|
|
||||||
if (key && key.startsWith('cache.')) {
|
|
||||||
delete prefs[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const text = JSON.stringify(Object.assign({}, prefs, {
|
|
||||||
'json-guid': guid,
|
|
||||||
'json-forced': false
|
|
||||||
}), null, e.shiftKey ? '' : ' ');
|
|
||||||
const blob = new Blob([text], {type: 'application/json'});
|
|
||||||
const objectURL = URL.createObjectURL(blob);
|
|
||||||
Object.assign(document.createElement('a'), {
|
|
||||||
href: objectURL,
|
|
||||||
type: 'application/json',
|
|
||||||
download: 'useragent-switcher-preferences.json'
|
|
||||||
}).dispatchEvent(new MouseEvent('click'));
|
|
||||||
setTimeout(() => URL.revokeObjectURL(objectURL));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// import
|
|
||||||
document.getElementById('import').addEventListener('click', () => {
|
|
||||||
const input = document.createElement('input');
|
|
||||||
input.style.display = 'none';
|
|
||||||
input.type = 'file';
|
|
||||||
input.accept = '.json';
|
|
||||||
input.acceptCharset = 'utf-8';
|
|
||||||
|
|
||||||
document.body.appendChild(input);
|
|
||||||
input.initialValue = input.value;
|
|
||||||
input.onchange = readFile;
|
|
||||||
input.click();
|
|
||||||
|
|
||||||
function readFile() {
|
|
||||||
if (input.value !== input.initialValue) {
|
|
||||||
const file = input.files[0];
|
|
||||||
if (file.size > 100e6) {
|
|
||||||
console.warn('100MB backup? I don\'t believe you.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onloadend = event => {
|
|
||||||
input.remove();
|
|
||||||
const json = JSON.parse(event.target.result);
|
|
||||||
chrome.storage.local.clear(() => {
|
|
||||||
chrome.storage.local.set(json, () => {
|
|
||||||
window.close();
|
|
||||||
chrome.runtime.reload();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
reader.readAsText(file, 'utf-8');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* toggle */
|
|
||||||
document.getElementById('toggle-blacklist-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-blacklist-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById('toggle-whitelist-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-whitelist-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById('toggle-custom-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-custom-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById('toggle-protected-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-protected-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById('toggle-parser-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-parser-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById('toggle-sibling-desc').addEventListener('click', () => {
|
|
||||||
document.querySelector('[for="toggle-sibling-desc"]').classList.toggle('hidden');
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows; U; Windows CE; Mobile; like Android; ko-kr) AppleWebKit/533.3 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.3 Dorothy","browser":{"name":"Android Browser","version":"4.0","major":"4"},"engine":{"name":"WebKit","version":"533.3"},"os":{"name":"Windows","version":"CE"},"device":{"type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4","browser":{"name":"Android Browser","version":"5.0.3","major":"5"},"engine":{"name":"WebKit","version":"533.19.4"},"os":{"name":"Windows","version":"7"},"device":{"model":"en-US","type":"tablet"},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )","browser":{"name":"Arora","version":"0.6","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"Vista"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )","browser":{"name":"Arora","version":"0.6","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.4 (Change: )","browser":{"name":"Arora","version":"0.4","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"Vista"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 6.0; de-DE) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.4 (Change: )","browser":{"name":"Arora","version":"0.4","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"Vista"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.2; pt-BR) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.4 (Change: )","browser":{"name":"Arora","version":"0.4","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.4 (Change: )","browser":{"name":"Arora","version":"0.4","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","browser":{"name":"Arora","version":"0.3","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-BE) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","browser":{"name":"Arora","version":"0.3","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","browser":{"name":"Arora","version":"0.3","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 6.0; de-DE) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2","browser":{"name":"Arora","version":"0.2","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"Vista"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2","browser":{"name":"Arora","version":"0.2","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2","browser":{"name":"Arora","version":"0.2","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; de-CH) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2","browser":{"name":"Arora","version":"0.2","major":"0"},"engine":{"name":"WebKit","version":"523.15"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) Arora/0.11.0 Safari/534.34","browser":{"name":"Arora","version":"0.11.0","major":"0"},"engine":{"name":"WebKit","version":"534.34"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-MY) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.10.0","browser":{"name":"Arora","version":"0.10.0","major":"0"},"engine":{"name":"WebKit","version":"527"},"os":{"name":"Windows","version":"Vista"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 Avast/72.0.1174.122","browser":{"name":"Avast Secure Browser","version":"72.0.1174.122","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.121"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 Avast/72.0.1174.122","browser":{"name":"Avast Secure Browser","version":"72.0.1174.122","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.121"},"os":{"name":"Windows","version":"8.1"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36 Avast/80.0.3571.123","browser":{"name":"Avast Secure Browser","version":"80.0.3571.123","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.122"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36 Avast/80.0.3571.123","browser":{"name":"Avast Secure Browser","version":"80.0.3571.123","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.122"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 AVG/72.0.718.83","browser":{"name":"AVG Secure Browser","version":"72.0.718.83","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.81"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36 AVG/80.0.3573.124","browser":{"name":"AVG Secure Browser","version":"80.0.3573.124","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.122"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Linux; Android 5.1.1; vivo X7 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/48.0.2564.116 Mobile Safari/537.36 baiduboxapp/8.6.5 (Baidu; P1 5.1.1)","browser":{"name":"baiduboxapp","version":"8.6.5","major":"8"},"engine":{"name":"Blink","version":"48.0.2564.116"},"os":{"name":"Android","version":"5.1.1"},"device":{"vendor":"Vivo","model":"X7","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (Linux; Android 8.0.0; SM-N9500 Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/10.13 baiduboxapp/10.13.0.11 (Baidu; P1 8.0.0)","browser":{"name":"baiduboxapp","version":"10.13.0.11","major":"10"},"engine":{"name":"Blink","version":"63.0.3239.83"},"os":{"name":"Android","version":"8.0.0"},"device":{"vendor":"Samsung","model":"SM-N9500","type":"mobile"},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.9) Gecko/20100101 Goanna/4.1 Firefox/60.9 Basilisk/20190327","browser":{"name":"Basilisk","version":"20190327","major":"20190327"},"engine":{"name":"Goanna","version":"4.1"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0) Gecko/20100101 Goanna/4.0 Firefox/55.0 Basilisk/20210125","browser":{"name":"Basilisk","version":"20210125","major":"20210125"},"engine":{"name":"Goanna","version":"4.0"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Goanna/4.8 Firefox/68.0 Basilisk/20210317","browser":{"name":"Basilisk","version":"20210317","major":"20210317"},"engine":{"name":"Goanna","version":"4.8"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Goanna/4.8 Firefox/68.0 Basilisk/20210927","browser":{"name":"Basilisk","version":"20210927","major":"20210927"},"engine":{"name":"Goanna","version":"4.8"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/4.0 (compatible; MSIE 6.0; Windows 95; PalmSource; Blazer 3.0) 16; 160x160","browser":{"name":"Blazer","version":"3.0","major":"3"},"engine":{},"os":{"name":"Windows","version":"95"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.340) AppleWebKit/530+ (KHTML, like Gecko) Version/4.0 Safari/530.17 UNTRUSTED/1.0 3gpp-gba","browser":{"name":"BOLT","version":"2.340","major":"2"},"engine":{"name":"WebKit","version":"530"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Gentoo 2.7; Linux 5.8; x86_64; DoNotTrack) AppleWebKit/537.36 (KHTML, like Gecko) Brave/1.14.81 Chrome/85.0.4183.102 Safari/537.36","browser":{"name":"Brave","version":"1.14.81","major":"1"},"engine":{"name":"Blink","version":"85.0.4183.102"},"os":{"name":"Gentoo","version":"2.7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Gentoo 2.7; Linux 5.10; x86_64; DoNotTrack) AppleWebKit/537.36 (KHTML, like Gecko) Brave/1.18.0 Chrome/87.0.4280.101 Safari/537.36","browser":{"name":"Brave","version":"1.18.0","major":"1"},"engine":{"name":"Blink","version":"87.0.4280.101"},"os":{"name":"Gentoo","version":"2.7"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.4 Mobile/13E238 Safari/601.1.46","browser":{"name":"Brave","version":"1.2.4","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.1"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.5 Mobile/13F69 Safari/601.1.46 _id/000005","browser":{"name":"Brave","version":"1.2.5","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.2"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.7 Mobile/13F69 Safari/601.1.46","browser":{"name":"Brave","version":"1.2.7","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.2"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.10 Mobile/13F69 Safari/601.1.46","browser":{"name":"Brave","version":"1.2.10","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.2"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_3 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.11 Mobile/13G34 Safari/601.1.46 _id/000004","browser":{"name":"Brave","version":"1.2.11","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.3"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Brave/1.2.11 Mobile/13G35 Safari/601.1.46 _id/000002","browser":{"name":"Brave","version":"1.2.11","major":"1"},"engine":{"name":"WebKit","version":"601.1.46"},"os":{"name":"iOS","version":"9.3.4"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Brave/1.2.9 Mobile/14A5297c Safari/602.1.38","browser":{"name":"Brave","version":"1.2.9","major":"1"},"engine":{"name":"WebKit","version":"602.1.38"},"os":{"name":"iOS","version":"10.0"},"device":{"vendor":"Apple","model":"iPhone","type":"mobile"},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/74.0.3729.157 Safari/537.36 Brave/74","browser":{"name":"Brave","version":"74","major":"74"},"engine":{"name":"Blink","version":"74.0.3729.157"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36 Brave/74","browser":{"name":"Brave","version":"74","major":"74"},"engine":{"name":"Blink","version":"74.0.3729.157"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.38 Safari/537.36 Brave/75","browser":{"name":"Brave","version":"75","major":"75"},"engine":{"name":"Blink","version":"75.0.3770.38"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.7.16 Chrome/47.0.2526.110 Brave/0.36.8 Safari/537.36","browser":{"name":"brave","version":"0.7.16","major":"0"},"engine":{"name":"Blink","version":"47.0.2526.110"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.8.2 Chrome/49.0.2623.87 Brave/0.37.2 Safari/537.36","browser":{"name":"brave","version":"0.8.2","major":"0"},"engine":{"name":"Blink","version":"49.0.2623.87"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.8.3 Chrome/49.0.2623.108 Brave/0.37.3 Safari/537.36","browser":{"name":"brave","version":"0.8.3","major":"0"},"engine":{"name":"Blink","version":"49.0.2623.108"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux Mint i686; rv:64.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Brave/1.5.122","browser":{"name":"Brave","version":"1.5.122","major":"1"},"engine":{"name":"Blink","version":"80.0.3987.163"},"os":{"name":"Mint","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3; x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Brave/1.5.122","browser":{"name":"Brave","version":"1.5.122","major":"1"},"engine":{"name":"Blink","version":"80.0.3987.163"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3; x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36 Brave/1.5.122","browser":{"name":"Brave","version":"1.5.122","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.92"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; OpenBSD i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36 Brave/1.5.115","browser":{"name":"Brave","version":"1.5.115","major":"1"},"engine":{"name":"Blink","version":"80.0.3987.162"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Brave/1.7.92","browser":{"name":"Brave","version":"1.7.92","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.113"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36 Brave/1.7.92","browser":{"name":"Brave","version":"1.7.92","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.122"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Brave/1.7.92","browser":{"name":"Brave","version":"1.7.92","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.129"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Brave/1.8.86","browser":{"name":"Brave","version":"1.8.86","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.129"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Brave/1.8.86","browser":{"name":"Brave","version":"1.8.86","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.138"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Brave/1.8.95","browser":{"name":"Brave","version":"1.8.95","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.138"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Brave/1.9.72","browser":{"name":"Brave","version":"1.9.72","major":"1"},"engine":{"name":"Blink","version":"83.0.4103.61"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 Brave/1.9.72","browser":{"name":"Brave","version":"1.9.72","major":"1"},"engine":{"name":"Blink","version":"83.0.4103.97"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 Brave/1.10.90","browser":{"name":"Brave","version":"1.10.90","major":"1"},"engine":{"name":"Blink","version":"83.0.4103.106"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Brave/1.10.97","browser":{"name":"Brave","version":"1.10.97","major":"1"},"engine":{"name":"Blink","version":"83.0.4103.116"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD; x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Brave/1.5.122","browser":{"name":"Brave","version":"1.5.122","major":"1"},"engine":{"name":"Blink","version":"80.0.3987.163"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; OpenBSD; x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36 Brave/1.5.122","browser":{"name":"Brave","version":"1.5.122","major":"1"},"engine":{"name":"Blink","version":"81.0.4044.92"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-PL; rv:1.0.1) Gecko/20021111 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-PL; rv:1.0.1) Gecko/20021111 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021104 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20030111 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS","version":"Mach"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20030109 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS","version":"Mach"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20021220 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS","version":"Mach"},"device":{},"cpu":{"architecture":"ppc"}},{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20021216 Chimera/0.6","browser":{"name":"Chimera","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.0.1"},"os":{"name":"Mac OS","version":"Mach"},"device":{},"cpu":{"architecture":"ppc"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/69.0.3497.81 Safari/537.36 SQWatcher/201906 (sqcompliance.com/sqwatcher.html)","browser":{"name":"Chrome Headless","version":"69.0.3497.81","major":"69"},"engine":{"name":"Blink","version":"69.0.3497.81"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/75.0.3770.142 Safari/537.36","browser":{"name":"Chrome Headless","version":"75.0.3770.142","major":"75"},"engine":{"name":"Blink","version":"75.0.3770.142"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows NT 6.0; Win64; x64; Xbox; Xbox One) AppleWebKit/606 (KHTML, like Gecko) HeadlessChrome/81.0.4015.0 Safari/606","browser":{"name":"Chrome Headless","version":"81.0.4015.0","major":"81"},"engine":{"name":"WebKit","version":"606"},"os":{"name":"Xbox","version":"One"},"device":{"vendor":"Microsoft","model":"Xbox One","type":"console"},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One) AppleWebKit/606 (KHTML, like Gecko) HeadlessChrome/81.0.4015.0 Safari/606","browser":{"name":"Chrome Headless","version":"81.0.4015.0","major":"81"},"engine":{"name":"WebKit","version":"606"},"os":{"name":"Xbox","version":"One"},"device":{"vendor":"Microsoft","model":"Xbox One","type":"console"},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Chrome/4.0.237.0 Safari/532.4 Debian","browser":{"name":"Chrome","version":"4.0.237.0","major":"4"},"engine":{"name":"WebKit","version":"532.4"},"os":{"name":"Debian"},"device":{},"cpu":{"architecture":"ia32"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/536.5 (KHTML like Gecko) Chrome/19.0.1084.56 Safari/1EA69","browser":{"name":"Chrome","version":"19.0.1084.56","major":"19"},"engine":{"name":"WebKit","version":"536.5"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.65 Safari/535.11","browser":{"name":"Chrome","version":"17.0.963.65","major":"17"},"engine":{"name":"WebKit","version":"535.11"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; FreeBSD i386) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2","browser":{"name":"Chrome","version":"15.0.874.121","major":"15"},"engine":{"name":"WebKit","version":"535.2"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16","browser":{"name":"Chrome","version":"10.0.648.204","major":"10"},"engine":{"name":"WebKit","version":"534.16"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16","browser":{"name":"Chrome","version":"10.0.648.204","major":"10"},"engine":{"name":"WebKit","version":"534.16"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.207.0 Safari/532.0","browser":{"name":"Chrome","version":"4.0.207.0","major":"4"},"engine":{"name":"WebKit","version":"532.0"},"os":{"name":"FreeBSD"},"device":{},"cpu":{"architecture":"ia32"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/81.0.4044.113 Safari/537.36","browser":{"name":"Chrome","version":"81.0.4044.113","major":"81"},"engine":{"name":"Blink","version":"81.0.4044.113"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/81.0.4044.122 Safari/537.36","browser":{"name":"Chrome","version":"81.0.4044.122","major":"81"},"engine":{"name":"Blink","version":"81.0.4044.122"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/81.0.4044.138 Safari/537.36","browser":{"name":"Chrome","version":"81.0.4044.138","major":"81"},"engine":{"name":"Blink","version":"81.0.4044.138"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.61 Safari/537.36","browser":{"name":"Chrome","version":"83.0.4103.61","major":"83"},"engine":{"name":"Blink","version":"83.0.4103.61"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.97 Safari/537.36","browser":{"name":"Chrome","version":"83.0.4103.97","major":"83"},"engine":{"name":"Blink","version":"83.0.4103.97"},"os":{"name":"Mint","version":"19"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/20 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.97 Safari/537.36","browser":{"name":"Chrome","version":"83.0.4103.97","major":"83"},"engine":{"name":"Blink","version":"83.0.4103.97"},"os":{"name":"Mint","version":"20"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux Mint/20 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.116 Safari/537.36","browser":{"name":"Chrome","version":"83.0.4103.116","major":"83"},"engine":{"name":"Blink","version":"83.0.4103.116"},"os":{"name":"Mint","version":"20"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36","browser":{"name":"Chrome","version":"27.0.1453.116","major":"27"},"engine":{"name":"WebKit","version":"537.36"},"os":{"name":"NetBSD"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36","browser":{"name":"Chrome","version":"27.0.1453.116","major":"27"},"engine":{"name":"WebKit","version":"537.36"},"os":{"name":"NetBSD"},"device":{},"cpu":{}},{"ua":"b'Mozilla/5.0 (X11; NetBSD amd64;) AppleWebKit/535.36 (KHTML, like Gecko) Chrome/51.0.2840.71 Safari/535.36'","browser":{"name":"Chrome","version":"51.0.2840.71","major":"51"},"engine":{"name":"WebKit","version":"535.36"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; NetBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.111","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.111"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"b'Mozilla/5.0 (X11; NetBSD amd64;) AppleWebKit/533.36 (KHTML, like Gecko) Chrome/49.0.2840.71 Safari/533.36'","browser":{"name":"Chrome","version":"49.0.2840.71","major":"49"},"engine":{"name":"WebKit","version":"533.36"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; NetBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.111","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.111"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; NetBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.122","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.122"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; NetBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.104","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.104"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; NetBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.122","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.122"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; NetBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36","browser":{"name":"Chrome","version":"38.0.2125.104","major":"38"},"engine":{"name":"Blink","version":"38.0.2125.104"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36","browser":{"name":"Chrome","version":"27.0.1453.116","major":"27"},"engine":{"name":"WebKit","version":"537.36"},"os":{"name":"NetBSD"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36","browser":{"name":"Chrome","version":"36.0.1985.125","major":"36"},"engine":{"name":"Blink","version":"36.0.1985.125"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; OpenBSD i386; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.359.0 Safari/533.3","browser":{"name":"Chrome","version":"5.0.359.0","major":"5"},"engine":{"name":"WebKit","version":"533.3"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36","browser":{"name":"Chrome","version":"43.0.2357.125","major":"43"},"engine":{"name":"Blink","version":"43.0.2357.125"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36","browser":{"name":"Chrome","version":"36.0.1985.125","major":"36"},"engine":{"name":"Blink","version":"36.0.1985.125"},"os":{"name":"OpenBSD"},"device":{},"cpu":{"architecture":"ia32"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41","browser":{"name":"Chrome","version":"13.0.782.41","major":"13"},"engine":{"name":"WebKit","version":"535.1"},"os":{"name":"Slackware","version":"13.37"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/12.0.742.91","browser":{"name":"Chrome","version":"12.0.742.91","major":"12"},"engine":{"name":"WebKit","version":"534.16"},"os":{"name":"Slackware","version":"13.37"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Slackware/Chrome/12.0.742.100 Safari/534.30","browser":{"name":"Chrome","version":"12.0.742.100","major":"12"},"engine":{"name":"WebKit","version":"534.30"},"os":{"name":"Slackware"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/11.0.696.50","browser":{"name":"Chrome","version":"11.0.696.50","major":"11"},"engine":{"name":"WebKit","version":"534.16"},"os":{"name":"Slackware","version":"13.37"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Slackware Linux x86_64; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.30 Safari/532.5","browser":{"name":"Chrome","version":"4.0.249.30","major":"4"},"engine":{"name":"WebKit","version":"532.5"},"os":{"name":"Slackware","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 SUSE/10.0.626.0 (KHTML, like Gecko) Chrome/10.0.626.0 Safari/534.16","browser":{"name":"Chrome","version":"10.0.626.0","major":"10"},"engine":{"name":"WebKit","version":"534.16"},"os":{"name":"SUSE","version":"10.0.626.0"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.1 SUSE/6.0.428.0 (KHTML, like Gecko) Chrome/6.0.428.0 Safari/534.1","browser":{"name":"Chrome","version":"6.0.428.0","major":"6"},"engine":{"name":"WebKit","version":"534.1"},"os":{"name":"SUSE","version":"6.0.428.0"},"device":{},"cpu":{"architecture":"ia32"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0","browser":{"name":"Chrome","version":"9.1.0.0","major":"9"},"engine":{"name":"WebKit","version":"540.0"},"os":{"name":"Ubuntu","version":"10.10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/8.1.0.0 Safari/540.0","browser":{"name":"Chrome","version":"8.1.0.0","major":"8"},"engine":{"name":"WebKit","version":"540.0"},"os":{"name":"Ubuntu","version":"10.10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/14.04.6 Chrome/81.0.3990.0 Safari/537.36","browser":{"name":"Chrome","version":"81.0.3990.0","major":"81"},"engine":{"name":"WebKit","version":"535.11"},"os":{"name":"Ubuntu","version":"14.04.6"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/14.04.6 Chrome/81.0.3990.0 Safari/537.36","browser":{"name":"Chrome","version":"81.0.3990.0","major":"81"},"engine":{"name":"WebKit","version":"535.11"},"os":{"name":"Ubuntu","version":"14.04.6"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; U; Unix; en-US) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15 Surf/0.7","browser":{"name":"Chrome","version":"24.0.1295.0","major":"24"},"engine":{"name":"WebKit","version":"537.15"},"os":{"name":"Unix"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; U; Unix; en-US) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15 Surf/0.6","browser":{"name":"Chrome","version":"24.0.1295.0","major":"24"},"engine":{"name":"WebKit","version":"537.15"},"os":{"name":"Unix"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 650) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Safari/537.36","browser":{"name":"Chrome","version":"54.0.2840.85","major":"54"},"engine":{"name":"Blink","version":"54.0.2840.85"},"os":{"name":"Windows Phone","version":"10.0"},"device":{"vendor":"Microsoft","model":"Lumia 650","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0","browser":{"name":"Chrome","version":"46.0.2486.0","major":"46"},"engine":{"name":"Blink","version":"46.0.2486.0"},"os":{"name":"Windows Phone","version":"10.0"},"device":{"vendor":"Microsoft","model":"Xbox One","type":"console"},"cpu":{}},{"ua":"Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; Lumia 650) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Mobile Safari/537.36","browser":{"name":"Chrome","version":"51.0.2704.79","major":"51"},"engine":{"name":"Blink","version":"51.0.2704.79"},"os":{"name":"Windows Phone","version":"10.0"},"device":{"vendor":"Microsoft","model":"Lumia 650","type":"mobile"},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.91 Chromium/12.0.742.91 Safari/534.30","browser":{"name":"Chromium","version":"12.0.742.91","major":"12"},"engine":{"name":"WebKit","version":"534.30"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/74.0.3729.131 Chrome/74.0.3729.131 Safari/537.36","browser":{"name":"Chromium","version":"74.0.3729.131","major":"74"},"engine":{"name":"Blink","version":"74.0.3729.131"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/80.0.3987.132 Chrome/80.0.3987.132 Safari/537.36","browser":{"name":"Chromium","version":"80.0.3987.132","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.132"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/80.0.3987.132 Chrome/80.0.3987.132 Safari/537.36","browser":{"name":"Chromium","version":"80.0.3987.132","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.132"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) snap Chromium/80.0.3987.132 Chrome/80.0.3987.132 Safari/537.36","browser":{"name":"Chromium","version":"80.0.3987.132","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.132"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/feature/ui-plus-fsd-0b6dd4d4db1f","browser":{"name":"Chromium","version":"79.0.3945.130","major":"79"},"engine":{"name":"Blink","version":"79.0.3945.130"},"os":{"name":"Linux"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/feature/ui-plus-fsd-0dd2b30798bf","browser":{"name":"Chromium","version":"79.0.3945.130","major":"79"},"engine":{"name":"Blink","version":"79.0.3945.130"},"os":{"name":"Linux"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/feature/ui-plus-fsd-a6439fd47d02","browser":{"name":"Chromium","version":"79.0.3945.130","major":"79"},"engine":{"name":"Blink","version":"79.0.3945.130"},"os":{"name":"Linux"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/88.0.4324.150 Chrome/88.0.4324.150 Safari/537.36 Tesla/DEV-BUILD-4d1a3f465b3a","browser":{"name":"Chromium","version":"88.0.4324.150","major":"88"},"engine":{"name":"Blink","version":"88.0.4324.150"},"os":{"name":"Linux"},"device":{},"cpu":{}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; NetBSD x86; en-us) AppleWebKit/666.6+ (KHTML, like Gecko) Chromium/20.0.0000.00 Chrome/20.0.0000.00 Safari/666.6+","browser":{"name":"Chromium","version":"20.0.0000.00","major":"20"},"engine":{"name":"WebKit","version":"666.6"},"os":{"name":"NetBSD"},"device":{},"cpu":{"architecture":"ia32"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/78.0.3904.108 Chrome/78.0.3904.108 Safari/537.36","browser":{"name":"Chromium","version":"78.0.3904.108","major":"78"},"engine":{"name":"Blink","version":"78.0.3904.108"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}},{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/72.0.3626.121 Chrome/72.0.3626.121 Safari/537.36","browser":{"name":"Chromium","version":"72.0.3626.121","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.121"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}},{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/74.0.3729.157 Chrome/74.0.3729.157 Safari/537.36","browser":{"name":"Chromium","version":"74.0.3729.157","major":"74"},"engine":{"name":"Blink","version":"74.0.3729.157"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}},{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/78.0.3904.108 Chrome/78.0.3904.108 Safari/537.36","browser":{"name":"Chromium","version":"78.0.3904.108","major":"78"},"engine":{"name":"Blink","version":"78.0.3904.108"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}},{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/74.0.3729.157 Chrome/74.0.3729.157 Safari/537.36","browser":{"name":"Chromium","version":"74.0.3729.157","major":"74"},"engine":{"name":"Blink","version":"74.0.3729.157"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}},{"ua":"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/72.0.3626.121 Chrome/72.0.3626.121 Safari/537.36","browser":{"name":"Chromium","version":"72.0.3626.121","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.121"},"os":{"name":"Raspbian"},"device":{},"cpu":{"architecture":"arm"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (Windows NT 6.1; Win32; x86) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/72.0.3626.96 Chrome/72.0.3626.96 Safari/537.36","browser":{"name":"Chromium","version":"72.0.3626.96","major":"72"},"engine":{"name":"Blink","version":"72.0.3626.96"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 (Chromium GOST)","browser":{"name":"Chromium","version":"GOST","major":""},"engine":{"name":"Blink","version":"100.0.4896.60"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36 (Chromium GOST)","browser":{"name":"Chromium","version":"GOST","major":""},"engine":{"name":"Blink","version":"99.0.4844.83"},"os":{"name":"Windows","version":"10"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|
|
@ -1 +0,0 @@
|
||||||
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Comodo_Dragon/4.1.1.11 Chrome/4.1.249.1042 Safari/532.5","browser":{"name":"Comodo Dragon","version":"4.1.1.11","major":"4"},"engine":{"name":"WebKit","version":"532.5"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}}]
|
|