Fix React, Preact detection

main
Elbert Alias 4 years ago
parent aa75a43286
commit ff3284e81d

@ -2,20 +2,20 @@
/* eslint-env browser */ /* eslint-env browser */
/* globals chrome */ /* globals chrome */
function getJs(technologies) { function inject(src, id, message) {
return new Promise((resolve) => { return new Promise((resolve) => {
// Inject a script tag into the page to access methods of the window object // Inject a script tag into the page to access methods of the window object
const script = document.createElement('script') const script = document.createElement('script')
script.onload = () => { script.onload = () => {
const onMessage = ({ data }) => { const onMessage = ({ data }) => {
if (!data.wappalyzer || !data.wappalyzer.js) { if (!data.wappalyzer || !data.wappalyzer[id]) {
return return
} }
window.removeEventListener('message', onMessage) window.removeEventListener('message', onMessage)
resolve(data.wappalyzer.js) resolve(data.wappalyzer[id])
script.remove() script.remove()
} }
@ -23,25 +23,38 @@ function getJs(technologies) {
window.addEventListener('message', onMessage) window.addEventListener('message', onMessage)
window.postMessage({ window.postMessage({
wappalyzer: { wappalyzer: message,
technologies: technologies
.filter(({ js }) => Object.keys(js).length)
.map(({ name, js }) => ({ name, chains: Object.keys(js) })),
},
}) })
} }
script.setAttribute('src', chrome.runtime.getURL('js/inject.js')) script.setAttribute('src', chrome.runtime.getURL(src))
document.body.appendChild(script) document.body.appendChild(script)
}) })
} }
function getDom(technologies) { function getJs(technologies) {
return technologies return inject('js/js.js', 'js', {
technologies: technologies
.filter(({ js }) => Object.keys(js).length)
.map(({ name, js }) => ({ name, chains: Object.keys(js) })),
})
}
async function getDom(technologies) {
const _technologies = technologies
.filter(({ dom }) => dom && dom.constructor === Object) .filter(({ dom }) => dom && dom.constructor === Object)
.map(({ name, dom }) => ({ name, dom })) .map(({ name, dom }) => ({ name, dom }))
.reduce((technologies, { name, dom }) => {
return [
...(await inject('js/dom.js', 'dom', {
technologies: _technologies.filter(({ dom }) =>
Object.values(dom)
.flat()
.some(({ properties }) => properties)
),
})),
..._technologies.reduce((technologies, { name, dom }) => {
const toScalar = (value) => const toScalar = (value) =>
typeof value === 'string' || typeof value === 'number' ? value : !!value typeof value === 'string' || typeof value === 'number' ? value : !!value
@ -58,7 +71,7 @@ function getDom(technologies) {
return return
} }
dom[selector].forEach(({ exists, text, properties, attributes }) => { dom[selector].forEach(({ exists, text, attributes }) => {
nodes.forEach((node) => { nodes.forEach((node) => {
if (exists) { if (exists) {
technologies.push({ technologies.push({
@ -80,23 +93,6 @@ function getDom(technologies) {
} }
} }
if (properties) {
Object.keys(properties).forEach((property) => {
if (Object.prototype.hasOwnProperty.call(node, property)) {
const value = node[property]
if (typeof value !== 'undefined') {
technologies.push({
name,
selector,
property,
value: toScalar(value),
})
}
}
})
}
if (attributes) { if (attributes) {
Object.keys(attributes).forEach((attribute) => { Object.keys(attributes).forEach((attribute) => {
if (node.hasAttribute(attribute)) { if (node.hasAttribute(attribute)) {
@ -116,7 +112,8 @@ function getDom(technologies) {
}) })
return technologies return technologies
}, []) }, []),
]
} }
const Content = { const Content = {
@ -353,7 +350,7 @@ const Content = {
const url = location.href const url = location.href
const js = await getJs(technologies) const js = await getJs(technologies)
const dom = getDom(technologies) const dom = await getDom(technologies)
await Promise.all([ await Promise.all([
Content.driver('analyzeJs', [url, js, requires]), Content.driver('analyzeJs', [url, js, requires]),

@ -0,0 +1,67 @@
/* eslint-env browser */
;(function () {
try {
const onMessage = ({ data }) => {
if (!data.wappalyzer || !data.wappalyzer.technologies) {
return
}
const { technologies } = data.wappalyzer
const toScalar = (value) =>
typeof value === 'string' || typeof value === 'number' ? value : !!value
removeEventListener('message', onMessage)
postMessage({
wappalyzer: {
dom: technologies.reduce((technologies, { name, dom }) => {
Object.keys(dom).forEach((selector) => {
let nodes = []
try {
nodes = document.querySelectorAll(selector)
} catch (error) {
// Continue
}
if (!nodes.length) {
return
}
nodes.forEach((node) => {
dom[selector].forEach(({ properties }) => {
if (properties) {
Object.keys(properties).forEach((property) => {
if (
Object.prototype.hasOwnProperty.call(node, property)
) {
const value = node[property]
if (typeof value !== 'undefined') {
technologies.push({
name,
selector,
property,
value: toScalar(value),
})
}
}
})
}
})
})
})
return technologies
}, []),
},
})
}
addEventListener('message', onMessage)
} catch (e) {
// Fail quietly
}
})()

@ -60,7 +60,8 @@
} }
], ],
"web_accessible_resources": [ "web_accessible_resources": [
"js/inject.js" "js/js.js",
"js/dom.js"
], ],
"options_ui": { "options_ui": {
"page": "html/options.html", "page": "html/options.html",

@ -2751,16 +2751,14 @@
"azuredns-cloud\\.net" "azuredns-cloud\\.net"
] ]
}, },
"xhr": {
"x-ms-gateway-requestid": "",
"x-ms-client-request-id": "",
"x-ms-correlation-request-id": ""
},
"headers": { "headers": {
"azure-regionname": "", "azure-regionname": "",
"azure-sitename": "", "azure-sitename": "",
"azure-slotname": "", "azure-slotname": "",
"azure-version": "", "azure-version": "",
"x-ms-gateway-requestid": "",
"x-ms-client-request-id": "",
"x-ms-correlation-request-id": "",
"server": "^Windows-Azure" "server": "^Windows-Azure"
}, },
"icon": "azure.svg", "icon": "azure.svg",