Add CSV export

main
Elbert Alias 3 years ago
parent 3f8ee7506b
commit eab96894cb

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Type de société" },
"attributeCompanyFounded": { "message": "Création de l'entreprise" },
"attributeKeywords": { "message": "Mots clés" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "Enregistrement SPF" },
"attributeDns_dmarc": { "message": "Enregistrement DMARC" },
"attributeSchemaOrgTypes": { "message": "types schema.org" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "会社種別" },
"attributeCompanyFounded": { "message": "会社創立日" },
"attributeKeywords": { "message": "キーワード" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPFレコード" },
"attributeDns_dmarc": { "message": "DMARCレコード" },
"attributeSchemaOrgTypes": { "message": "schema.orgタイプ" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "회사 종류" },
"attributeCompanyFounded": { "message": "회사 상장" },
"attributeKeywords": { "message": "키워드" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF 레코드" },
"attributeDns_dmarc": { "message": "DMARC 레코드" },
"attributeSchemaOrgTypes": { "message": "schema.org 타입" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Bedrijfstype" },
"attributeCompanyFounded": { "message": "Oprichting van het bedrijf" },
"attributeKeywords": { "message": "Trefwoorden" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF-registratie" },
"attributeDns_dmarc": { "message": "DMARC-registratie" },
"attributeSchemaOrgTypes": { "message": "Typen schema.org" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -91,6 +91,7 @@
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"attributeEmployees": { "message": "Employees" },
"attributeDns_spf": { "message": "SPF record" },
"attributeDns_dmarc": { "message": "DMARC record" },
"attributeSchemaOrgTypes": { "message": "schema.org types" },

@ -391,6 +391,16 @@ small {
display: none;
}
.plus-download {
background: var(--color-secondary);
padding: 1rem 1.5rem 0 1.5rem;
text-align: right;
}
.plus-download--hidden {
display: none;
}
.plus-error {
margin: 1.5rem;
}

@ -154,6 +154,20 @@
</div>
<div class="tab-item tab-item--hidden">
<div class="plus-download plus-download--hidden">
<div class="plus-download__button button">
<span class="button__link">
<svg class="button__icon button__icon--left" viewBox="0 0 24 24">
<path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>
<span class="button__text">
Download CSV
</span>
</span>
</div>
</div>
<div class="plus-error plus-error--hidden">
<div class="plus-error__message">
</div>
@ -180,7 +194,7 @@
<div class="message__button button">
<a class="button__link" href="https://www.wappalyzer.com/plus/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer">
<span class="button__text" data-i18n="plusButton"></span>
<span class="button__text" data-i18n="plusButton">&nbsp;</span>
<svg class="button__icon button__icon--right" viewBox="0 0 24 24">
<path fill="currentColor" d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" />

@ -179,6 +179,13 @@ const Driver = {
}
},
/**
* Get all categories
*/
getCategories() {
return Wappalyzer.categories
},
/**
* Perform a HTTP POST request
* @param {String} url
@ -780,11 +787,17 @@ const Driver = {
* Get the detected technologies for the current tab
*/
async getDetections() {
const [{ id, url }] = await promisify(chrome.tabs, 'query', {
const tab = await promisify(chrome.tabs, 'query', {
active: true,
currentWindow: true,
})
if (!tab) {
return
}
const [{ id, url }] = tab
if (await Driver.isDisabledDomain(url)) {
await Driver.setIcon(url, [])

@ -41,6 +41,54 @@ const footers = [
},
]
const attributeKeys = [
'phone',
'skype',
'whatsapp',
'email',
'verifiedEmail',
'safeEmail',
'twitter',
'facebook',
'instagram',
'github',
'tiktok',
'youtube',
'pinterest',
'linkedin',
'owler',
'title',
'description',
'copyright',
'copyrightYear',
'responsive',
'schemaOrgTypes',
'certInfo.subjectOrg',
'certInfo.subjectCountry',
'certInfo.subjectState',
'certInfo.subjectLocality',
'certInfo.issuer',
'certInfo.protocol',
'certInfo.validTo',
'dns.spf',
'dns.dmarc',
'https',
'trackerGoogleAnalytics',
'trackerGoogleAdSense',
'trackerMedianet',
'trackerFacebook',
'trackerOptimizely',
'companyName',
'inferredCompanyName',
'industry',
'about',
'locations',
'companySize',
'companyType',
'companyFounded',
'employees',
]
function setDisabledDomain(enabled) {
const el = {
headerSwitchEnabled: document.querySelector('.header__switch--enabled'),
@ -56,6 +104,30 @@ function setDisabledDomain(enabled) {
}
}
function csvEscape(value = '') {
if (Array.isArray(value)) {
value = value
.flat()
.slice(0, 10)
.map((value) => csvEscape(value.replace(/ ; /g, ' : ')))
.join(' ; ')
}
if (typeof value === 'string') {
return value.replace(/\n/g, ' ').replace(/"/g, '""').trim()
}
if (typeof value === 'boolean') {
return String(value).toUpperCase()
}
if (value === null) {
return ''
}
return String(value).replace(/"/g, '""')
}
const Popup = {
/**
* Initialise popup
@ -472,6 +544,10 @@ const Popup = {
empty: document.querySelector('.plus-empty'),
crawl: document.querySelector('.plus-crawl'),
error: document.querySelector('.plus-error'),
download: document.querySelector('.plus-download'),
downloadLink: document.querySelector(
'.plus-download__button .button__link'
),
errorMessage: document.querySelector('.plus-error__message'),
configure: document.querySelector('.plus-configure'),
credits: document.querySelector('.credits'),
@ -494,6 +570,7 @@ const Popup = {
}
el.panels.classList.add('panels--hidden')
el.download.classList.add('plus-download--hidden')
el.empty.classList.add('plus-empty--hidden')
el.crawl.classList.add('plus-crawl--hidden')
el.error.classList.add('plus-error--hidden')
@ -502,6 +579,24 @@ const Popup = {
el.panels.removeChild(el.panels.lastElementChild)
}
let hostname = ''
let www = false
let https = false
try {
let protocol = ''
;({ hostname, protocol } = new URL(url))
www = hostname.startsWith('www')
https = protocol === 'https:'
hostname = hostname.replace(/^www\./, '').replace(/\./g, '-')
} catch (error) {
// Continue
}
try {
const response = await fetch(
`https://api.wappalyzer.com/v2/plus/${encodeURIComponent(url)}`,
@ -549,6 +644,45 @@ const Popup = {
return
}
const categories = await Popup.driver('getCategories')
const columns = [
'URL',
...categories.map(({ id }) =>
chrome.i18n.getMessage(`categoryName${id}`)
),
...attributeKeys.map((key) =>
chrome.i18n.getMessage(
`attribute${
key.charAt(0).toUpperCase() + key.slice(1).replace('.', '_')
}`
)
),
]
const csv = [`"${columns.join('","')}"`]
const row = [`http${https ? 's' : ''}://${www ? 'www.' : ''}${hostname}`]
const detections = await Popup.driver('getDetections')
row.push(
...categories.reduce((categories, { id }) => {
categories.push(
detections
.filter(({ categories }) =>
categories.some(({ id: _id }) => _id === id)
)
.map(({ name }) => name)
.join(' ; ')
)
return categories
}, [])
)
const attributeValues = {}
Object.keys(attributes).forEach((set) => {
const panel = document.createElement('div')
const header = document.createElement('div')
@ -579,11 +713,15 @@ const Popup = {
}`
)
attributeValues[key] = []
if (Array.isArray(value)) {
value.forEach((value) => {
const div = document.createElement('div')
if (typeof value === 'object') {
attributeValues[key].push(value.text)
const a = document.createElement('a')
a.href = value.to
@ -601,6 +739,8 @@ const Popup = {
td.appendChild(div)
}
} else if (key === 'employees') {
attributeValues[key].push(value)
const [name, title] = value.split(' -- ')
const strong = document.createElement('strong')
@ -613,17 +753,23 @@ const Popup = {
div.appendChild(span)
td.appendChild(div)
} else {
attributeValues[key].push(value)
div.textContent = value
td.appendChild(div)
}
})
} else if (key === 'companyName') {
attributeValues[key].push(value)
const strong = document.createElement('strong')
strong.textContent = value
td.appendChild(strong)
} else {
attributeValues[key].push(value)
td.textContent = value
}
@ -642,7 +788,29 @@ const Popup = {
el.panels.appendChild(panel)
})
row.push(...attributeKeys.map((key) => csvEscape(attributeValues[key])))
csv.push(`"${row.join('","')}"`)
el.downloadLink.addEventListener('click', (event) => {
event.preventDefault()
const file = URL.createObjectURL(
new Blob([csv.join('\n')], { type: 'text/csv;charset=utf-8' })
)
chrome.downloads.download({
url: file,
filename: `wappalyzer${
hostname ? `_${hostname.replace('.', '-')}` : ''
}.csv`,
})
return false
})
el.panels.classList.remove('panels--hidden')
el.download.classList.remove('plus-download--hidden')
} catch (error) {
Popup.log(error.data)

@ -73,8 +73,9 @@
"tabs",
"webRequest",
"webNavigation",
"downloads",
"http://*/*",
"https://*/*"
],
"content_security_policy": "script-src 'self'; object-src 'self'"
}
}

Loading…
Cancel
Save