Skip to content

Commit

Permalink
Merge pull request #4 from 2000me/queued-scans
Browse files Browse the repository at this point in the history
Queued scans
  • Loading branch information
2000me committed Feb 2, 2019
2 parents fc7a9b9 + 9909a28 commit c990739
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 29 deletions.
22 changes: 22 additions & 0 deletions _locales/en/messages.json
@@ -0,0 +1,22 @@
{
"extensionName": {
"message": "VirusTotal Scan"
},
"extensionDescription": {
"message": "Scan URL with VirusTotal"
},
"notifyQueuedAndPolling": {
"message": "VirusTotal Scan queued.\nPolling every $POLL_INTERVAL_SECONDS$ seconds for the results...",
"placeholders": {
"POLL_INTERVAL_SECONDS": {
"content": "$1"
}
}
},
"notifyStillQueuedStoppedPolling": {
"message": "VirusTotal Scan still queued. Stopped polling for the results.\nPlease select VirusTotal Scan again in a minute or later."
},
"notifyUnexpectedResponse": {
"message": "Received unexpected response. Please retry."
}
}
125 changes: 99 additions & 26 deletions b.js
@@ -1,33 +1,107 @@
function dl(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var responseJSON = JSON.parse(this.responseText);
var permalink = responseJSON.permalink;
if (permalink.match(/^https:\/\/www.virustotal.com\/([a-z]{2}\/)?url\/[0-9a-f]{64}\/analysis\/[0-9]{10}\/$/)) {
browser.windows.create({
type: "detached_panel",
url: permalink
});
} else {
browser.notifications.create({
"type": "basic",
"title": "VirusTotal",
"message": "unexpected permalink"
});
}
}
'use strict';

class ResponseError extends Error {
constructor(response) {
super(response.status);
this.name = this.constructor.name;
this.response = response;
}
};

function notifyUsingBasicNotification(msg) {
console.log('vtscan: ' + msg);
browser.notifications.clear(NOTIFIDATION_ID)
browser.notifications.create(
NOTIFIDATION_ID,
{
'type': 'basic',
'title': browser.i18n.getMessage('extensionName'),
'message': msg
}
);
};

function notifyResponseError(error) {
var msg;
if (error.response.status == 204) {
msg = browser.i18n.getMessage('notifyStillQueuedStoppedPolling');
} else {
msg = browser.i18n.getMessage('notifyUnexpectedResponse');
};
notifyUsingBasicNotification(msg);
};

function ok(response) {
if (response.status == 200) {
return Promise.resolve(response);
} else {
return Promise.reject(new ResponseError(response));
};
xhttp.open("GET", url, true);
xhttp.send();
};

function json(response) {
return response.json();
};

function pollReport(responseJson, reportUrl, i) {
if (typeof responseJson['positives'] === 'undefined') {
if (i == 1) {
notifyUsingBasicNotification(
browser.i18n.getMessage(
'notifyQueuedAndPolling',
POLL_INTERVAL_SECONDS
)
)
}
if (i <= MAX_POLLS) {
setTimeout(() => {
fetch(reportUrl)
.then(ok)
.then(json)
.then(responseJson => pollReport(responseJson, reportUrl, ++i))
.catch(error => notifyResponseError(error))
}, POLL_INTERVAL_MILLISECONDS);
} else {
notifyUsingBasicNotification(
browser.i18n.getMessage('notifyStillQueuedStoppedPolling')
);
}
} else {
var id = responseJson.scan_id.substring(0, 64);
if (id.match(/^[0-9a-f]{64}$/)) {
browser.windows.create({
url: DETECTION_URL_PREFIX + id + DETECTION_URL_SUFFIX
});
} else {
notifyUsingBasicNotification(
browser.i18n.getMessage('notifyUnexpectedResponse')
)
}
}
}

var urlPrefix = "https://www.virustotal.com/vtapi/v2/url/report?" +
"apikey=4771394c63f176c44ecbb9a14398041adc349096c072e72158ddf88be13ba164&scan=1&resource=";
function scan(scanUrl, reportUrl) {
fetch(scanUrl)
.then(ok)
.then(json)
.then(responseJson => pollReport(responseJson, reportUrl, 1))
.catch(error => notifyResponseError(error));
};

const API_KEY = '4771394c63f176c44ecbb9a14398041adc349096c072e72158ddf88be13ba164';
const API_REPORT_URL = 'https://www.virustotal.com/vtapi/v2/url/report';
const DETECTION_URL_PREFIX = 'https://www.virustotal.com/#/url/';
const DETECTION_URL_SUFFIX = '/detection';
const MAX_POLLS = 4;
const NOTIFIDATION_ID = 'vtscan';
const POLL_INTERVAL_SECONDS = 5;
const POLL_INTERVAL_MILLISECONDS = POLL_INTERVAL_SECONDS * 1000;
const SCAN_URL_PREFIX = API_REPORT_URL + '?apikey=' + API_KEY + '&scan=1&resource=';
const REPORT_URL_PREFIX = API_REPORT_URL + '?apikey=' + API_KEY + '&resource=';

browser.contextMenus.create({
id: "vtscan@gmx.de",
title: "VirusTotal Scan",
title: browser.i18n.getMessage('extensionName'),
contexts: ["link"],
"icons": {
"16": "i.svg"
Expand All @@ -36,7 +110,6 @@ browser.contextMenus.create({

browser.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "vtscan@gmx.de") {
dl(urlPrefix + info.linkUrl);
scan(SCAN_URL_PREFIX + info.linkUrl, REPORT_URL_PREFIX + info.linkUrl);
}
});

8 changes: 5 additions & 3 deletions manifest.json
Expand Up @@ -3,16 +3,18 @@
"background": {
"page": "b.html"
},
"description": "Scan URL with VirusTotal",
"default_locale": "en",
"description": "__MSG_extensionDescription__",
"homepage_url": "https://www.github.com/2000me/vtscan",
"icons": {
"16": "i.svg"
},
"manifest_version": 2,
"name": "VirusTotal Scan",
"name": "__MSG_extensionName__",
"permissions": [
"contextMenus",
"notifications",
"https://www.virustotal.com/*"
],
"version": "0.5.4"
"version": "0.6.0"
}

0 comments on commit c990739

Please sign in to comment.