6 """ |
6 """ |
7 Module implementing the <a href="http://www.virustotal.com">VirusTotal</a> |
7 Module implementing the <a href="http://www.virustotal.com">VirusTotal</a> |
8 API class. |
8 API class. |
9 """ |
9 """ |
10 |
10 |
|
11 import contextlib |
11 import json |
12 import json |
12 |
13 |
13 from PyQt6.QtCore import pyqtSignal, QObject, QUrl, QUrlQuery, QByteArray |
14 from PyQt6.QtCore import pyqtSignal, QObject, QUrl, QUrlQuery, QByteArray |
14 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply |
15 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply |
15 |
16 |
167 import WebBrowser.WebBrowserWindow |
168 import WebBrowser.WebBrowserWindow |
168 nam = ( |
169 nam = ( |
169 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
170 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
170 ) |
171 ) |
171 reply = nam.post(request, params) |
172 reply = nam.post(request, params) |
172 reply.finished.connect(self.__submitUrlFinished) |
173 reply.finished.connect(lambda: self.__submitUrlFinished(reply)) |
173 self.__replies.append(reply) |
174 self.__replies.append(reply) |
174 |
175 |
175 def __submitUrlFinished(self, reply): |
176 def __submitUrlFinished(self, reply): |
176 """ |
177 """ |
177 Private slot to determine the result of the URL scan submission. |
178 Private slot to determine the result of the URL scan submission. |
214 import WebBrowser.WebBrowserWindow |
215 import WebBrowser.WebBrowserWindow |
215 nam = ( |
216 nam = ( |
216 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
217 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
217 ) |
218 ) |
218 reply = nam.post(request, params) |
219 reply = nam.post(request, params) |
219 reply.finished.connect(self.__getUrlScanReportUrlFinished) |
220 reply.finished.connect( |
|
221 lambda: self.__getUrlScanReportUrlFinished(reply)) |
220 self.__replies.append(reply) |
222 self.__replies.append(reply) |
221 |
223 |
222 def __getUrlScanReportUrlFinished(self, reply): |
224 def __getUrlScanReportUrlFinished(self, reply): |
223 """ |
225 """ |
224 Private slot to determine the result of the URL scan report URL. |
226 Private slot to determine the result of the URL scan report URL. |
250 import WebBrowser.WebBrowserWindow |
252 import WebBrowser.WebBrowserWindow |
251 nam = ( |
253 nam = ( |
252 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
254 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
253 ) |
255 ) |
254 reply = nam.post(request, params) |
256 reply = nam.post(request, params) |
255 reply.finished.connect(self.__getFileScanReportUrlFinished) |
257 reply.finished.connect( |
|
258 lambda: self.__getFileScanReportUrlFinished(reply)) |
256 self.__replies.append(reply) |
259 self.__replies.append(reply) |
257 |
260 |
258 def __getFileScanReportUrlFinished(self, reply): |
261 def __getFileScanReportUrlFinished(self, reply): |
259 """ |
262 """ |
260 Private slot to determine the result of the file scan report URL |
263 Private slot to determine the result of the file scan report URL |
291 import WebBrowser.WebBrowserWindow |
294 import WebBrowser.WebBrowserWindow |
292 nam = ( |
295 nam = ( |
293 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
296 WebBrowser.WebBrowserWindow.WebBrowserWindow.networkManager() |
294 ) |
297 ) |
295 reply = nam.get(request) |
298 reply = nam.get(request) |
296 reply.finished.connect(self.__getIpAddressReportFinished) |
299 reply.finished.connect( |
|
300 lambda: self.__getIpAddressReportFinished(reply)) |
297 self.__replies.append(reply) |
301 self.__replies.append(reply) |
298 |
302 |
299 def __getIpAddressReportFinished(self, reply): |
303 def __getIpAddressReportFinished(self, reply): |
300 """ |
304 """ |
301 Private slot to process the IP address report data. |
305 Private slot to process the IP address report data. |
363 Private slot to process the IP address report data. |
367 Private slot to process the IP address report data. |
364 |
368 |
365 @param reply reference to the network reply |
369 @param reply reference to the network reply |
366 @type QNetworkReply |
370 @type QNetworkReply |
367 """ |
371 """ |
|
372 categoriesMapping = { |
|
373 "bitdefender": ("BitDefender category",), |
|
374 "sophos": ("sophos category", "Sophos category"), |
|
375 "valkyrie": ("Comodo Valkyrie Verdict category",), |
|
376 "alpha": ("alphaMountain.ai category",), |
|
377 "forcepoint": ("Forcepoint ThreatSeeker category",), |
|
378 } |
368 if reply.error() == QNetworkReply.NetworkError.NoError: |
379 if reply.error() == QNetworkReply.NetworkError.NoError: |
369 result = json.loads(str(reply.readAll(), "utf-8")) |
380 result = json.loads(str(reply.readAll(), "utf-8")) |
370 if result["response_code"] == 0: |
381 if result["response_code"] == 0: |
371 EricMessageBox.information( |
382 EricMessageBox.information( |
372 None, |
383 None, |
386 urls = [] |
397 urls = [] |
387 try: |
398 try: |
388 subdomains = result["subdomains"] |
399 subdomains = result["subdomains"] |
389 except KeyError: |
400 except KeyError: |
390 subdomains = [] |
401 subdomains = [] |
391 try: |
402 categories = {} |
392 bdCategory = result["BitDefender category"] |
403 for key, vtCategories in categoriesMapping.items(): |
393 except KeyError: |
404 for vtCategory in vtCategories: |
394 bdCategory = self.tr("not available") |
405 with contextlib.suppress(KeyError): |
395 try: |
406 categories[key] = result[vtCategory] |
396 tmCategory = result["TrendMicro category"] |
407 break |
397 except KeyError: |
408 else: |
398 tmCategory = self.tr("not available") |
409 categories[key] = "--" |
399 try: |
|
400 wtsCategory = result["Websense ThreatSeeker category"] |
|
401 except KeyError: |
|
402 wtsCategory = self.tr("not available") |
|
403 try: |
410 try: |
404 whois = result["whois"] |
411 whois = result["whois"] |
405 except KeyError: |
412 except KeyError: |
406 whois = "" |
413 whois = "" |
|
414 # TODO: add "Webutation domain info" with subdict |
|
415 # "Adult content" (yes/no) |
|
416 # "Safety score" (0-100, integer) |
|
417 # "Verdict" (string) |
407 |
418 |
408 from .VirusTotalDomainReportDialog import ( |
419 from .VirusTotalDomainReportDialog import ( |
409 VirusTotalDomainReportDialog |
420 VirusTotalDomainReportDialog |
410 ) |
421 ) |
411 self.__domainReportDlg = VirusTotalDomainReportDialog( |
422 self.__domainReportDlg = VirusTotalDomainReportDialog( |
412 self.__lastDomain, resolutions, urls, subdomains, |
423 self.__lastDomain, resolutions, urls, subdomains, |
413 bdCategory, tmCategory, wtsCategory, whois) |
424 categories, whois) |
414 self.__domainReportDlg.show() |
425 self.__domainReportDlg.show() |
415 self.__replies.remove(reply) |
426 self.__replies.remove(reply) |
416 reply.deleteLater() |
427 reply.deleteLater() |
417 |
428 |
418 def close(self): |
429 def close(self): |