This commit is contained in:
Ray Lothian 2020-12-28 14:17:45 +01:00
parent b9a23d8ce2
commit ae8219dd9e
303 changed files with 321 additions and 24 deletions

1
extension/firefox/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../LICENSE

View file

@ -0,0 +1,2 @@
ua-parser.min.js:
https://github.com/faisalman/ua-parser-js/releases/tag/0.7.23

View file

@ -0,0 +1,208 @@
{
"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"
},
"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!"
}
}

View file

@ -0,0 +1,208 @@
{
"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 раза левой кнопкой мыши для сброса!"
}
}

622
extension/firefox/common.js Normal file
View file

@ -0,0 +1,622 @@
/* globals 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,
'protected': ['google.com/recaptcha', 'gstatic.com/recaptcha'],
'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) {
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 || '';
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';
}
if (isFF) {
o.oscpu = ((p.os.name || '') + ' ' + (p.os.version || '')).trim();
}
else {
o.oscpu = '[delete]';
}
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.substr(0, 3) : ''
});
}));
}
else if (tabId) {
const o = ua.object(tabId, undefined, cookieStoreId);
chrome.browserAction.setBadgeText({
tabId,
text: o.platform ? o.platform.substr(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.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) {
if (name === 'User-Agent' || name === 'user-agent') {
requestHeaders[i].value = str === 'empty' ? '' : str;
return {
requestHeaders
};
}
}
}
};
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) {
chrome.tabs.executeScript(tabId, {
runAt: 'document_start',
frameId,
code: `{
const script = document.createElement('script');
script.src = 'data:text/javascript;charset=utf-8;base64,' + btoa(\`{
const o = JSON.parse('${JSON.stringify(o)}');
for (const key of Object.keys(o)) {
navigator.__defineGetter__(key, () => {
if (o[key] === '[delete]') {
return undefined;
}
else if (o[key] === 'empty') {
return '';
}
return o[key];
});
}
}\`);
document.documentElement.appendChild(script);
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, undefined, 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.create({
url: page + '?version=' + version + (previousVersion ? '&p=' + previousVersion : '') + '&type=' + reason,
active: reason === 'install'
});
storage.local.set({'last-update': Date.now()});
}
}
}));
});
setUninstallURL(page + '?rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

View file

@ -0,0 +1,47 @@
'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) {}
}

View file

@ -0,0 +1,147 @@
: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;
}

View file

@ -0,0 +1,81 @@
<!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="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>

View file

@ -0,0 +1,277 @@
'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,
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,
log: false,
cache: true,
mode: 'blacklist',
whitelist: [],
blacklist: [],
custom: {},
parser: {},
siblings: {},
protected: ['google.com/recaptcha', 'gstatic.com/recaptcha']
}, prefs => {
document.getElementById('exactMatch').checked = prefs.exactMatch;
document.getElementById('faqs').checked = prefs.faqs;
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');
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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":{}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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":{}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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":{"model":"vivo 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":{}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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":{}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (compatible; DotBot/1.1; http://www.opensiteexplorer.org/dotbot, help@moz.com)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; Qwantify/Bleriot/1.1; +https://help.qwant.com/bot)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; SemrushBot/3~bl; +http://www.semrush.com/bot.html)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; Linux x86_64; Mail.RU_Bot/2.0; +http://go.mail.ru/help/robots)","browser":{},"engine":{},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; coccocbot-image/1.0; +http://help.coccoc.com/searchengine)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; SeznamBot/3.2; +http://napoveda.seznam.cz/en/seznambot-intro/)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; Googlebot/2.1; startmebot/1.0; +https://start.me/bot)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (TweetmemeBot/4.0; +http://datasift.com/bot.html) Gecko/20100101 Firefox/31.0","browser":{"name":"Firefox","version":"31.0","major":"31"},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; Go-http-client/1.1; +centurybot9@gmail.com)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; SemrushBot/1.0~bm; +http://www.semrush.com/bot.html)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible;contxbot/1.0)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; AmazonAdBot/1.0; +https://adbot.amazon.com)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Safari/537.36","browser":{"name":"Safari"},"engine":{"name":"WebKit","version":"537.36"},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)","browser":{},"engine":{},"os":{},"device":{},"cpu":{}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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"}}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","browser":{"name":"Chrome","version":"63.0.3239.132","major":"63"},"engine":{"name":"Blink","version":"63.0.3239.132"},"os":{"name":"Fedora"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36","browser":{"name":"Chrome","version":"79.0.3945.130","major":"79"},"engine":{"name":"Blink","version":"79.0.3945.130"},"os":{"name":"Fedora"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36","browser":{"name":"Chrome","version":"80.0.3987.132","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.132"},"os":{"name":"Fedora"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"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","version":"amd64"},"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","version":"amd64"},"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","version":"i386"},"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","version":"x86_64"},"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","version":"i386"},"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","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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 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","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}},{"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","version":"amd64"},"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","version":"amd64"},"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","version":"i386"},"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","version":"i386"},"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","version":"amd64"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"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","version":"i386"},"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","version":"i386"},"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","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}}]

View file

@ -0,0 +1 @@
[{"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":"Linux"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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":{}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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 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":"Linux","version":"armv7l"},"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":"Linux","version":"armv7l"},"device":{},"cpu":{"architecture":"arm"}}]

View file

@ -0,0 +1 @@
[{"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","version":"x86"},"device":{},"cpu":{"architecture":"ia32"}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"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"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7","browser":{"name":"Comodo Dragon","version":"16.1.1.0","major":"16"},"engine":{"name":"WebKit","version":"535.7"},"os":{"name":"Windows","version":"8"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.30 (KHTML, like Gecko) Comodo_Dragon/12.1.0.0 Chrome/12.0.742.91 Safari/534.30","browser":{"name":"Comodo Dragon","version":"12.1.0.0","major":"12"},"engine":{"name":"WebKit","version":"534.30"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Comodo_Dragon/12.1.0.0 Chrome/12.0.742.91 Safari/534.30","browser":{"name":"Comodo Dragon","version":"12.1.0.0","major":"12"},"engine":{"name":"WebKit","version":"534.30"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.30 (KHTML, like Gecko) Comodo_Dragon/12.1.0.0 Chrome/12.0.742.91 Safari/534.30","browser":{"name":"Comodo Dragon","version":"12.1.0.0","major":"12"},"engine":{"name":"WebKit","version":"534.30"},"os":{"name":"Windows","version":"XP"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Windows; U; Windows NT 5.1; 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":"Windows","version":"XP"},"device":{},"cpu":{}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; Linux x86_64; rv:10.0.11) Gecko/20100101 conkeror/1.0pre (Debian-1.0~~pre+git120527-1)","browser":{"name":"conkeror","version":"1.0pre","major":"1"},"engine":{"name":"Gecko","version":"10.0.11"},"os":{"name":"Debian","version":"1.0"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.16) Gecko/20101209 Conkeror/0.9.2 (Debian-0.9.2+git100804-1)","browser":{"name":"Conkeror","version":"0.9.2","major":"0"},"engine":{"name":"Gecko","version":"1.9.1.16"},"os":{"name":"Debian","version":"0.9.2"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.15) Gecko/20101028 Conkeror/0.9.2 (Debian-0.9.2+git100804-1)","browser":{"name":"Conkeror","version":"0.9.2","major":"0"},"engine":{"name":"Gecko","version":"1.9.1.15"},"os":{"name":"Debian","version":"0.9.2"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.14) Gecko/20101020 Conkeror/0.9.2 (Debian-0.9.2+git100804-1)","browser":{"name":"Conkeror","version":"0.9.2","major":"0"},"engine":{"name":"Gecko","version":"1.9.1.14"},"os":{"name":"Debian","version":"0.9.2"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; Linux x86_64; rv:6.0.1) Gecko/20110831 conkeror/0.9.3","browser":{"name":"conkeror","version":"0.9.3","major":"0"},"engine":{"name":"Gecko","version":"6.0.1"},"os":{"name":"Linux","version":"x86_64"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20121010 conkeror/1.0pre","browser":{"name":"conkeror","version":"1.0pre","major":"1"},"engine":{"name":"Gecko","version":"16.0"},"os":{"name":"Windows","version":"7"},"device":{},"cpu":{}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36 Edg/80.0.361.66","browser":{"name":"Edge","version":"80.0.361.66","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.132"},"os":{"name":"Mac OS","version":"10.15.3"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36 Edg/80.0.361.62","browser":{"name":"Edge","version":"80.0.361.62","major":"80"},"engine":{"name":"Blink","version":"80.0.3987.122"},"os":{"name":"Mac OS","version":"10.15.3"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.38 Safari/537.36 Edg/84.0.522.15","browser":{"name":"Edge","version":"84.0.522.15","major":"84"},"engine":{"name":"Blink","version":"84.0.4147.38"},"os":{"name":"Mac OS","version":"10.15.5"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52","browser":{"name":"Edge","version":"84.0.522.52","major":"84"},"engine":{"name":"Blink","version":"84.0.4147.105"},"os":{"name":"Mac OS","version":"10.15.6"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44","browser":{"name":"Edge","version":"85.0.564.44","major":"85"},"engine":{"name":"Blink","version":"85.0.4183.83"},"os":{"name":"Mac OS","version":"10.16.0"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66","browser":{"name":"Edge","version":"87.0.664.66","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"11.1.0"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66","browser":{"name":"Edge","version":"87.0.664.66","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"10.15.3"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66","browser":{"name":"Edge","version":"87.0.664.66","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"10.15.6"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.60","browser":{"name":"Edge","version":"87.0.664.60","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"11.2.0"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66","browser":{"name":"Edge","version":"87.0.664.66","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"10.15.7"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66","browser":{"name":"Edge","version":"87.0.664.66","major":"87"},"engine":{"name":"Blink","version":"87.0.4280.88"},"os":{"name":"Mac OS","version":"10.14.6"},"device":{},"cpu":{}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.14977","browser":{"name":"Edge","version":"15.14977","major":"15"},"engine":{"name":"EdgeHTML","version":"15.14977"},"os":{"name":"Windows Phone","version":"10.0"},"device":{"vendor":"Microsoft","model":"Lumia 950","type":"mobile"},"cpu":{}},{"ua":"Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; RM-1067) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.15063","browser":{"name":"Edge","version":"15.15063","major":"15"},"engine":{"name":"EdgeHTML","version":"15.15063"},"os":{"name":"Windows Phone","version":"10.0"},"device":{"model":"RM-1067","type":"mobile"},"cpu":{}}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.9.0.8) Gecko/20080528 Fedora/2.24.3-4.fc10 Epiphany/2.22 Firefox/3.0","browser":{"name":"Epiphany","version":"2.22","major":"2"},"engine":{"name":"Gecko","version":"1.9.0.8"},"os":{"name":"Fedora","version":"2.24.3-4.fc10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en; rv:1.9.0.5) Gecko/20080528 Fedora/2.24.1-3.fc10 Epiphany/2.22 Firefox/3.0","browser":{"name":"Epiphany","version":"2.22","major":"2"},"engine":{"name":"Gecko","version":"1.9.0.5"},"os":{"name":"Fedora","version":"2.24.1-3.fc10"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.8.1.14) Gecko/20080616 Fedora/2.20.3-4.fc8 Epiphany/2.20 Firefox/2.0.0.14","browser":{"name":"Epiphany","version":"2.20","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.14"},"os":{"name":"Fedora","version":"2.20.3-4.fc8"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en; rv:1.8.1.14) Gecko/20080416 Fedora/2.18.3-9.fc7 Epiphany/2.18 Firefox/2.0.0.14","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.14"},"os":{"name":"Fedora","version":"2.18.3-9.fc7"},"device":{},"cpu":{"architecture":"ia32"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; FreeBSD amd64; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Safari/531.2+ Epiphany/2.30.0","browser":{"name":"Epiphany","version":"2.30.0","major":"2"},"engine":{"name":"WebKit","version":"531.2"},"os":{"name":"FreeBSD","version":"amd64"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD i386; pl; rv:1.8.1.12) Gecko/20080213 Epiphany/2.20 Firefox/2.0.0.12","browser":{"name":"Epiphany","version":"2.20","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.12"},"os":{"name":"FreeBSD","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD i386; en; rv:1.8.1.12) Gecko/20080213 Epiphany/2.20 Firefox/2.0.0.12","browser":{"name":"Epiphany","version":"2.20","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.12"},"os":{"name":"FreeBSD","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8.1) Gecko/20070322 Epiphany/2.18","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1"},"os":{"name":"FreeBSD","version":"i386"},"device":{},"cpu":{"architecture":"ia32"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; Linux i686; en; rv:1.9) Gecko/20080528 (Gentoo) Epiphany/2.22 Firefox/3.0","browser":{"name":"Epiphany","version":"2.22","major":"2"},"engine":{"name":"Gecko","version":"1.9"},"os":{"name":"Gentoo"},"device":{},"cpu":{"architecture":"ia32"}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; OpenBSD arm; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Safari/531.2+ Epiphany/2.30.0","browser":{"name":"Epiphany","version":"2.30.0","major":"2"},"engine":{"name":"WebKit","version":"531.2"},"os":{"name":"OpenBSD","version":"arm"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; U; OpenBSD amd64; en; rv:1.8.1.6) Gecko/20070817 Epiphany/2.18 Firefox/2.0.0.6","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.6"},"os":{"name":"OpenBSD","version":"amd64"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; SunOS 5.11; en-US; rv:1.8.0.2) Gecko/20050405 Epiphany/1.7.1","browser":{"name":"Epiphany","version":"1.7.1","major":"1"},"engine":{"name":"Gecko","version":"1.8.0.2"},"os":{"name":"Solaris","version":"5.11"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20050105 Epiphany/1.4.8","browser":{"name":"Epiphany","version":"1.4.8","major":"1"},"engine":{"name":"Gecko","version":"1.7.5"},"os":{"name":"Solaris","version":"sun4u"},"device":{},"cpu":{"architecture":"sparc"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; zh-cn) AppleWebKit/531.2+ (KHTML, like Gecko) Safari/531.2+ Epiphany/2.28.2 SUSE/2.28.0-2.4","browser":{"name":"Epiphany","version":"2.28.2","major":"2"},"engine":{"name":"WebKit","version":"531.2"},"os":{"name":"SUSE","version":"2.28.0-2.4"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; zh-cn) AppleWebKit/531.2+ (KHTML, like Gecko) Safari/531.2+ Epiphany/2.28.0 SUSE/2.28.0-2.4","browser":{"name":"Epiphany","version":"2.28.0","major":"2"},"engine":{"name":"WebKit","version":"531.2"},"os":{"name":"SUSE","version":"2.28.0-2.4"},"device":{},"cpu":{"architecture":"amd64"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; it-it) AppleWebKit/534.26+ (KHTML, like Gecko) Ubuntu/11.04 Epiphany/2.30.6","browser":{"name":"Epiphany","version":"2.30.6","major":"2"},"engine":{"name":"WebKit","version":"534.26"},"os":{"name":"Ubuntu","version":"11.04"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.9.0.14) Gecko/20080528 Ubuntu/9.10 (karmic) Epiphany/2.22 Firefox/3.0","browser":{"name":"Epiphany","version":"2.22","major":"2"},"engine":{"name":"Gecko","version":"1.9.0.14"},"os":{"name":"Ubuntu","version":"9.10"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.8.1.4) Gecko/20061201 Epiphany/2.18 Firefox/2.0.0.4 (Ubuntu-feisty)","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.4"},"os":{"name":"Ubuntu","version":"feisty"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.8.1.3) Gecko/20061201 Epiphany/2.18 Firefox/2.0.0.3 (Ubuntu-feisty)","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.3"},"os":{"name":"Ubuntu","version":"feisty"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en; rv:1.8.1.3) Gecko/20061201 Epiphany/2.18 Firefox/2.0.0.3 (Ubuntu-feisty)","browser":{"name":"Epiphany","version":"2.18","major":"2"},"engine":{"name":"Gecko","version":"1.8.1.3"},"os":{"name":"Ubuntu","version":"feisty"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en; rv:1.8.0.7) Gecko/20060928 Epiphany/2.14 (Ubuntu)","browser":{"name":"Epiphany","version":"2.14","major":"2"},"engine":{"name":"Gecko","version":"1.8.0.7"},"os":{"name":"Ubuntu"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.5) Gecko/20060731 Ubuntu/dapper-security Epiphany/2.14 Firefox/1.5.0.5","browser":{"name":"Epiphany","version":"2.14","major":"2"},"engine":{"name":"Gecko","version":"1.8.0.5"},"os":{"name":"Ubuntu","version":"dapper-security"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060608 Ubuntu/dapper-security Epiphany/2.14 Firefox/1.5.0.4","browser":{"name":"Epiphany","version":"2.14","major":"2"},"engine":{"name":"Gecko","version":"1.8.0.4"},"os":{"name":"Ubuntu","version":"dapper-security"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.3) Gecko/20060523 Ubuntu/dapper Epiphany/2.14 Firefox/1.5.0.3","browser":{"name":"Epiphany","version":"2.14","major":"2"},"engine":{"name":"Gecko","version":"1.8.0.3"},"os":{"name":"Ubuntu","version":"dapper"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.7.12) Gecko/20051010 Epiphany/1.8.2 (Ubuntu) (Ubuntu package 1.0.7)","browser":{"name":"Epiphany","version":"1.8.2","major":"1"},"engine":{"name":"Gecko","version":"1.7.12"},"os":{"name":"Ubuntu"},"device":{},"cpu":{"architecture":"amd64"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20051010 Epiphany/1.8.2 (Ubuntu) (Ubuntu package 1.0.7)","browser":{"name":"Epiphany","version":"1.8.2","major":"1"},"engine":{"name":"Gecko","version":"1.7.12"},"os":{"name":"Ubuntu"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)","browser":{"name":"Epiphany","version":"1.4.4","major":"1"},"engine":{"name":"Gecko","version":"1.7.3"},"os":{"name":"Ubuntu"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)","browser":{"name":"Epiphany","version":"1.4.4","major":"1"},"engine":{"name":"Gecko","version":"1.7.3"},"os":{"name":"Ubuntu"},"device":{},"cpu":{}}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20110517 Firefox/5.0 Fennec/5.0","browser":{"name":"Fennec","version":"5.0","major":"5"},"engine":{"name":"Gecko","version":"5.0"},"os":{"name":"Mac OS","version":"10.6"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.1) Gecko/20110318 Firefox/4.0b13pre Fennec/4.0","browser":{"name":"Fennec","version":"4.0","major":"4"},"engine":{"name":"Gecko","version":"2.1"},"os":{"name":"Mac OS","version":"10.6"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2a1pre) Gecko/20090626 Fennec/1.0b2","browser":{"name":"Fennec","version":"1.0b2","major":"1"},"engine":{"name":"Gecko","version":"1.9.2a1pr"},"os":{"name":"Mac OS","version":"10.5"},"device":{},"cpu":{}},{"ua":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1","browser":{"name":"Fennec","version":"1.0a1","major":"1"},"engine":{"name":"Gecko","version":"1.9.1b2pr"},"os":{"name":"Mac OS","version":"10.6"},"device":{},"cpu":{}}]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1","browser":{"name":"Firebird","version":"0.6.1","major":"0"},"engine":{"name":"Gecko","version":"1.5a"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030630 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4b"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030607 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4b"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4b"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030505 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4b"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}},{"ua":"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4a) Gecko/20030425 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4a"},"os":{"name":"Linux","version":"i686"},"device":{},"cpu":{"architecture":"ia32"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5) Gecko/20031026 Firebird/0.7","browser":{"name":"Firebird","version":"0.7","major":"0"},"engine":{"name":"Gecko","version":"1.5"},"os":{"name":"Mac OS","version":"Mach"},"device":{},"cpu":{"architecture":"ppc"}}]

View file

@ -0,0 +1 @@
[{"ua":"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5a) Gecko/20030729 Mozilla Firebird/0.6.1","browser":{"name":"Firebird","version":"0.6.1","major":"0"},"engine":{"name":"Gecko","version":"1.5a"},"os":{"name":"Solaris","version":"sun4u"},"device":{},"cpu":{"architecture":"sparc"}},{"ua":"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6","browser":{"name":"Firebird","version":"0.6","major":"0"},"engine":{"name":"Gecko","version":"1.4b"},"os":{"name":"Solaris","version":"sun4u"},"device":{},"cpu":{"architecture":"sparc"}}]

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more