2 |
2 |
3 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> |
3 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> |
4 # |
4 # |
5 |
5 |
6 """ |
6 """ |
7 Module implementing the <a href="http://www.virustotal.com">VirusTotal</a> API class. |
7 Module implementing the <a href="http://www.virustotal.com">VirusTotal</a> |
|
8 API class. |
8 """ |
9 """ |
9 |
10 |
10 import json |
11 import json |
11 |
12 |
12 from PyQt4.QtCore import QObject, QUrl, QByteArray, pyqtSignal |
13 from PyQt4.QtCore import QObject, QUrl, QByteArray, pyqtSignal |
13 from PyQt4.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager |
14 from PyQt4.QtNetwork import QNetworkRequest, QNetworkReply, \ |
|
15 QNetworkAccessManager |
14 |
16 |
15 import Preferences |
17 import Preferences |
16 |
18 |
17 |
19 |
18 class VirusTotalAPI(QObject): |
20 class VirusTotalAPI(QObject): |
19 """ |
21 """ |
20 Class implementing the <a href="http://www.virustotal.com">VirusTotal</a> API. |
22 Class implementing the <a href="http://www.virustotal.com">VirusTotal</a> |
21 |
23 API. |
22 @signal checkServiceKeyFinished(bool, str) emitted after the service key check |
24 |
23 has been performed. It gives a flag indicating validity (boolean) and |
25 @signal checkServiceKeyFinished(bool, str) emitted after the service key |
24 an error message in case of a network error (string). |
26 check has been performed. It gives a flag indicating validity |
|
27 (boolean) and an error message in case of a network error (string). |
25 @signal submitUrlError(str) emitted with the error string, if the URL scan |
28 @signal submitUrlError(str) emitted with the error string, if the URL scan |
26 submission returned an error. |
29 submission returned an error. |
27 @signal urlScanReport(str) emitted with the URL of the URL scan report page |
30 @signal urlScanReport(str) emitted with the URL of the URL scan report page |
28 @signal fileScanReport(str) emitted with the URL of the file scan report page |
31 @signal fileScanReport(str) emitted with the URL of the file scan report |
|
32 page |
29 """ |
33 """ |
30 checkServiceKeyFinished = pyqtSignal(bool, str) |
34 checkServiceKeyFinished = pyqtSignal(bool, str) |
31 submitUrlError = pyqtSignal(str) |
35 submitUrlError = pyqtSignal(str) |
32 urlScanReport = pyqtSignal(str) |
36 urlScanReport = pyqtSignal(str) |
33 fileScanReport = pyqtSignal(str) |
37 fileScanReport = pyqtSignal(str) |
42 |
46 |
43 GetFileReportPattern = "{0}://www.virustotal.com/api/get_file_report.json" |
47 GetFileReportPattern = "{0}://www.virustotal.com/api/get_file_report.json" |
44 ScanUrlPattern = "{0}://www.virustotal.com/api/scan_url.json" |
48 ScanUrlPattern = "{0}://www.virustotal.com/api/scan_url.json" |
45 GetUrlReportPattern = "{0}://www.virustotal.com/api/get_url_report.json" |
49 GetUrlReportPattern = "{0}://www.virustotal.com/api/get_url_report.json" |
46 |
50 |
47 ReportUrlScanPagePattern = "http://www.virustotal.com/url-scan/report.html?id={0}" |
51 ReportUrlScanPagePattern = \ |
48 ReportFileScanPagePattern = "http://www.virustotal.com/file-scan/report.html?id={0}" |
52 "http://www.virustotal.com/url-scan/report.html?id={0}" |
|
53 ReportFileScanPagePattern = \ |
|
54 "http://www.virustotal.com/file-scan/report.html?id={0}" |
49 |
55 |
50 SearchUrl = "http://www.virustotal.com/search.html" |
56 SearchUrl = "http://www.virustotal.com/search.html" |
51 |
57 |
52 def __init__(self, parent=None): |
58 def __init__(self, parent=None): |
53 """ |
59 """ |
133 @param url url to be scanned (QUrl) |
139 @param url url to be scanned (QUrl) |
134 """ |
140 """ |
135 request = QNetworkRequest(QUrl(self.ScanUrlUrl)) |
141 request = QNetworkRequest(QUrl(self.ScanUrlUrl)) |
136 request.setHeader(QNetworkRequest.ContentTypeHeader, |
142 request.setHeader(QNetworkRequest.ContentTypeHeader, |
137 "application/x-www-form-urlencoded") |
143 "application/x-www-form-urlencoded") |
138 params = QByteArray( |
144 params = QByteArray("key={0}&url=".format( |
139 "key={0}&url=".format(Preferences.getHelp("VirusTotalServiceKey")))\ |
145 Preferences.getHelp("VirusTotalServiceKey")))\ |
140 .append(QUrl.toPercentEncoding(url.toString())) |
146 .append(QUrl.toPercentEncoding(url.toString())) |
141 |
147 |
142 import Helpviewer.HelpWindow |
148 import Helpviewer.HelpWindow |
143 nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager() |
149 nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager() |
144 reply = nam.post(request, params) |
150 reply = nam.post(request, params) |
180 reply.finished.connect(self.__getFileScanReportUrlFinished) |
186 reply.finished.connect(self.__getFileScanReportUrlFinished) |
181 self.__replies.append(reply) |
187 self.__replies.append(reply) |
182 |
188 |
183 def __getFileScanReportUrlFinished(self): |
189 def __getFileScanReportUrlFinished(self): |
184 """ |
190 """ |
185 Private slot to determine the result of the file scan report URL request. |
191 Private slot to determine the result of the file scan report URL |
|
192 request. |
186 """ |
193 """ |
187 reply = self.sender() |
194 reply = self.sender() |
188 if reply.error() == QNetworkReply.NoError: |
195 if reply.error() == QNetworkReply.NoError: |
189 result = json.loads(str(reply.readAll(), "utf-8")) |
196 result = json.loads(str(reply.readAll(), "utf-8")) |
190 if "file-report" in result: |
197 if "file-report" in result: |
191 self.fileScanReport.emit( |
198 self.fileScanReport.emit( |
192 self.ReportFileScanPagePattern.format(result["file-report"])) |
199 self.ReportFileScanPagePattern.format( |
|
200 result["file-report"])) |
193 self.__replies.remove(reply) |
201 self.__replies.remove(reply) |
194 |
202 |
195 @classmethod |
203 @classmethod |
196 def getSearchRequestData(cls, term): |
204 def getSearchRequestData(cls, term): |
197 """ |
205 """ |