From 2a20d3ff473abd3265cc2ce3e9462a757f7b1d41 Mon Sep 17 00:00:00 2001 From: NotoriousRebel Date: Wed, 14 Nov 2018 22:13:52 -0500 Subject: [PATCH] Starting the change from python2 to python3.7 --- .gitignore | 2 +- Dockerfile | 8 + README.md | 4 +- censysparser.py | 39 + discovery/DNS/Base.py | 25 +- discovery/DNS/Lib.py | 143 +-- discovery/DNS/__init__.py | 20 +- discovery/DNS/lazy.py | 2 +- discovery/DNS/win32dns.py | 56 +- discovery/__init__.py | 26 +- discovery/bingsearch.py | 10 +- discovery/censys.py | 71 ++ discovery/dnssearch.py | 24 +- discovery/exaleadsearch.py | 11 +- discovery/googleplussearch.py | 10 +- discovery/googlesearch.py | 30 +- discovery/googlesets.py | 4 +- discovery/huntersearch.py | 12 +- discovery/linkedinsearch.py | 10 +- discovery/pgpsearch.py | 10 +- discovery/shodan/client.py | 2 +- discovery/shodansearch.py | 10 +- discovery/yandexsearch.py | 12 +- lib/graphs.py | 1558 ++++++++++++++++----------------- requirements.txt | 1 + stash.py | 8 +- tests/myparser_test.py | 2 +- theHarvester.py | 246 +++--- 28 files changed, 1227 insertions(+), 1129 deletions(-) create mode 100644 Dockerfile create mode 100644 censysparser.py create mode 100644 discovery/censys.py diff --git a/.gitignore b/.gitignore index 89088ad4..55b36956 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ tests/myparser.py stash.sqlite *.sqlite -.vscode \ No newline at end of file +.vscode diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..5dc1f32c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM python:2-alpine + RUN mkdir /app +RUN pip install requests +WORKDIR /app +COPY . /app +RUN chmod +x *.py + ENTRYPOINT ["/app/theHarvester.py"] +CMD ["--help"] \ No newline at end of file diff --git a/README.md b/README.md index 39cacfa6..e3774fc6 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ The sources are: * shodan: Shodan Computer search engine, will search for ports and banner of the discovered hosts (http://www.shodanhq.com/) -* hunter: Hunter search engine +* hunter: Hunter search engine (you need to add your Key in the discovery/huntersearch.py file) Active: ------- @@ -104,6 +104,8 @@ https://github.com/laramies/theHarvester Thanks: ------- +* Matthew Brown @NotoriousRebel +* Janos Zold @Jzod * John Matherly - SHODAN project * Lee Baird for suggestions and bugs reporting * Ahmed Aboul Ela - subdomain names dictionary (big and small) diff --git a/censysparser.py b/censysparser.py new file mode 100644 index 00000000..49f97dfe --- /dev/null +++ b/censysparser.py @@ -0,0 +1,39 @@ +from bs4 import BeautifulSoup +import re + +class parser: + + def __init__(self, results): + self.results = results + self.ipaddresses = [] + self.soup = BeautifulSoup(results.results,features="html.parser") + self.hostnames = [] + self.numberofpages = 0 + + def search_hostnames(self): + try: + hostnamelist = self.soup.findAll('tt') + for hostnameitem in hostnamelist: + self.hostnames.append(hostnameitem.text) + return self.hostnames + except Exception,e: + print("Error occurred: " + e) + + def search_ipaddresses(self): + try: + ipaddresslist = self.soup.findAll('a','SearchResult__title-text') + for ipaddressitem in ipaddresslist: + self.ipaddresses.append(ipaddressitem.text.strip()) + return self.ipaddresses + except Exception,e: + print("Error occurred: " + e) + + def search_numberofpages(self): + try: + items = self.soup.findAll(href=re.compile("page")) + for item in items: + if (item.text !='next'): #to filter out pagination + self.numberofpages+=1 + return self.numberofpages + except Exception,e: + print("Error occurred: " + e) diff --git a/discovery/DNS/Base.py b/discovery/DNS/Base.py index be61a796..7860f1a6 100644 --- a/discovery/DNS/Base.py +++ b/discovery/DNS/Base.py @@ -13,12 +13,11 @@ import string import types import time -import Type -import Class -import Opcode +import discovery.DNS.Type as Type +import discovery.DNS.Class as Class +import discovery.DNS.Opcode as Opcode import asyncore - class DNSError(Exception): pass @@ -33,7 +32,7 @@ def ParseResolvConf(resolv_path): try: lines = open(resolv_path).readlines() except: - print "error in path" + resolv_path + print("error in path" + resolv_path) for line in lines: line = string.strip(line) if not line or line[0] == ';' or line[0] == '#': @@ -68,7 +67,9 @@ class DnsRequest: def __init__(self, *name, **args): self.donefunc = None - self.async = None + #fix maybe? + self.asyn= False + #self.async = None #TODO FIX async is a keyword self.defaults = {} self.argparse(name, args) self.defaults = self.args @@ -172,11 +173,11 @@ def req(self, *name, **args): else: qtype = self.args['qtype'] if 'name' not in self.args: - print self.args + print(self.args) raise DNSError('nothing to lookup') qname = self.args['name'] if qtype == Type.AXFR: - print 'Query type AXFR, protocol forced to TCP' + print('Query type AXFR, protocol forced to TCP') protocol = 'tcp' # print 'QTYPE %d(%s)' % (qtype, Type.typestr(qtype)) m = Lib.Mpacker() @@ -193,7 +194,7 @@ def req(self, *name, **args): self.sendTCPRequest(server) except socket.error as reason: raise DNSError(reason) - if self.async: + if self.asyn: return None else: return self.response @@ -208,7 +209,7 @@ def sendUDPRequest(self, server): #self.s.connect((self.ns, self.port)) self.conn() self.time_start = time.time() - if not self.async: + if not self.asyn: self.s.send(self.request) self.response = self.processUDPReply() # except socket.error: @@ -216,7 +217,7 @@ def sendUDPRequest(self, server): continue break if not self.response: - if not self.async: + if not self.asyn: raise DNSError('no working nameservers found') def sendTCPRequest(self, server): @@ -253,7 +254,7 @@ def __init__(self, *name, **args): else: self.donefunc = self.showResult # self.realinit(name,args) # XXX todo - self.async = 1 + self.asyn = 1 def conn(self): import time diff --git a/discovery/DNS/Lib.py b/discovery/DNS/Lib.py index 239b035e..965d7d60 100644 --- a/discovery/DNS/Lib.py +++ b/discovery/DNS/Lib.py @@ -26,12 +26,12 @@ import string import types -import Type -import Class -import Opcode -import Status +import discovery.DNS.Type as Type +import discovery.DNS.Class as Class +import discovery.DNS.Opcode as Opcode +import discovery.DNS.Status as Status -from Base import DNSError +from discovery.DNS.Base import DNSError class UnpackError(DNSError): @@ -116,14 +116,15 @@ def addname(self, name): # The case of the first occurrence of a name is preserved. # Redundant dots are ignored. list = [] - for label in string.splitfields(name, '.'): + for label in name.split('.'): if label: if len(label) > 63: raise PackError('label too long') list.append(label) keys = [] + s = '' for i in range(len(list)): - key = string.upper(string.joinfields(list[i:], '.')) + key = str.upper((s.join(list[i:]))) keys.append(key) if key in self.index: pointer = self.index[key] @@ -142,8 +143,8 @@ def addname(self, name): if offset + len(buf) < 0x3FFF: index.append((keys[j], offset + len(buf))) else: - print 'DNS.Lib.Packer.addname:', - print 'warning: pointer too big' + print('DNS.Lib.Packer.addname:',) + print('warning: pointer too big') buf = buf + (chr(n) + label) if pointer: buf = buf + pack16bit(pointer | 0xC000) @@ -155,26 +156,26 @@ def addname(self, name): def dump(self): keys = sorted(self.index.keys()) - print '-' * 40 + print('-' * 40) for key in keys: - print '%20s %3d' % (key, self.index[key]) - print '-' * 40 + print('%20s %3d' % (key, self.index[key])) + print('-' * 40) space = 1 for i in range(0, len(self.buf) + 1, 2): if self.buf[i:i + 2] == '**': if not space: - print + print() space = 1 continue space = 0 - print '%4d' % i, + print('%4d' % i,) for c in self.buf[i:i + 2]: if ' ' < c < '\177': - print ' %c' % c, + print(' %c' % c,) else: - print '%2d' % ord(c), - print - print '-' * 40 + print('%2d' % ord(c),) + print() + print('-' * 40) # Unpacking class @@ -257,8 +258,8 @@ def testpacker(): p.addbytes('*' * 26) p.addname('') timing.finish() - print timing.milli(), "ms total for packing" - print round(timing.milli() / i, 4), 'ms per packing' + print(timing.milli(), "ms total for packing") + print(round(timing.milli() / i, 4), 'ms per packing') # p.dump() u = Unpacker(p.buf) u.getaddr() @@ -284,8 +285,8 @@ def testpacker(): u.getbytes(26), u.getname()) timing.finish() - print timing.milli(), "ms total for unpacking" - print round(timing.milli() / i, 4), 'ms per unpacking' + print(timing.milli(), "ms total for unpacking") + print(round(timing.milli() / i, 4), 'ms per unpacking') # for item in res: print item @@ -379,7 +380,7 @@ def addSOA(self, name, klass, ttl, def addTXT(self, name, klass, ttl, list): self.addRRheader(name, Type.TXT, klass, ttl) - if isinstance(list, types.StringType): + if isinstance(list, str): list = [list] for txtdata in list: self.addstring(txtdata) @@ -555,29 +556,29 @@ class Munpacker(RRunpacker, Qunpacker, Hunpacker): # These affect the unpacker's current position! def dumpM(u): - print 'HEADER:', + print('HEADER:',) (id, qr, opcode, aa, tc, rd, ra, z, rcode, qdcount, ancount, nscount, arcount) = u.getHeader() - print 'id=%d,' % id, - print 'qr=%d, opcode=%d, aa=%d, tc=%d, rd=%d, ra=%d, z=%d, rcode=%d,' \ - % (qr, opcode, aa, tc, rd, ra, z, rcode) + print('id=%d,' % id,) + print('qr=%d, opcode=%d, aa=%d, tc=%d, rd=%d, ra=%d, z=%d, rcode=%d,' \ + % (qr, opcode, aa, tc, rd, ra, z, rcode)) if tc: - print '*** response truncated! ***' + print('*** response truncated! ***') if rcode: - print '*** nonzero error code! (%d) ***' % rcode - print ' qdcount=%d, ancount=%d, nscount=%d, arcount=%d' \ - % (qdcount, ancount, nscount, arcount) + print('*** nonzero error code! (%d) ***' % rcode) + print(' qdcount=%d, ancount=%d, nscount=%d, arcount=%d' \ + % (qdcount, ancount, nscount, arcount)) for i in range(qdcount): - print 'QUESTION %d:' % i, + print('QUESTION %d:' % i,) dumpQ(u) for i in range(ancount): - print 'ANSWER %d:' % i, + print('ANSWER %d:' % i,) dumpRR(u) for i in range(nscount): - print 'AUTHORITY RECORD %d:' % i, + print('AUTHORITY RECORD %d:' % i,) dumpRR(u) for i in range(arcount): - print 'ADDITIONAL RECORD %d:' % i, + print('ADDITIONAL RECORD %d:' % i,) dumpRR(u) @@ -594,44 +595,44 @@ def __init__(self, u, args): def show(self): import time - print '; <<>> PDG.py 1.0 <<>> %s %s' % (self.args['name'], - self.args['qtype']) + print('; <<>> PDG.py 1.0 <<>> %s %s' % (self.args['name'], + self.args['qtype'])) opt = "" if self.args['rd']: opt = opt + 'recurs ' h = self.header - print ';; options: ' + opt - print ';; got answer:' - print ';; ->>HEADER<<- opcode %s, status %s, id %d' % ( - h['opcode'], h['status'], h['id']) + print(';; options: ' + opt) + print(';; got answer:') + print(';; ->>HEADER<<- opcode %s, status %s, id %d' % ( + h['opcode'], h['status'], h['id'])) flags = filter(lambda x, h=h: h[x], ('qr', 'aa', 'rd', 'ra', 'tc')) - print ';; flags: %s; Ques: %d, Ans: %d, Auth: %d, Addit: %d' % ( - string.join(flags), h['qdcount'], h['ancount'], h['nscount'], - h['arcount']) - print ';; QUESTIONS:' + print(';; flags: %s; Ques: %d, Ans: %d, Auth: %d, Addit: %d' % ( + ''.join(map(str,flags)), h['qdcount'], h['ancount'], h['nscount'], + h['arcount'])) + print(';; QUESTIONS:') for q in self.questions: - print ';; %s, type = %s, class = %s' % (q['qname'], q['qtypestr'], - q['qclassstr']) - print - print ';; ANSWERS:' + print(';; %s, type = %s, class = %s' % (q['qname'], q['qtypestr'], + q['qclassstr'])) + print() + print(';; ANSWERS:') for a in self.answers: - print '%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], - a['data']) - print - print ';; AUTHORITY RECORDS:' + print('%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], + a['data'])) + print() + print(';; AUTHORITY RECORDS:') for a in self.authority: - print '%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], - a['data']) - print - print ';; ADDITIONAL RECORDS:' + print('%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], + a['data'])) + print() + print(';; ADDITIONAL RECORDS:') for a in self.additional: - print '%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], - a['data']) - print + print('%-20s %-6s %-6s %s' % (a['name'], repr(a['ttl']), a['typename'], + a['data'])) + print() if 'elapsed' in self.args: - print ';; Total query time: %d msec' % self.args['elapsed'] - print ';; To SERVER: %s' % (self.args['server']) - print ';; WHEN: %s' % time.ctime(time.time()) + print(';; Total query time: %d msec' % self.args['elapsed']) + print(';; To SERVER: %s' % (self.args['server'])) + print(';; WHEN: %s' % time.ctime(time.time())) def storeM(self, u): (self.header['id'], self.header['qr'], self.header['opcode'], @@ -682,25 +683,25 @@ def storeRR(self, u): def dumpQ(u): qname, qtype, qclass = u.getQuestion() - print 'qname=%s, qtype=%d(%s), qclass=%d(%s)' \ + print('qname=%s, qtype=%d(%s), qclass=%d(%s)' \ % (qname, qtype, Type.typestr(qtype), - qclass, Class.classstr(qclass)) + qclass, Class.classstr(qclass))) def dumpRR(u): name, type, klass, ttl, rdlength = u.getRRheader() typename = Type.typestr(type) - print 'name=%s, type=%d(%s), class=%d(%s), ttl=%d' \ + print('name=%s, type=%d(%s), class=%d(%s), ttl=%d' \ % (name, type, typename, klass, Class.classstr(klass), - ttl) + ttl)) mname = 'get%sdata' % typename if hasattr(u, mname): - print ' formatted rdata:', getattr(u, mname)() + print(' formatted rdata:', getattr(u, mname)()) else: - print ' binary rdata:', u.getbytes(rdlength) + print(' binary rdata:', u.getbytes(rdlength)) if __name__ == "__main__": testpacker() @@ -753,10 +754,10 @@ def dumpRR(u): # added identifying header to top of each file # # Revision 1.7 2001/07/19 07:50:44 anthony -# Added SRV (RFC 2782) support. Code from Michael Ströder. +# Added SRV (RFC 2782) support. Code from Michael Str�der. # # Revision 1.6 2001/07/19 07:39:18 anthony -# 'type' -> 'rrtype' in getRRheader(). Fix from Michael Ströder. +# 'type' -> 'rrtype' in getRRheader(). Fix from Michael Str�der. # # Revision 1.5 2001/07/19 07:34:19 anthony # oops. glitch in storeRR (fixed now). diff --git a/discovery/DNS/__init__.py b/discovery/DNS/__init__.py index 670b6b6b..0b7302f1 100644 --- a/discovery/DNS/__init__.py +++ b/discovery/DNS/__init__.py @@ -11,16 +11,16 @@ __version__ = '2.3.1' -import Type -import Opcode -import Status -import Class -from Base import DnsRequest, DNSError -from Lib import DnsResult -from Base import * -from Lib import * +from discovery.DNS import Type +from discovery.DNS import Opcode +from discovery.DNS import Status +from discovery.DNS import Class +from discovery.DNS.Base import DnsRequest, DNSError +from discovery.DNS.Lib import DnsResult +from discovery.DNS.Base import * +from discovery.DNS.Lib import * Error = DNSError -from lazy import * +from discovery.DNS.lazy import * Request = DnsRequest Result = DnsResult @@ -57,4 +57,4 @@ # Revision 1.2 2001/07/19 06:57:07 anthony # cvs keywords added # -# +# \ No newline at end of file diff --git a/discovery/DNS/lazy.py b/discovery/DNS/lazy.py index 7a982cf0..a7763497 100644 --- a/discovery/DNS/lazy.py +++ b/discovery/DNS/lazy.py @@ -7,7 +7,7 @@ # # routines for lazy people. -import Base +import discovery.DNS.Base as Base import string diff --git a/discovery/DNS/win32dns.py b/discovery/DNS/win32dns.py index 609559ee..3d1674bf 100644 --- a/discovery/DNS/win32dns.py +++ b/discovery/DNS/win32dns.py @@ -19,23 +19,21 @@ License analog to the current Python license """ -import string -import re -import _winreg - +import winreg def binipdisplay(s): "convert a binary array of ip adresses to a python list" if len(s) % 4 != 0: raise EnvironmentError # well ... ol = [] - for i in range(len(s) / 4): + s = '.' + for i in range(int(len(s) / 4)): s1 = s[:4] s = s[4:] ip = [] for j in s1: ip.append(str(ord(j))) - ol.append(string.join(ip, '.')) + ol.append(s.join(ip)) return ol @@ -49,75 +47,75 @@ def stringdisplay(s): def RegistryResolve(): nameservers = [] - x = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + x = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) try: - y = _winreg.OpenKey(x, + y = winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters") except EnvironmentError: # so it isn't NT/2000/XP # windows ME, perhaps? try: # for Windows ME - y = _winreg.OpenKey(x, + y = winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Services\VxD\MSTCP") - nameserver, dummytype = _winreg.QueryValueEx(y, 'NameServer') + nameserver, dummytype = winreg.QueryValueEx(y, 'NameServer') if nameserver and not (nameserver in nameservers): nameservers.extend(stringdisplay(nameserver)) except EnvironmentError: pass return nameservers # no idea try: - nameserver = _winreg.QueryValueEx(y, "DhcpNameServer")[0].split() + nameserver = winreg.QueryValueEx(y, "DhcpNameServer")[0].split() except: - nameserver = _winreg.QueryValueEx(y, "NameServer")[0].split() + nameserver = winreg.QueryValueEx(y, "NameServer")[0].split() if nameserver: nameservers = nameserver - nameserver = _winreg.QueryValueEx(y, "NameServer")[0] - _winreg.CloseKey(y) + nameserver = winreg.QueryValueEx(y, "NameServer")[0] + winreg.CloseKey(y) try: # for win2000 - y = _winreg.OpenKey(x, + y = winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DNSRegisteredAdapters") for i in range(1000): try: - n = _winreg.EnumKey(y, i) - z = _winreg.OpenKey(y, n) - dnscount, dnscounttype = _winreg.QueryValueEx(z, + n = winreg.EnumKey(y, i) + z = winreg.OpenKey(y, n) + dnscount, dnscounttype = winreg.QueryValueEx(z, 'DNSServerAddressCount') - dnsvalues, dnsvaluestype = _winreg.QueryValueEx(z, + dnsvalues, dnsvaluestype = winreg.QueryValueEx(z, 'DNSServerAddresses') nameservers.extend(binipdisplay(dnsvalues)) - _winreg.CloseKey(z) + winreg.CloseKey(z) except EnvironmentError: break - _winreg.CloseKey(y) + winreg.CloseKey(y) except EnvironmentError: pass # try: # for whistler - y = _winreg.OpenKey(x, + y = winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces") for i in range(1000): try: - n = _winreg.EnumKey(y, i) - z = _winreg.OpenKey(y, n) + n = winreg.EnumKey(y, i) + z = winreg.OpenKey(y, n) try: - nameserver, dummytype = _winreg.QueryValueEx( + nameserver, dummytype = winreg.QueryValueEx( z, 'NameServer') if nameserver and not (nameserver in nameservers): nameservers.extend(stringdisplay(nameserver)) except EnvironmentError: pass - _winreg.CloseKey(z) + winreg.CloseKey(z) except EnvironmentError: break - _winreg.CloseKey(y) + winreg.CloseKey(y) except EnvironmentError: # print "Key Interfaces not found, just do nothing" pass # - _winreg.CloseKey(x) + winreg.CloseKey(x) return nameservers if __name__ == "__main__": - print "Name servers:", RegistryResolve() + print("Name servers:", RegistryResolve()) # # $Log: win32dns.py,v $ diff --git a/discovery/__init__.py b/discovery/__init__.py index 749d20e8..3f8ea606 100644 --- a/discovery/__init__.py +++ b/discovery/__init__.py @@ -1,23 +1,3 @@ -__all__ = ["bingsearch", - "googlesearch", - "googleplussearch", - "pgpsearch", - "linkedinsearch", - "exaleadsearch", - "yandexsearch", - "googlesets", - "dnssearch", - "shodansearch", - "jigsaw", - "twittersearch", - "dogpilesearch", - "baidusearch", - "yahoosearch", - "netcraft", - "crtsh", - "virustotal", - "threatcrowd", - "wfuzz_search", - "port_scanner", - "takeover", - "googleCSE"] +from api import WebAPI +from client import Shodan +from exception import APIError \ No newline at end of file diff --git a/discovery/bingsearch.py b/discovery/bingsearch.py index 2ef80f65..5717b9ce 100644 --- a/discovery/bingsearch.py +++ b/discovery/bingsearch.py @@ -1,5 +1,5 @@ import string -import httplib +import http.client import sys import myparser import re @@ -22,7 +22,7 @@ def __init__(self, word, limit, start): self.counter = start def do_search(self): - h = httplib.HTTP(self.server) + h = http.client.HTTP(self.server) h.putrequest('GET', "/search?q=%40" + self.word + "&count=50&first=" + str(self.counter)) h.putheader('Host', self.hostname) @@ -35,7 +35,7 @@ def do_search(self): self.totalresults += self.results def do_search_api(self): - h = httplib.HTTP(self.apiserver) + h = http.client.HTTP(self.apiserver) h.putrequest('GET', "/xml.aspx?Appid=" + self.bingApi + "&query=%40" + self.word + "&sources=web&web.count=40&web.offset=" + str(self.counter)) h.putheader('Host', "api.search.live.net") @@ -74,7 +74,7 @@ def get_allhostnames(self): def process(self, api): if api == "yes": if self.bingApi == "": - print "Please insert your API key in the discovery/bingsearch.py" + print("Please insert your API key in the discovery/bingsearch.py") sys.exit() while (self.counter < self.limit): if api == "yes": @@ -84,7 +84,7 @@ def process(self, api): self.do_search() time.sleep(1) self.counter += 50 - print "\tSearching " + str(self.counter) + " results..." + print("\tSearching " + str(self.counter) + " results...") def process_vhost(self): # Maybe it is good to use other limit for this. diff --git a/discovery/censys.py b/discovery/censys.py new file mode 100644 index 00000000..07b44980 --- /dev/null +++ b/discovery/censys.py @@ -0,0 +1,71 @@ +import httplib +import sys +import random +import requests +import censysparser + +class search_censys: + + def __init__(self, word): + self.word = word + self.url = "" + self.page = "" + self.results = "" + self.total_results = "" + self.server = "censys.io" + self.userAgent = ["(Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36" + ,("Mozilla/5.0 (Linux; Android 7.0; SM-G892A Build/NRD90M; wv) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Mobile Safari/537.36"), + ("Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; RM-1152) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.15254"), + "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebKit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42" + ,"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991" + ,"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36 OPR/48.0.2685.52" + ,"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" + ,"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko" + ,"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"] + + def do_search(self): + try: + headers = {'user-agent': random.choice(self.userAgent),'Accept':'*/*','Referer':self.url} + response = requests.get(self.url, headers=headers) + self.results = response.content + self.total_results += self.results + except Exception,e: + print e + + def process(self,morepage=None): + try: + if (morepage is not None): + self.page =str(morepage) + baseurl = self.url + self.url = baseurl + "&page=" + self.page + else: + self.url="https://" + self.server + "/ipv4/_search?q=" + self.word + self.do_search() + print "\tSearching Censys results.." + except Exception,e: + print("Error occurred: " + e) + + def get_hostnames(self): + try: + hostnames = censysparser.parser(self) + return hostnames.search_hostnames() + except Exception,e: + print("Error occurred: " + e) + + def get_ipaddresses(self): + try: + ips = censysparser.parser(self) + return ips.search_ipaddresses() + except Exception,e: + print("Error occurred: " + e) + + def get_totalnumberofpages(self): + try: + pages = censysparser.parser(self) + return pages.search_numberofpages() + except Exception,e: + print("Error occurred: " + e) + diff --git a/discovery/dnssearch.py b/discovery/dnssearch.py index bd3e4de5..c18053d5 100644 --- a/discovery/dnssearch.py +++ b/discovery/dnssearch.py @@ -1,5 +1,5 @@ -import IPy -import DNS +from discovery import IPy +import discovery.DNS as DNS import string import socket import sys @@ -18,7 +18,7 @@ def __init__(self, range, verbose=True): DNS.ParseResolvConf("/etc/resolv.conf") nameserver = DNS.defaults['server'][0] except: - print "Error in DNS resolvers" + print("Error in DNS resolvers") sys.exit() def run(self, host): @@ -42,7 +42,7 @@ def get_ip_list(self, ips): try: list = IPy.IP(ips) except: - print "Error in IP format, check the input and try again. (Eg. 192.168.1.0/24)" + print("Error in IP format, check the input and try again. (Eg. 192.168.1.0/24)") sys.exit() name = [] for x in list: @@ -75,12 +75,12 @@ def __init__(self, domain, dnsserver, verbose=False): res_path = os.path.join(fileDir,'lib/resolvers.txt') with open(res_path) as f: self.resolvers = f.read().splitlines() - except Exception, e: - print "Resolvers file can't be open" + except Exception as e: + print("Resolvers file can't be open") try: f = open(self.file, "r") except: - print "Error opening dns dictionary file" + print("Error opening dns dictionary file") sys.exit() self.list = f.readlines() @@ -105,10 +105,10 @@ def getdns(self, domain): server=primary, aa=1).req() except Exception as e: - print e + print(e) if test.header['status'] != "NOERROR": - print "Error" + print("Error") sys.exit() self.nameserver = test.answers[0]['data'] elif self.nameserver == "local": @@ -118,7 +118,7 @@ def getdns(self, domain): def run(self, host): if self.nameserver == "": self.nameserver = self.getdns(self.domain) - print "\n\033[94m[-] Using DNS server: " + self.nameserver + "\033[1;33;40m\n" + print("\n\033[94m[-] Using DNS server: " + self.nameserver + "\033[1;33;40m\n") #secure_random = random.SystemRandom() #self.nameserver = secure_random.choice(self.resolvers) @@ -144,7 +144,7 @@ def process(self): for x in self.list: host = self.run(x) if host is not None: - print " : " + host.split(":")[1] + print(" : " + host.split(":")[1]) results.append(host) return results @@ -199,7 +199,7 @@ def getdns(self, domain): 0]['data'] test = DNS.Request(rootdom, qtype='NS', server=primary, aa=1).req() if test.header['status'] != "NOERROR": - print "Error" + print("Error") sys.exit() self.nameserver = test.answers[0]['data'] elif self.nameserver == "local": diff --git a/discovery/exaleadsearch.py b/discovery/exaleadsearch.py index d6a8c78d..97bd04e6 100644 --- a/discovery/exaleadsearch.py +++ b/discovery/exaleadsearch.py @@ -1,5 +1,5 @@ import string -import httplib +import http.client import sys import myparser import re @@ -7,7 +7,6 @@ class search_exalead: - def __init__(self, word, limit, start): self.word = word self.files = "pdf" @@ -20,7 +19,7 @@ def __init__(self, word, limit, start): self.counter = start def do_search(self): - h = httplib.HTTP(self.server) + h = http.client.HTTPConnection(self.server) h.putrequest('GET', "/search/web/results/?q=%40" + self.word + "&elements_per_page=50&start_index=" + str(self.counter)) h.putheader('Host', self.hostname) @@ -37,7 +36,7 @@ def do_search(self): self.totalresults += self.results def do_search_files(self, files): - h = httplib.HTTP(self.server) + h = http.client.HTTPConnection(self.server) h.putrequest( 'GET', "search/web/results/?q=" + @@ -58,7 +57,7 @@ def check_next(self): nextres = renext.findall(self.results) if nextres != []: nexty = "1" - print str(self.counter) + print(str(self.counter)) else: nexty = "0" return nexty @@ -79,7 +78,7 @@ def process(self): while self.counter <= self.limit: self.do_search() self.counter += 50 - print "\tSearching " + str(self.counter) + " results..." + print("\ tSearching " + str(self.counter) + " results...") def process_files(self, files): while self.counter < self.limit: diff --git a/discovery/googleplussearch.py b/discovery/googleplussearch.py index 94e5efd2..ee37ba69 100644 --- a/discovery/googleplussearch.py +++ b/discovery/googleplussearch.py @@ -21,13 +21,13 @@ def __init__(self, word, limit): def do_search(self): try: urly="https://" + self.server + "/search?num=100&start=" + str(self.counter) + "&hl=en&meta=&q=site%3Aplus.google.com%20intext%3A%22Works%20at%22%20" + self.word+ "%20-inurl%3Aphotos%20-inurl%3Aabout%20-inurl%3Aposts%20-inurl%3Aplusones" - except Exception, e: - print e + except Exception as e: + print(e) try: headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:34.0) Gecko/20100101 Firefox/34.0'} r=requests.get(urly,headers=headers) - except Exception,e: - print e + except Exception as e: + print(e) self.results = r.content self.totalresults += self.results @@ -39,4 +39,4 @@ def process(self): while (self.counter < self.limit): self.do_search() self.counter += 100 - print "\tSearching " + str(self.counter) + " results.." + print("\tSearching " + str(self.counter) + " results..") diff --git a/discovery/googlesearch.py b/discovery/googlesearch.py index 4dddcf92..23c24c66 100644 --- a/discovery/googlesearch.py +++ b/discovery/googlesearch.py @@ -32,25 +32,25 @@ def __init__(self, word, limit, start): def do_search(self): try: #do normal scraping urly="http://" + self.server + "/search?num=" + self.quantity + "&start=" + str(self.counter) + "&hl=en&meta=&q=%40\"" + self.word + "\"" - except Exception, e: - print e + except Exception as e: + print(e) try: params = {'User-Agent': random.choice(self.userAgent)} #select random user agent r=requests.get(urly,params= params) - except Exception,e: - print e + except Exception as e: + print(e) self.results = r.content self.totalresults += self.results def do_search_profiles(self): try: urly="http://" + self.server + "/search?num=" + self.quantity + "&start=" + str(self.counter) + "&hl=en&meta=&q=site:www.google.com%20intitle:\"Google%20Profile\"%20\"Companies%20I%27ve%20worked%20for\"%20\"at%20" + self.word + "\"" - except Exception, e: - print e + except Exception as e: + print(e) try: r=requests.get(urly) - except Exception,e: - print e + except Exception as e: + print (e) self.results = r.content #'&hl=en&meta=&q=site:www.google.com%20intitle:"Google%20Profile"%20"Companies%20I%27ve%20worked%20for"%20"at%20' + self.word + '"') self.totalresults += self.results @@ -77,17 +77,17 @@ def process(self,google_dorking): self.do_search() #more = self.check_next() time.sleep(1) - print "\tSearching " + str(self.counter) + " results..." + print("\tSearching " + str(self.counter) + " results...") self.counter += 100 else: #google dorking is true self.counter = 0 #reset counter - print '\n' - print "[-] Searching with Google Dorks: " + print('\n') + print("[-] Searching with Google Dorks: ") while self.counter <= self.limit and self.counter <= 200: # only 200 dorks in list self.googledork() #call google dorking method if user wanted it! # more = self.check_next() - time.sleep(.1) - print "\tSearching " + str(self.counter) + " results..." + time.sleep(.5) + print("\tSearching " + str(self.counter) + " results...") self.counter += 100 def process_profiles(self): @@ -95,7 +95,7 @@ def process_profiles(self): self.do_search_profiles() time.sleep(0.15) self.counter += 100 - print "\tSearching " + str(self.counter) + " results..." + print("\tSearching " + str(self.counter) + " results...") def append_dorks(self): try: # wrap in try-except incase filepaths are messed up @@ -150,4 +150,4 @@ def send_dork(self, start, end): # helper function to minimize code reusability self.results = req.content self.totalresults += self.results except: - continue + continue \ No newline at end of file diff --git a/discovery/googlesets.py b/discovery/googlesets.py index 575b7330..06d656a5 100644 --- a/discovery/googlesets.py +++ b/discovery/googlesets.py @@ -1,5 +1,5 @@ import string -import httplib +import http.client import sys import myparser import re @@ -24,7 +24,7 @@ def __init__(self, list): self.set = self.set + "&q" + str(id) + "=" + str(x) def do_search(self): - h = httplib.HTTP(self.server) + h = http.client.HTTPConnection(self.server) h.putrequest('GET', "/sets?hl=en&" + self.set) h.putheader('Host', self.hostname) h.putheader('User-agent', self.userAgent) diff --git a/discovery/huntersearch.py b/discovery/huntersearch.py index fdfa1c8a..95729392 100644 --- a/discovery/huntersearch.py +++ b/discovery/huntersearch.py @@ -7,28 +7,28 @@ class search_hunter: def __init__(self, word, limit, start): self.word = word - self.limit = limit + self.limit = 100 self.start = start self.key = "" if self.key == "": - print "You need an API key in order to use the Hunter search engine. You can get one here: https://hunter.io" + print("You need an API key in order to use the Hunter search engine. You can get one here: https://hunter.io") sys.exit() self.results = "" self.totalresults = "" self.counter = start - self.database = "https://api.hunter.io/v2/domain-search?domain=" + word + "&api_key=" + self.key + self.database = "https://api.hunter.io/v2/domain-search?domain=" + word + "&api_key=" + self.key +"&limit=" + str(self.limit) def do_search(self): try: r = requests.get(self.database) - except Exception,e: - print e + except Exception as e: + print(e) self.results = r.content self.totalresults += self.results def process(self): self.do_search() #only need to do it once - print '\tDone Searching Results' + print('\tDone Searching Results') def get_emails(self): rawres = myparser.parser(self.totalresults, self.word) diff --git a/discovery/linkedinsearch.py b/discovery/linkedinsearch.py index 673f5cac..8d799d02 100644 --- a/discovery/linkedinsearch.py +++ b/discovery/linkedinsearch.py @@ -20,12 +20,12 @@ def __init__(self, word, limit): def do_search(self): try: urly="http://"+ self.server + "/search?num=100&start=" + str(self.counter) + "&hl=en&meta=&q=site%3Alinkedin.com/in%20" + self.word - except Exception, e: - print e + except Exception as e: + print(e) try: r=requests.get(urly) - except Exception,e: - print e + except Exception as e: + print(e) self.results = r.content self.totalresults += self.results @@ -37,4 +37,4 @@ def process(self): while (self.counter < self.limit): self.do_search() self.counter += 100 - print "\tSearching " + str(self.counter) + " results.." + print("\tSearching " + str(self.counter) + " results..") diff --git a/discovery/pgpsearch.py b/discovery/pgpsearch.py index a18bfd47..6235250a 100644 --- a/discovery/pgpsearch.py +++ b/discovery/pgpsearch.py @@ -1,5 +1,5 @@ import string -import httplib +import http.client import sys import myparser @@ -15,18 +15,18 @@ def __init__(self, word): self.userAgent = "(Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6" def process(self): - print "\tSearching PGP results..." + print("\tSearching PGP results...") try: - h = httplib.HTTP(self.server) + h = http.client.HTTP(self.server) h.putrequest('GET', "/pks/lookup?search=" + self.word + "&op=index") h.putheader('Host', self.hostname) h.putheader('User-agent', self.userAgent) h.endheaders() returncode, returnmsg, headers = h.getreply() self.results = h.getfile().read() - except Exception, e: - print "Unable to connect to PGP server: ",str(e) + except Exception as e: + print("Unable to connect to PGP server: ",str(e)) pass def get_emails(self): diff --git a/discovery/shodan/client.py b/discovery/shodan/client.py index de2cd781..23d5dc15 100644 --- a/discovery/shodan/client.py +++ b/discovery/shodan/client.py @@ -30,7 +30,7 @@ # Define a basestring type if necessary for Python3 compatibility try: - basestring + str except NameError: basestring = str diff --git a/discovery/shodansearch.py b/discovery/shodansearch.py index b861942f..f5fcdd07 100644 --- a/discovery/shodansearch.py +++ b/discovery/shodansearch.py @@ -1,4 +1,4 @@ -from shodan import Shodan +from discovery.shodan import Shodan import sys import json @@ -9,7 +9,7 @@ def __init__(self, host): self.host = host self.key = "oCiMsgM6rQWqiTvPxFHYcExlZgg7wvTt" if self.key == "": - print "You need an API key in order to use SHODAN database. You can get one here: http://www.shodanhq.com/" + print("You need an API key in order to use SHODAN database. You can get one here: http://www.shodanhq.com/") sys.exit() self.api = Shodan(self.key) @@ -17,7 +17,7 @@ def run(self): try: host = self.api.host(self.host) return host['data'] - except Exception, e: - print "SHODAN empty reply or error in the call" - print e + except Exception as e: + print("SHODAN empty reply or error in the call") + print(e) return "error" diff --git a/discovery/yandexsearch.py b/discovery/yandexsearch.py index 0415d3a7..26eb8585 100644 --- a/discovery/yandexsearch.py +++ b/discovery/yandexsearch.py @@ -1,5 +1,5 @@ import string -import httplib +import http.client import sys import myparser import re @@ -19,7 +19,7 @@ def __init__(self, word, limit, start): self.counter = start def do_search(self): - h = httplib.HTTP(self.server) + h = http.client.HTTPConnection(self.server) h.putrequest('GET', "/search?text=%40" + self.word + "&numdoc=50&lr=" + str(self.counter)) h.putheader('Host', self.hostname) @@ -28,10 +28,10 @@ def do_search(self): returncode, returnmsg, headers = h.getreply() self.results = h.getfile().read() self.totalresults += self.results - print self.results + print(self.results) def do_search_files(self, files): # TODO - h = httplib.HTTP(self.server) + h = http.client.HTTPConnection(self.server) h.putrequest('GET', "/search?text=%40" + self.word + "&numdoc=50&lr=" + str(self.counter)) h.putheader('Host', self.hostname) @@ -46,7 +46,7 @@ def check_next(self): nextres = renext.findall(self.results) if nextres != []: nexty = "1" - print str(self.counter) + print(str(self.counter)) else: nexty = "0" return nexty @@ -67,7 +67,7 @@ def process(self): while self.counter <= self.limit: self.do_search() self.counter += 50 - print "Searching " + str(self.counter) + " results..." + print("Searching " + str(self.counter) + " results...") def process_files(self, files): while self.counter < self.limit: diff --git a/lib/graphs.py b/lib/graphs.py index 82c45492..12ff68f0 100644 --- a/lib/graphs.py +++ b/lib/graphs.py @@ -1,779 +1,779 @@ -""" - +-------------------------------------------------------------------+ - | H T M L - G R A P H S (v4.8) | - | | - | Copyright Gerd Tentler www.gerd-tentler.de/tools | - | Created: Sep. 17, 2002 Last modified: Feb. 13, 2010 | - +-------------------------------------------------------------------+ - | This program may be used and hosted free of charge by anyone for | - | personal purpose as long as this copyright notice remains intact. | - | | - | Obtain permission before selling the code for this program or | - | hosting this software on a commercial website or redistributing | - | this software over the Internet or in any other medium. In all | - | cases copyright must remain intact. | - +-------------------------------------------------------------------+ - -===================================================================================================== - Example: - - import graphs - graph = graphs.BarGraph('hBar') - graph.values = [234, 125, 289, 147, 190] - print graph.create() - - Returns HTML code -===================================================================================================== -""" - -import re -import math - - -class BarGraph: - - """creates horizontal and vertical bar graphs, progress bars and faders""" - - def __init__(self, type=''): -#------------------------------------------------------------------------- -# Configuration -#------------------------------------------------------------------------- - # graph type: "hBar", "vBar", "pBar", or "fader" - self.type = type and type or 'hBar' - self.values = [] # graph data: list - - # graph background color: string - self.graphBGColor = '' - # graph border: string (CSS-spec: "size style color"; doesn't work with - # NN4) - self.graphBorder = '' - # graph padding: integer (pixels) - self.graphPadding = 0 - - # titles: array or string with comma-separated values - self.titles = [] - self.titleColor = 'black' # title font color: string - # title background color: string - self.titleBGColor = '#C0E0FF' - # title border: string (CSS specification) - self.titleBorder = '2px groove white' - # title font family: string (CSS specification) - self.titleFont = 'Arial, Helvetica' - # title font size: integer (pixels) - self.titleSize = 12 - # title text align: "left", "center", or "right" - self.titleAlign = 'center' - # title padding: integer (pixels) - self.titlePadding = 2 - - # label names: list or string with comma-separated values - self.labels = [] - self.labelColor = 'black' # label font color: string - # label background color: string - self.labelBGColor = '#C0E0FF' - # label border: string (CSS-spec: "size style color"; doesn't work with - # NN4) - self.labelBorder = '2px groove white' - # label font family: string (CSS-spec) - self.labelFont = 'Arial, Helvetica' - # label font size: integer (pixels) - self.labelSize = 12 - # label text align: "left", "center", or "right" - self.labelAlign = 'center' - # additional space between labels: integer (pixels) - self.labelSpace = 0 - - self.barWidth = 20 # bar width: integer (pixels) - # bar length ratio: float (from 0.1 to 2.9) - self.barLength = 1.0 - # bar colors OR bar images: list or string with comma-separated values - self.barColors = [] - # bar background color: string - self.barBGColor = '' - # bar border: string (CSS-spec: "size style color"; doesn't work with - # NN4) - self.barBorder = '2px outset white' - # bar level colors: ascending list (bLevel, bColor[,...]); draw bars >= - # bLevel with bColor - self.barLevelColors = [] - - # show values: 0 = % only, 1 = abs. and %, 2 = abs. only, 3 = none - self.showValues = 0 - # base value: integer or float (only hBar and vBar) - self.baseValue = 0 - - # abs. values font color: string - self.absValuesColor = 'black' - # abs. values background color: string - self.absValuesBGColor = '#C0E0FF' - # abs. values border: string (CSS-spec: "size style color"; doesn't - # work with NN4) - self.absValuesBorder = '2px groove white' - # abs. values font family: string (CSS-spec) - self.absValuesFont = 'Arial, Helvetica' - # abs. values font size: integer (pixels) - self.absValuesSize = 12 - # abs. values prefix: string (e.g. "$") - self.absValuesPrefix = '' - # abs. values suffix: string (e.g. " kg") - self.absValuesSuffix = '' - - # perc. values font color: string - self.percValuesColor = 'black' - # perc. values font family: string (CSS-spec) - self.percValuesFont = 'Arial, Helvetica' - # perc. values font size: integer (pixels) - self.percValuesSize = 12 - # perc. values number of decimals: integer - self.percValuesDecimals = 0 - - self.charts = 1 # number of charts: integer - - # hBar/vBar only: - # legend items: list or string with comma-separated values - self.legend = [] - self.legendColor = 'black' # legend font color: string - # legend background color: string - self.legendBGColor = '#F0F0F0' - # legend border: string (CSS-spec: "size style color"; doesn't work - # with NN4) - self.legendBorder = '2px groove white' - # legend font family: string (CSS-spec) - self.legendFont = 'Arial, Helvetica' - # legend font size: integer (pixels) - self.legendSize = 12 - # legend vertical align: "top", "center", "bottom" - self.legendAlign = 'top' - - # debug mode: 0 = off, 1 = on; just views some extra information - self.debug = 0 -#------------------------------------------------------------------------- - - # default bar colors; only used if barColors isn't set - __colors = ( - '#0000FF', - '#FF0000', - '#00E000', - '#A0A0FF', - '#FFA0A0', - '#00A000') - - # error messages - __err_type = 'ERROR: Type must be "hBar", "vBar", "pBar", or "fader"' - - # CSS names (don't change) - __cssGRAPH = '' - __cssBAR = '' - __cssBARBG = '' - __cssTITLE = '' - __cssLABEL = '' - __cssLABELBG = '' - __cssLEGEND = '' - __cssLEGENDBG = '' - __cssABSVALUES = '' - __cssPERCVALUES = '' - - # search pattern for images - __img_pattern = re.compile(r'\.(jpg|jpeg|jpe|gif|png)') - - def set_styles(self): - """set graph styles""" - if self.graphBGColor: - self.__cssGRAPH += 'background-color:' + self.graphBGColor + ';' - if self.graphBorder: - self.__cssGRAPH += 'border:' + self.graphBorder + ';' - if self.barBorder: - self.__cssBAR += 'border:' + self.barBorder + ';' - if self.barBGColor: - self.__cssBARBG += 'background-color:' + self.barBGColor + ';' - if self.titleColor: - self.__cssTITLE += 'color:' + self.titleColor + ';' - if self.titleBGColor: - self.__cssTITLE += 'background-color:' + self.titleBGColor + ';' - if self.titleBorder: - self.__cssTITLE += 'border:' + self.titleBorder + ';' - if self.titleFont: - self.__cssTITLE += 'font-family:' + self.titleFont + ';' - if self.titleAlign: - self.__cssTITLE += 'text-align:' + self.titleAlign + ';' - if self.titleSize: - self.__cssTITLE += 'font-size:' + str(self.titleSize) + 'px;' - if self.titleBGColor: - self.__cssTITLE += 'background-color:' + self.titleBGColor + ';' - if self.titlePadding: - self.__cssTITLE += 'padding:' + str(self.titlePadding) + 'px;' - if self.labelColor: - self.__cssLABEL += 'color:' + self.labelColor + ';' - if self.labelBGColor: - self.__cssLABEL += 'background-color:' + self.labelBGColor + ';' - if self.labelBorder: - self.__cssLABEL += 'border:' + self.labelBorder + ';' - if self.labelFont: - self.__cssLABEL += 'font-family:' + self.labelFont + ';' - if self.labelSize: - self.__cssLABEL += 'font-size:' + str(self.labelSize) + 'px;' - if self.labelAlign: - self.__cssLABEL += 'text-align:' + self.labelAlign + ';' - if self.labelBGColor: - self.__cssLABELBG += 'background-color:' + self.labelBGColor + ';' - if self.legendColor: - self.__cssLEGEND += 'color:' + self.legendColor + ';' - if self.legendFont: - self.__cssLEGEND += 'font-family:' + self.legendFont + ';' - if self.legendSize: - self.__cssLEGEND += 'font-size:' + str(self.legendSize) + 'px;' - if self.legendBGColor: - self.__cssLEGENDBG += 'background-color:' + \ - self.legendBGColor + ';' - if self.legendBorder: - self.__cssLEGENDBG += 'border:' + self.legendBorder + ';' - if self.absValuesColor: - self.__cssABSVALUES += 'color:' + self.absValuesColor + ';' - if self.absValuesBGColor: - self.__cssABSVALUES += 'background-color:' + \ - self.absValuesBGColor + ';' - if self.absValuesBorder: - self.__cssABSVALUES += 'border:' + self.absValuesBorder + ';' - if self.absValuesFont: - self.__cssABSVALUES += 'font-family:' + self.absValuesFont + ';' - if self.absValuesSize: - self.__cssABSVALUES += 'font-size:' + \ - str(self.absValuesSize) + 'px;' - if self.percValuesColor: - self.__cssPERCVALUES += 'color:' + self.percValuesColor + ';' - if self.percValuesFont: - self.__cssPERCVALUES += 'font-family:' + self.percValuesFont + ';' - if self.percValuesSize: - self.__cssPERCVALUES += 'font-size:' + \ - str(self.percValuesSize) + 'px;' - - def level_color(self, value, color): - """return bar color for each level""" - if self.barLevelColors: - for i in range(0, len(self.barLevelColors), 2): - try: - if (self.barLevelColors[i] > 0 and value >= self.barLevelColors[i]) or \ - (self.barLevelColors[i] < 0 and value <= self.barLevelColors[i]): - color = self.barLevelColors[i + 1] - except IndexError: - pass - return color - - def build_bar(self, value, width, height, color): - """return a single bar""" - title = self.absValuesPrefix + str(value) + self.absValuesSuffix - bg = self.__img_pattern.search(color) and 'background' or 'bgcolor' - bar = '' - bar += '
' or '>' - bar += '
' - bar += '
' - return bar - - def build_fader(self, value, width, height, x, color): - """return a single fader""" - fader = '' - x -= int(round(width / 2)) - if x > 0: - fader += '' - fader += '' - fader += '
' + self.build_bar(value, width, height, color) + '
' - return fader - - def build_value(self, val, max_dec, sum=0, align=''): - """return a single bar/fader value""" - val = _number_format(val, max_dec) - if sum: - sum = _number_format(sum, max_dec) - value = '' - legend += '' - i = 0 - - for color in barColors: - if len(self.legend) >= i + 1: - text = hasattr( - self.legend[i], - 'strip') and self.legend[i].strip() or str(self.legend[i]) - else: - text = '' - legend += '' - legend += '' - legend += '' - legend += '' - i += 1 - - legend += '
' + \ - self.build_bar( - '', - self.barWidth, - self.barWidth, - color) + '' + text + '
' - return legend - - def build_hTitle(self, titleLabel, titleValue, titleBar): - """return horizontal titles""" - title = '' - title += '' + titleLabel + '' - if titleValue != '': - title += '' + titleValue + '' - title += '' + titleBar + '' - title += '' - return title - - def create_hBar(self, value, percent, mPerc, mPerc_neg, - max_neg, mul, valSpace, bColor, border, spacer, spacer_neg): - """return a single horizontal bar with label and values (abs./perc.)""" - bar = '' - - if percent < 0: - percent *= -1 - bar += '' - else: - if max_neg: - bar += '' - if percent: - bar += '' - else: - bar += '' - bar += '' - - bar += '
' - if self.showValues < 2: - bar += '' + \ - str(_number_format(percent, self.percValuesDecimals)) + \ - '%' - bar += ' ' - bar += self.build_bar(value, int(round(percent * mul)), - self.barWidth, bColor) - bar += '' - bar += '
' - bar += self.build_bar(value, int(round(percent * mul)), - self.barWidth, bColor) - bar += '' - if self.showValues < 2: - bar += ' ' + \ - str(_number_format(percent, self.percValuesDecimals)) + '%' - bar += ' 
' - return bar - - def create_vBar(self, value, percent, mPerc, mPerc_neg, - max_neg, mul, valSpace, bColor, border, spacer, spacer_neg): - """return a single vertical bar with label and values (abs./perc.)""" - bar = '' - - if percent < 0: - percent *= -1 - bar += '' - bar += '' - else: - bar += '' - if percent: - bar += '' - else: - bar += '' - if max_neg: - bar += '' - - bar += '
' - bar += self.build_bar(value, self.barWidth, - int(round(percent * mul)), bColor) - bar += '
' - bar += (self.showValues < 2) and '' + \ - str(_number_format(percent, self.percValuesDecimals)) + \ - '%' or ' ' - bar += '' - if self.showValues < 2: - bar += str(_number_format(percent, self.percValuesDecimals)) + \ - '%' - bar += '
' - bar += self.build_bar(value, self.barWidth, - int(round(percent * mul)), bColor) - bar += '
' - bar += '
' - return bar - - def create(self): - """create a complete bar graph (horizontal, vertical, progress, or fader)""" - self.type = self.type.lower() - d = self.values - t = hasattr( - self.titles, - 'split') and self.titles.split( - ',') or self.titles - r = hasattr( - self.labels, - 'split') and self.labels.split( - ',') or self.labels - drc = hasattr( - self.barColors, - 'split') and self.barColors.split( - ',') or self.barColors - val = [] - bc = [] - if self.barLength < 0.1: - self.barLength = 0.1 - elif self.barLength > 2.9: - self.barLength = 2.9 - labels = (len(d) > len(r)) and len(d) or len(r) - - if self.type == 'pbar' or self.type == 'fader': - if not self.barBGColor: - self.barBGColor = self.labelBGColor - if self.labelBGColor == self.barBGColor and len(t) == 0: - self.labelBGColor = '' - self.labelBorder = '' - - self.set_styles() - - graph = '' - graph += '' - - if self.legend and self.type != 'pbar' and self.type != 'fader': - graph += '
' - if self.type == 'vbar': - graph += '' - graph += '
' - - if self.charts > 1: - divide = math.ceil(labels / self.charts) - graph += '' - if self.showValues < 2: - graph += '' - graph += '' - if self.labelSpace and i < len(v) - 1: - graph += '' - lcnt += 1 - - else: - graph += '' - - graph += '
' - else: - divide = 0 - - sum = 0 - max = 0 - max_neg = 0 - max_dec = 0 - ccnt = 0 - lcnt = 0 - chart = 0 - - for i in range(labels): - if divide and i and not i % divide: - lcnt = 0 - chart += 1 - - try: - drv = len(d[i]) and [e for e in d[i]] or [d[i]] - except: - drv = [d[i]] - - j = 0 - dec = 0 - if len(val) <= chart: - val.append([]) - - for v in drv: - s = str(v) - if s.find('.') != -1: - dec = len(s[s.find('.') + 1:]) - if dec > max_dec: - max_dec = dec - - if len(val[chart]) <= lcnt: - val[chart].append([]) - val[chart][lcnt].append(v) - - if v != 0: - v -= self.baseValue - - if v > max: - max = v - elif v < max_neg: - max_neg = v - - if v < 0: - v *= -1 - sum += v - - if len(bc) <= j: - if ccnt >= len(self.__colors): - ccnt = 0 - if len(drc) <= j or len(drc[j]) < 3: - bc.append(self.__colors[ccnt]) - ccnt += 1 - else: - bc.append(drc[j].strip()) - - j += 1 - - lcnt += 1 - - border = int(self.barBorder[0]) - mPerc = sum and int(round(max * 100.0 / sum)) or 0 - if self.type == 'pbar' or self.type == 'fader': - mul = 2 - else: - mul = mPerc and 100.0 / mPerc or 1 - mul *= self.barLength - - if self.showValues < 2: - if self.type == 'hbar': - valSpace = (self.percValuesDecimals * (self.percValuesSize / 1.6)) + \ - (self.percValuesSize * 3.2) - else: - valSpace = self.percValuesSize * 1.2 - else: - valSpace = self.percValuesSize - spacer = maxSize = int(round(mPerc * mul + valSpace + border * 2)) - - if max_neg: - mPerc_neg = sum and int(round(-max_neg * 100.0 / sum)) or 0 - if mPerc_neg > mPerc and self.type != 'pbar' and self.type != 'fader': - mul = 100.0 / mPerc_neg * self.barLength - spacer_neg = int(round(mPerc_neg * mul + valSpace + border * 2)) - maxSize += spacer_neg - else: - mPerc_neg = spacer_neg = 0 - - titleLabel = '' - titleValue = '' - titleBar = '' - - if len(t) > 0: - titleLabel = (t[0] == '') and ' ' or t[0] - - if self.showValues == 1 or self.showValues == 2: - titleValue = (t[1] == '') and ' ' or t[1] - titleBar = (t[2] == '') and ' ' or t[2] - else: - titleBar = (t[1] == '') and ' ' or t[1] - - chart = 0 - lcnt = 0 - - for v in val: - graph += '' - - if self.type == 'hbar': - if len(t) > 0: - graph += self.build_hTitle(titleLabel, - titleValue, titleBar) - - for i in range(len(v)): - label = ( - lcnt < len(r)) and r[lcnt].strip() or str(lcnt + 1) - rowspan = len(v[i]) - graph += '' - - for j in range(len(v[i])): - value = v[i][j] and v[i][j] - self.baseValue or 0 - percent = sum and value * 100.0 / sum or 0 - value = _number_format(v[i][j], max_dec) - bColor = self.level_color(v[i][j], bc[j]) - - if self.showValues == 1 or self.showValues == 2: - graph += self.build_value(v[i] - [j], max_dec, 0, 'right') - - graph += '' - graph += self.create_hBar( - value, percent, mPerc, mPerc_neg, - max_neg, mul, valSpace, bColor, border, spacer, spacer_neg) - graph += '' - if j < len(v[i]) - 1: - graph += '' - - if self.labelSpace and i < len(v) - 1: - graph += '' - lcnt += 1 - - elif self.type == 'vbar': - graph += '' - - if titleBar != '': - titleBar = titleBar.replace('-', '-
') - graph += '' - - for i in range(len(v)): - for j in range(len(v[i])): - value = v[i][j] and v[i][j] - self.baseValue or 0 - percent = sum and value * 100.0 / sum or 0 - value = _number_format(v[i][j], max_dec) - bColor = self.level_color(v[i][j], bc[j]) - - graph += '' - graph += self.create_vBar( - value, percent, mPerc, mPerc_neg, - max_neg, mul, valSpace, bColor, border, spacer, spacer_neg) - graph += '' - - if self.labelSpace: - graph += '' - - if self.showValues == 1 or self.showValues == 2: - graph += '' - if titleValue != '': - graph += '' - - for i in range(len(v)): - for j in range(len(v[i])): - graph += self.build_value(v[i][j], max_dec) - if self.labelSpace: - graph += '' - - graph += '' - if titleLabel != '': - graph += '' - - for i in range(len(v)): - label = ( - lcnt < len(r)) and r[lcnt].strip() or str(lcnt + 1) - colspan = len(v[i]) - graph += '' - if self.labelSpace: - graph += '' - lcnt += 1 - - graph += '' - - elif self.type == 'pbar' or self.type == 'fader': - if len(t) > 0: - graph += self.build_hTitle(titleLabel, - titleValue, titleBar) - - for i in range(len(v)): - try: - m = (len(v[i]) > 1) and True or False - except: - m = False - - if m or not i: - label = ( - lcnt < len(r)) and r[lcnt].strip() or str(i + 1) - graph += '' - - if len(r): - graph += '' - - try: - sum = v[i][1] and v[i][1] or v[-1][0] - except: - sum = v[-1][0] - - percent = sum and v[i][0] * 100.0 / sum or 0 - value = _number_format(v[i][0], max_dec) - - if self.showValues == 1 or self.showValues == 2: - graph += self.build_value(v[i] - [0], max_dec, sum, 'right') - - graph += '' - - self.barColors = ( - len(drc) >= i + 1) and drc[i].strip() or self.__colors[0] - bColor = self.level_color(v[i][0], self.barColors) - graph += '
1) and ' rowspan=' + str(rowspan) or '') + \ - '>' - graph += ' ' + label + ' 
' + titleBar + '
' + titleValue + '
' + titleLabel + ' 1) and ' colspan=' + str(colspan) or '') + \ - '>' - graph += ' ' + label + ' 
' - graph += ' ' + label + ' 
' - graph += '
' - if self.type == 'fader': - graph += self.build_fader( - value, int(round(self.barWidth / 2)), - self.barWidth, int(round(percent * mul)), bColor) - else: - graph += self.build_bar(value, - int(round(percent * mul)), self.barWidth, bColor) - graph += '
 ' + \ - str(_number_format(percent, self.percValuesDecimals)) + \ - '%
' + self.__err_type + '
' - - if chart < self.charts - 1 and len(val[chart + 1]): - graph += '
' - - chart += 1 - - if self.charts > 1: - graph += '
' - - if self.legend and self.type != 'pbar' and self.type != 'fader': - graph += ' ' - graph += self.build_legend(bc) - graph += '' - - if self.debug: - graph += "
sum=%s max=%s max_neg=%s max_dec=%s " % (sum, - max, max_neg, max_dec) - graph += "mPerc=%s mPerc_neg=%s mul=%s valSpace=%s" % (mPerc, - mPerc_neg, mul, valSpace) - - graph += '' - return graph - - -def _number_format(val, dec): - """return float with dec decimals; if dec is 0, return integer""" - return dec and ('%.' + str(dec) + 'f') % val or int(round(val)) - -if __name__ == '__main__': - print __doc__ +""" + +-------------------------------------------------------------------+ + | H T M L - G R A P H S (v4.8) | + | | + | Copyright Gerd Tentler www.gerd-tentler.de/tools | + | Created: Sep. 17, 2002 Last modified: Feb. 13, 2010 | + +-------------------------------------------------------------------+ + | This program may be used and hosted free of charge by anyone for | + | personal purpose as long as this copyright notice remains intact. | + | | + | Obtain permission before selling the code for this program or | + | hosting this software on a commercial website or redistributing | + | this software over the Internet or in any other medium. In all | + | cases copyright must remain intact. | + +-------------------------------------------------------------------+ + +===================================================================================================== + Example: + + import graphs + graph = graphs.BarGraph('hBar') + graph.values = [234, 125, 289, 147, 190] + print graph.create() + + Returns HTML code +===================================================================================================== +""" + +import re +import math + + +class BarGraph: + + """creates horizontal and vertical bar graphs, progress bars and faders""" + + def __init__(self, type=''): +#------------------------------------------------------------------------- +# Configuration +#------------------------------------------------------------------------- + # graph type: "hBar", "vBar", "pBar", or "fader" + self.type = type and type or 'hBar' + self.values = [] # graph data: list + + # graph background color: string + self.graphBGColor = '' + # graph border: string (CSS-spec: "size style color"; doesn't work with + # NN4) + self.graphBorder = '' + # graph padding: integer (pixels) + self.graphPadding = 0 + + # titles: array or string with comma-separated values + self.titles = [] + self.titleColor = 'black' # title font color: string + # title background color: string + self.titleBGColor = '#C0E0FF' + # title border: string (CSS specification) + self.titleBorder = '2px groove white' + # title font family: string (CSS specification) + self.titleFont = 'Arial, Helvetica' + # title font size: integer (pixels) + self.titleSize = 12 + # title text align: "left", "center", or "right" + self.titleAlign = 'center' + # title padding: integer (pixels) + self.titlePadding = 2 + + # label names: list or string with comma-separated values + self.labels = [] + self.labelColor = 'black' # label font color: string + # label background color: string + self.labelBGColor = '#C0E0FF' + # label border: string (CSS-spec: "size style color"; doesn't work with + # NN4) + self.labelBorder = '2px groove white' + # label font family: string (CSS-spec) + self.labelFont = 'Arial, Helvetica' + # label font size: integer (pixels) + self.labelSize = 12 + # label text align: "left", "center", or "right" + self.labelAlign = 'center' + # additional space between labels: integer (pixels) + self.labelSpace = 0 + + self.barWidth = 20 # bar width: integer (pixels) + # bar length ratio: float (from 0.1 to 2.9) + self.barLength = 1.0 + # bar colors OR bar images: list or string with comma-separated values + self.barColors = [] + # bar background color: string + self.barBGColor = '' + # bar border: string (CSS-spec: "size style color"; doesn't work with + # NN4) + self.barBorder = '2px outset white' + # bar level colors: ascending list (bLevel, bColor[,...]); draw bars >= + # bLevel with bColor + self.barLevelColors = [] + + # show values: 0 = % only, 1 = abs. and %, 2 = abs. only, 3 = none + self.showValues = 0 + # base value: integer or float (only hBar and vBar) + self.baseValue = 0 + + # abs. values font color: string + self.absValuesColor = 'black' + # abs. values background color: string + self.absValuesBGColor = '#C0E0FF' + # abs. values border: string (CSS-spec: "size style color"; doesn't + # work with NN4) + self.absValuesBorder = '2px groove white' + # abs. values font family: string (CSS-spec) + self.absValuesFont = 'Arial, Helvetica' + # abs. values font size: integer (pixels) + self.absValuesSize = 12 + # abs. values prefix: string (e.g. "$") + self.absValuesPrefix = '' + # abs. values suffix: string (e.g. " kg") + self.absValuesSuffix = '' + + # perc. values font color: string + self.percValuesColor = 'black' + # perc. values font family: string (CSS-spec) + self.percValuesFont = 'Arial, Helvetica' + # perc. values font size: integer (pixels) + self.percValuesSize = 12 + # perc. values number of decimals: integer + self.percValuesDecimals = 0 + + self.charts = 1 # number of charts: integer + + # hBar/vBar only: + # legend items: list or string with comma-separated values + self.legend = [] + self.legendColor = 'black' # legend font color: string + # legend background color: string + self.legendBGColor = '#F0F0F0' + # legend border: string (CSS-spec: "size style color"; doesn't work + # with NN4) + self.legendBorder = '2px groove white' + # legend font family: string (CSS-spec) + self.legendFont = 'Arial, Helvetica' + # legend font size: integer (pixels) + self.legendSize = 12 + # legend vertical align: "top", "center", "bottom" + self.legendAlign = 'top' + + # debug mode: 0 = off, 1 = on; just views some extra information + self.debug = 0 +#------------------------------------------------------------------------- + + # default bar colors; only used if barColors isn't set + __colors = ( + '#0000FF', + '#FF0000', + '#00E000', + '#A0A0FF', + '#FFA0A0', + '#00A000') + + # error messages + __err_type = 'ERROR: Type must be "hBar", "vBar", "pBar", or "fader"' + + # CSS names (don't change) + __cssGRAPH = '' + __cssBAR = '' + __cssBARBG = '' + __cssTITLE = '' + __cssLABEL = '' + __cssLABELBG = '' + __cssLEGEND = '' + __cssLEGENDBG = '' + __cssABSVALUES = '' + __cssPERCVALUES = '' + + # search pattern for images + __img_pattern = re.compile(r'\.(jpg|jpeg|jpe|gif|png)') + + def set_styles(self): + """set graph styles""" + if self.graphBGColor: + self.__cssGRAPH += 'background-color:' + self.graphBGColor + ';' + if self.graphBorder: + self.__cssGRAPH += 'border:' + self.graphBorder + ';' + if self.barBorder: + self.__cssBAR += 'border:' + self.barBorder + ';' + if self.barBGColor: + self.__cssBARBG += 'background-color:' + self.barBGColor + ';' + if self.titleColor: + self.__cssTITLE += 'color:' + self.titleColor + ';' + if self.titleBGColor: + self.__cssTITLE += 'background-color:' + self.titleBGColor + ';' + if self.titleBorder: + self.__cssTITLE += 'border:' + self.titleBorder + ';' + if self.titleFont: + self.__cssTITLE += 'font-family:' + self.titleFont + ';' + if self.titleAlign: + self.__cssTITLE += 'text-align:' + self.titleAlign + ';' + if self.titleSize: + self.__cssTITLE += 'font-size:' + str(self.titleSize) + 'px;' + if self.titleBGColor: + self.__cssTITLE += 'background-color:' + self.titleBGColor + ';' + if self.titlePadding: + self.__cssTITLE += 'padding:' + str(self.titlePadding) + 'px;' + if self.labelColor: + self.__cssLABEL += 'color:' + self.labelColor + ';' + if self.labelBGColor: + self.__cssLABEL += 'background-color:' + self.labelBGColor + ';' + if self.labelBorder: + self.__cssLABEL += 'border:' + self.labelBorder + ';' + if self.labelFont: + self.__cssLABEL += 'font-family:' + self.labelFont + ';' + if self.labelSize: + self.__cssLABEL += 'font-size:' + str(self.labelSize) + 'px;' + if self.labelAlign: + self.__cssLABEL += 'text-align:' + self.labelAlign + ';' + if self.labelBGColor: + self.__cssLABELBG += 'background-color:' + self.labelBGColor + ';' + if self.legendColor: + self.__cssLEGEND += 'color:' + self.legendColor + ';' + if self.legendFont: + self.__cssLEGEND += 'font-family:' + self.legendFont + ';' + if self.legendSize: + self.__cssLEGEND += 'font-size:' + str(self.legendSize) + 'px;' + if self.legendBGColor: + self.__cssLEGENDBG += 'background-color:' + \ + self.legendBGColor + ';' + if self.legendBorder: + self.__cssLEGENDBG += 'border:' + self.legendBorder + ';' + if self.absValuesColor: + self.__cssABSVALUES += 'color:' + self.absValuesColor + ';' + if self.absValuesBGColor: + self.__cssABSVALUES += 'background-color:' + \ + self.absValuesBGColor + ';' + if self.absValuesBorder: + self.__cssABSVALUES += 'border:' + self.absValuesBorder + ';' + if self.absValuesFont: + self.__cssABSVALUES += 'font-family:' + self.absValuesFont + ';' + if self.absValuesSize: + self.__cssABSVALUES += 'font-size:' + \ + str(self.absValuesSize) + 'px;' + if self.percValuesColor: + self.__cssPERCVALUES += 'color:' + self.percValuesColor + ';' + if self.percValuesFont: + self.__cssPERCVALUES += 'font-family:' + self.percValuesFont + ';' + if self.percValuesSize: + self.__cssPERCVALUES += 'font-size:' + \ + str(self.percValuesSize) + 'px;' + + def level_color(self, value, color): + """return bar color for each level""" + if self.barLevelColors: + for i in range(0, len(self.barLevelColors), 2): + try: + if (self.barLevelColors[i] > 0 and value >= self.barLevelColors[i]) or \ + (self.barLevelColors[i] < 0 and value <= self.barLevelColors[i]): + color = self.barLevelColors[i + 1] + except IndexError: + pass + return color + + def build_bar(self, value, width, height, color): + """return a single bar""" + title = self.absValuesPrefix + str(value) + self.absValuesSuffix + bg = self.__img_pattern.search(color) and 'background' or 'bgcolor' + bar = '' + bar += '
' or '>' + bar += '
' + bar += '
' + return bar + + def build_fader(self, value, width, height, x, color): + """return a single fader""" + fader = '' + x -= int(round(width / 2)) + if x > 0: + fader += '' + fader += '' + fader += '
' + self.build_bar(value, width, height, color) + '
' + return fader + + def build_value(self, val, max_dec, sum=0, align=''): + """return a single bar/fader value""" + val = _number_format(val, max_dec) + if sum: + sum = _number_format(sum, max_dec) + value = '' + legend += '' + i = 0 + + for color in barColors: + if len(self.legend) >= i + 1: + text = hasattr( + self.legend[i], + 'strip') and self.legend[i].strip() or str(self.legend[i]) + else: + text = '' + legend += '' + legend += '' + legend += '' + legend += '' + i += 1 + + legend += '
' + \ + self.build_bar( + '', + self.barWidth, + self.barWidth, + color) + '' + text + '
' + return legend + + def build_hTitle(self, titleLabel, titleValue, titleBar): + """return horizontal titles""" + title = '' + title += '' + titleLabel + '' + if titleValue != '': + title += '' + titleValue + '' + title += '' + titleBar + '' + title += '' + return title + + def create_hBar(self, value, percent, mPerc, mPerc_neg, + max_neg, mul, valSpace, bColor, border, spacer, spacer_neg): + """return a single horizontal bar with label and values (abs./perc.)""" + bar = '' + + if percent < 0: + percent *= -1 + bar += '' + else: + if max_neg: + bar += '' + if percent: + bar += '' + else: + bar += '' + bar += '' + + bar += '
' + if self.showValues < 2: + bar += '' + \ + str(_number_format(percent, self.percValuesDecimals)) + \ + '%' + bar += ' ' + bar += self.build_bar(value, int(round(percent * mul)), + self.barWidth, bColor) + bar += '' + bar += '
' + bar += self.build_bar(value, int(round(percent * mul)), + self.barWidth, bColor) + bar += '' + if self.showValues < 2: + bar += ' ' + \ + str(_number_format(percent, self.percValuesDecimals)) + '%' + bar += ' 
' + return bar + + def create_vBar(self, value, percent, mPerc, mPerc_neg, + max_neg, mul, valSpace, bColor, border, spacer, spacer_neg): + """return a single vertical bar with label and values (abs./perc.)""" + bar = '' + + if percent < 0: + percent *= -1 + bar += '' + bar += '' + else: + bar += '' + if percent: + bar += '' + else: + bar += '' + if max_neg: + bar += '' + + bar += '
' + bar += self.build_bar(value, self.barWidth, + int(round(percent * mul)), bColor) + bar += '
' + bar += (self.showValues < 2) and '' + \ + str(_number_format(percent, self.percValuesDecimals)) + \ + '%' or ' ' + bar += '' + if self.showValues < 2: + bar += str(_number_format(percent, self.percValuesDecimals)) + \ + '%' + bar += '
' + bar += self.build_bar(value, self.barWidth, + int(round(percent * mul)), bColor) + bar += '
' + bar += '
' + return bar + + def create(self): + """create a complete bar graph (horizontal, vertical, progress, or fader)""" + self.type = self.type.lower() + d = self.values + t = hasattr( + self.titles, + 'split') and self.titles.split( + ',') or self.titles + r = hasattr( + self.labels, + 'split') and self.labels.split( + ',') or self.labels + drc = hasattr( + self.barColors, + 'split') and self.barColors.split( + ',') or self.barColors + val = [] + bc = [] + if self.barLength < 0.1: + self.barLength = 0.1 + elif self.barLength > 2.9: + self.barLength = 2.9 + labels = (len(d) > len(r)) and len(d) or len(r) + + if self.type == 'pbar' or self.type == 'fader': + if not self.barBGColor: + self.barBGColor = self.labelBGColor + if self.labelBGColor == self.barBGColor and len(t) == 0: + self.labelBGColor = '' + self.labelBorder = '' + + self.set_styles() + + graph = '' + graph += '' + + if self.legend and self.type != 'pbar' and self.type != 'fader': + graph += '
' + if self.type == 'vbar': + graph += '' + graph += '
' + + if self.charts > 1: + divide = math.ceil(labels / self.charts) + graph += '' + if self.showValues < 2: + graph += '' + graph += '' + if self.labelSpace and i < len(v) - 1: + graph += '' + lcnt += 1 + + else: + graph += '' + + graph += '
' + else: + divide = 0 + + sum = 0 + max = 0 + max_neg = 0 + max_dec = 0 + ccnt = 0 + lcnt = 0 + chart = 0 + + for i in range(labels): + if divide and i and not i % divide: + lcnt = 0 + chart += 1 + + try: + drv = len(d[i]) and [e for e in d[i]] or [d[i]] + except: + drv = [d[i]] + + j = 0 + dec = 0 + if len(val) <= chart: + val.append([]) + + for v in drv: + s = str(v) + if s.find('.') != -1: + dec = len(s[s.find('.') + 1:]) + if dec > max_dec: + max_dec = dec + + if len(val[chart]) <= lcnt: + val[chart].append([]) + val[chart][lcnt].append(v) + + if v != 0: + v -= self.baseValue + + if v > max: + max = v + elif v < max_neg: + max_neg = v + + if v < 0: + v *= -1 + sum += v + + if len(bc) <= j: + if ccnt >= len(self.__colors): + ccnt = 0 + if len(drc) <= j or len(drc[j]) < 3: + bc.append(self.__colors[ccnt]) + ccnt += 1 + else: + bc.append(drc[j].strip()) + + j += 1 + + lcnt += 1 + + border = int(self.barBorder[0]) + mPerc = sum and int(round(max * 100.0 / sum)) or 0 + if self.type == 'pbar' or self.type == 'fader': + mul = 2 + else: + mul = mPerc and 100.0 / mPerc or 1 + mul *= self.barLength + + if self.showValues < 2: + if self.type == 'hbar': + valSpace = (self.percValuesDecimals * (self.percValuesSize / 1.6)) + \ + (self.percValuesSize * 3.2) + else: + valSpace = self.percValuesSize * 1.2 + else: + valSpace = self.percValuesSize + spacer = maxSize = int(round(mPerc * mul + valSpace + border * 2)) + + if max_neg: + mPerc_neg = sum and int(round(-max_neg * 100.0 / sum)) or 0 + if mPerc_neg > mPerc and self.type != 'pbar' and self.type != 'fader': + mul = 100.0 / mPerc_neg * self.barLength + spacer_neg = int(round(mPerc_neg * mul + valSpace + border * 2)) + maxSize += spacer_neg + else: + mPerc_neg = spacer_neg = 0 + + titleLabel = '' + titleValue = '' + titleBar = '' + + if len(t) > 0: + titleLabel = (t[0] == '') and ' ' or t[0] + + if self.showValues == 1 or self.showValues == 2: + titleValue = (t[1] == '') and ' ' or t[1] + titleBar = (t[2] == '') and ' ' or t[2] + else: + titleBar = (t[1] == '') and ' ' or t[1] + + chart = 0 + lcnt = 0 + + for v in val: + graph += '' + + if self.type == 'hbar': + if len(t) > 0: + graph += self.build_hTitle(titleLabel, + titleValue, titleBar) + + for i in range(len(v)): + label = ( + lcnt < len(r)) and r[lcnt].strip() or str(lcnt + 1) + rowspan = len(v[i]) + graph += '' + + for j in range(len(v[i])): + value = v[i][j] and v[i][j] - self.baseValue or 0 + percent = sum and value * 100.0 / sum or 0 + value = _number_format(v[i][j], max_dec) + bColor = self.level_color(v[i][j], bc[j]) + + if self.showValues == 1 or self.showValues == 2: + graph += self.build_value(v[i] + [j], max_dec, 0, 'right') + + graph += '' + graph += self.create_hBar( + value, percent, mPerc, mPerc_neg, + max_neg, mul, valSpace, bColor, border, spacer, spacer_neg) + graph += '' + if j < len(v[i]) - 1: + graph += '' + + if self.labelSpace and i < len(v) - 1: + graph += '' + lcnt += 1 + + elif self.type == 'vbar': + graph += '' + + if titleBar != '': + titleBar = titleBar.replace('-', '-
') + graph += '' + + for i in range(len(v)): + for j in range(len(v[i])): + value = v[i][j] and v[i][j] - self.baseValue or 0 + percent = sum and value * 100.0 / sum or 0 + value = _number_format(v[i][j], max_dec) + bColor = self.level_color(v[i][j], bc[j]) + + graph += '' + graph += self.create_vBar( + value, percent, mPerc, mPerc_neg, + max_neg, mul, valSpace, bColor, border, spacer, spacer_neg) + graph += '' + + if self.labelSpace: + graph += '' + + if self.showValues == 1 or self.showValues == 2: + graph += '' + if titleValue != '': + graph += '' + + for i in range(len(v)): + for j in range(len(v[i])): + graph += self.build_value(v[i][j], max_dec) + if self.labelSpace: + graph += '' + + graph += '' + if titleLabel != '': + graph += '' + + for i in range(len(v)): + label = ( + lcnt < len(r)) and r[lcnt].strip() or str(lcnt + 1) + colspan = len(v[i]) + graph += '' + if self.labelSpace: + graph += '' + lcnt += 1 + + graph += '' + + elif self.type == 'pbar' or self.type == 'fader': + if len(t) > 0: + graph += self.build_hTitle(titleLabel, + titleValue, titleBar) + + for i in range(len(v)): + try: + m = (len(v[i]) > 1) and True or False + except: + m = False + + if m or not i: + label = ( + lcnt < len(r)) and r[lcnt].strip() or str(i + 1) + graph += '' + + if len(r): + graph += '' + + try: + sum = v[i][1] and v[i][1] or v[-1][0] + except: + sum = v[-1][0] + + percent = sum and v[i][0] * 100.0 / sum or 0 + value = _number_format(v[i][0], max_dec) + + if self.showValues == 1 or self.showValues == 2: + graph += self.build_value(v[i] + [0], max_dec, sum, 'right') + + graph += '' + + self.barColors = ( + len(drc) >= i + 1) and drc[i].strip() or self.__colors[0] + bColor = self.level_color(v[i][0], self.barColors) + graph += '
1) and ' rowspan=' + str(rowspan) or '') + \ + '>' + graph += ' ' + label + ' 
' + titleBar + '
' + titleValue + '
' + titleLabel + ' 1) and ' colspan=' + str(colspan) or '') + \ + '>' + graph += ' ' + label + ' 
' + graph += ' ' + label + ' 
' + graph += '
' + if self.type == 'fader': + graph += self.build_fader( + value, int(round(self.barWidth / 2)), + self.barWidth, int(round(percent * mul)), bColor) + else: + graph += self.build_bar(value, + int(round(percent * mul)), self.barWidth, bColor) + graph += '
 ' + \ + str(_number_format(percent, self.percValuesDecimals)) + \ + '%
' + self.__err_type + '
' + + if chart < self.charts - 1 and len(val[chart + 1]): + graph += '
' + + chart += 1 + + if self.charts > 1: + graph += '
' + + if self.legend and self.type != 'pbar' and self.type != 'fader': + graph += ' ' + graph += self.build_legend(bc) + graph += '' + + if self.debug: + graph += "
sum=%s max=%s max_neg=%s max_dec=%s " % (sum, + max, max_neg, max_dec) + graph += "mPerc=%s mPerc_neg=%s mul=%s valSpace=%s" % (mPerc, + mPerc_neg, mul, valSpace) + + graph += '' + return graph + + +def _number_format(val, dec): + """return float with dec decimals; if dec is 0, return integer""" + return dec and ('%.' + str(dec) + 'f') % val or int(round(val)) + +if __name__ == '__main__': + print(__doc__) diff --git a/requirements.txt b/requirements.txt index 271baf7e..260e5717 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ requests==2.18.4 +bs4==0.0.1 \ No newline at end of file diff --git a/stash.py b/stash.py index 74dd489d..64aeae64 100644 --- a/stash.py +++ b/stash.py @@ -29,8 +29,8 @@ def store(self,domain, resource,res_type,source): c.execute ('INSERT INTO results (domain,resource, type, find_date, source) VALUES (?,?,?,?,?)',(self.domain,self.resource,self.type,self.date,self.source)) conn.commit() conn.close() - except Exception, e: - print e + except Exception as e: + print(e) return def store_all(self,domain,all,res_type,source): @@ -46,6 +46,6 @@ def store_all(self,domain,all,res_type,source): c.execute ('INSERT INTO results (domain,resource, type, find_date, source) VALUES (?,?,?,?,?)',(self.domain,x,self.type,self.date,self.source)) conn.commit() conn.close() - except Exception, e: - print e + except Exception as e: + print(e) return \ No newline at end of file diff --git a/tests/myparser_test.py b/tests/myparser_test.py index b765b4bb..f76f82bf 100644 --- a/tests/myparser_test.py +++ b/tests/myparser_test.py @@ -12,7 +12,7 @@ def test_emails(self): results = '@domain.com***a@domain***banotherdomain.com***c@domain.com***d@sub.domain.com***' p = myparser.parser(results, word) emails = sorted(p.emails()) - self.assertEquals(emails, [ 'c@domain.com', 'd@sub.domain.com' ]) + self.assertEqual(emails, [ 'c@domain.com', 'd@sub.domain.com' ]) if __name__ == '__main__': unittest.main() diff --git a/theHarvester.py b/theHarvester.py index d7d4fb12..16cb4d19 100644 --- a/theHarvester.py +++ b/theHarvester.py @@ -1,10 +1,8 @@ #!/usr/bin/env python import string -import httplib import sys import os -from socket import * import re import getopt import stash @@ -13,25 +11,25 @@ try: import requests except: - print "Request library not found, please install it before proceeding\n" + print("Request library not found, please install it before proceeding\n") sys.exit() from discovery import * from lib import htmlExport from lib import hostchecker -print "\n \033[92m *******************************************************************" -print "* *" -print "* | |_| |__ ___ /\ /\__ _ _ ____ _____ ___| |_ ___ _ __ *" -print "* | __| '_ \ / _ \ / /_/ / _` | '__\ \ / / _ \/ __| __/ _ \ '__| *" -print "* | |_| | | | __/ / __ / (_| | | \ V / __/\__ \ || __/ | *" -print "* \__|_| |_|\___| \/ /_/ \__,_|_| \_/ \___||___/\__\___|_| *" -print "* *" -print "* TheHarvester Ver. 3.0.0 *" -print "* Coded by Christian Martorella *" -print "* Edge-Security Research *" -print "* cmartorella@edge-security.com *" -print "*******************************************************************\033[94m\n\n" +print("\n \033[92m *******************************************************************") +print("* *") +print("* | |_| |__ ___ /\ /\__ _ _ ____ _____ ___| |_ ___ _ __ *") +print("* | __| '_ \ / _ \ / /_/ / _` | '__\ \ / / _ \/ __| __/ _ \ '__| *") +print("* | |_| | | | __/ / __ / (_| | | \ V / __/\__ \ || __/ | *") +print("* \__|_| |_|\___| \/ /_/ \__,_|_| \_/ \___||___/\__\___|_| *") +print("* *") +print("* TheHarvester Ver. 3.0.0 *") +print("* Coded by Christian Martorella *") +print("* Edge-Security Research *") +print("* cmartorella@edge-security.com *") +print("*******************************************************************\033[94m\n\n") def usage(): @@ -41,29 +39,29 @@ def usage(): if os.path.dirname(sys.argv[0]) == os.getcwd(): comm = "./" + comm - print "Usage: theharvester options \n" - print " -d: Domain to search or company name" - print """ -b: data source: baidu, bing, bingapi, dogpile, google, googleCSE, + print("Usage: theharvester options \n") + print(" -d: Domain to search or company name") + print(""" -b: data source: baidu, bing, bingapi, dogpile, google, googleCSE, googleplus, google-profiles, linkedin, pgp, twitter, vhost, - virustotal, threatcrowd, crtsh, netcraft, yahoo, hunter, all\n""" - print " -g: use google dorking instead of normal google search" - print " -s: start in result number X (default: 0)" - print " -v: verify host name via dns resolution and search for virtual hosts" - print " -f: save the results into an HTML and XML file (both)" - print " -n: perform a DNS reverse query on all ranges discovered" - print " -c: perform a DNS brute force for the domain name" - print " -t: perform a DNS TLD expansion discovery" - print " -e: use this DNS server" - print " -p: port scan the detected hosts and check for Takeovers (80,443,22,21,8080)" - print " -l: limit the number of results to work with(bing goes from 50 to 50 results," - print " google 100 to 100, and pgp doesn't use this option)" - print " -h: use SHODAN database to query discovered hosts" - print "\nExamples:" - print " " + comm + " -d microsoft.com -l 500 -b google -h myresults.html" - print " " + comm + " -d microsoft.com -b pgp" - print " " + comm + " -d microsoft -l 200 -b linkedin" - print " " + comm + " -d microsoft.com -l 200 -g -b google" - print " " + comm + " -d apple.com -b googleCSE -l 500 -s 300\n" + virustotal, threatcrowd, crtsh, netcraft, yahoo, hunter, all\n""") + print(" -g: use google dorking instead of normal google search") + print(" -s: start in result number X (default: 0)") + print(" -v: verify host name via dns resolution and search for virtual hosts") + print(" -f: save the results into an HTML and XML file (both)") + print(" -n: perform a DNS reverse query on all ranges discovered") + print(" -c: perform a DNS brute force for the domain name") + print(" -t: perform a DNS TLD expansion discovery") + print(" -e: use this DNS server") + print(" -p: port scan the detected hosts and check for Takeovers (80,443,22,21,8080)") + print(" -l: limit the number of results to work with(bing goes from 50 to 50 results,") + print(" google 100 to 100, and pgp doesn't use this option)") + print(" -h: use SHODAN database to query discovered hosts") + print("\nExamples:") + print((" " + comm + " -d microsoft.com -l 500 -b google -h myresults.html")) + print((" " + comm + " -d microsoft.com -b pgp")) + print((" " + comm + " -d microsoft -l 200 -b linkedin")) + print((" " + comm + " -d microsoft.com -l 200 -g -b google")) + print((" " + comm + " -d apple.com -b googleCSE -l 500 -s 300\n")) def start(argv): @@ -78,7 +76,7 @@ def start(argv): try: db=stash.stash_manager() db.do_init() - except Exception, e: + except Exception as e: pass start = 0 host_ip = [] @@ -124,11 +122,11 @@ def start(argv): engines = set(arg.split(',')) supportedengines = set(["baidu","bing","crtsh","bingapi","dogpile","google","googleCSE","virustotal","threatcrowd","googleplus","google-profiles","linkedin","pgp","twitter","vhost","yahoo","netcraft","hunter","all"]) if set(engines).issubset(supportedengines): - print "found supported engines" - print "[-] Starting harvesting process for domain: " + word + "\n" + print("found supported engines") + print(("[-] Starting harvesting process for domain: " + word + "\n")) for engineitem in engines: if engineitem == "google": - print "[-] Searching in Google:" + print("[-] Searching in Google:") search = googlesearch.search_google(word, limit, start) search.process(google_dorking) all_emails = search.get_emails() @@ -137,11 +135,11 @@ def start(argv): try: db=stash.stash_manager() db.store(word,x,'host','google') - except Exception, e: - print e + except Exception as e: + print(e) if engineitem == "netcraft": - print "[-] Searching in Netcraft:" + print("[-] Searching in Netcraft:") search = netcraft.search_netcraft(word) search.process() all_hosts = search.get_hostnames() @@ -151,7 +149,7 @@ def start(argv): if engineitem == "threatcrowd": - print "[-] Searching in Threatcrowd:" + print("[-] Searching in Threatcrowd:") search = threatcrowd.search_threatcrowd(word) search.process() all_hosts = search.get_hostnames() @@ -160,7 +158,7 @@ def start(argv): db.store_all(word,all_hosts,'host','threatcrowd') if engineitem == "virustotal": - print "[-] Searching in Virustotal:" + print("[-] Searching in Virustotal:") search = virustotal.search_virustotal(word) search.process() all_hosts = search.get_hostnames() @@ -170,7 +168,7 @@ def start(argv): if engineitem == "crtsh": - print "[-] Searching in CRT.sh:" + print("[-] Searching in CRT.sh:") search = crtsh.search_crtsh(word) search.process() all_hosts = search.get_hostnames() @@ -179,7 +177,7 @@ def start(argv): db.store_all(word,all_hosts,'host','CRTsh') if engineitem == "googleCSE": - print "[-] Searching in Google Custom Search:" + print("[-] Searching in Google Custom Search:") search = googleCSE.search_googleCSE(word, limit, start) search.process() search.store_results() @@ -191,7 +189,7 @@ def start(argv): db.store_all(word,all_hosts,'host','googleCSE') elif engineitem == "bing" or engineitem == "bingapi": - print "[-] Searching in Bing:" + print("[-] Searching in Bing:") search = bingsearch.search_bing(word, limit, start) if engineitem == "bingapi": bingapi = "yes" @@ -202,14 +200,14 @@ def start(argv): all_hosts = search.get_hostnames() elif engineitem == "dogpile": - print "[-] Searching in Dogpilesearch.." + print("[-] Searching in Dogpilesearch..") search = dogpilesearch.search_dogpile(word, limit) search.process() all_emails = search.get_emails() all_hosts = search.get_hostnames() elif engineitem == "pgp": - print "[-] Searching in PGP key server.." + print("[-] Searching in PGP key server..") search = pgpsearch.search_pgp(word) search.process() all_emails = search.get_emails() @@ -220,65 +218,65 @@ def start(argv): db.store_all(word,all_emails,'emails','pgp') elif engineitem == "yahoo": - print "[-] Searching in Yahoo.." + print("[-] Searching in Yahoo..") search = yahoosearch.search_yahoo(word, limit) search.process() all_emails = search.get_emails() all_hosts = search.get_hostnames() - # elif engineitem == "baidu": - print "[-] Searching in Baidu.." + elif engineitem == "baidu": + print("[-] Searching in Baidu..") search = baidusearch.search_baidu(word, limit) search.process() all_emails = search.get_emails() all_hosts = search.get_hostnames() elif engineitem == "googleplus": - print "[-] Searching in Google+ .." + print("[-] Searching in Google+ ..") search = googleplussearch.search_googleplus(word, limit) search.process() people = search.get_people() - print "Users from Google+:" - print "====================" + print("Users from Google+:") + print("====================") for user in people: - print user + print(user) sys.exit() elif engineitem == "twitter": - print "[-] Searching in Twitter .." + print("[-] Searching in Twitter ..") search = twittersearch.search_twitter(word, limit) search.process() people = search.get_people() - print "Users from Twitter:" - print "-------------------" + print("Users from Twitter:") + print("-------------------") for user in people: - print user + print(user) sys.exit() elif engineitem == "linkedin": - print "[-] Searching in Linkedin.." + print("[-] Searching in Linkedin..") search = linkedinsearch.search_linkedin(word, limit) search.process() people = search.get_people() - print "Users from Linkedin:" - print "-------------------" + print("Users from Linkedin:") + print("-------------------") for user in people: - print user + print(user) sys.exit() elif engineitem == "google-profiles": - print "[-] Searching in Google profiles.." + print("[-] Searching in Google profiles..") search = googlesearch.search_google(word, limit, start) search.process_profiles() people = search.get_profiles() - print "Users from Google profiles:" - print "---------------------------" + print("Users from Google profiles:") + print("---------------------------") for users in people: - print users + print(users) sys.exit() elif engineitem == "hunter": - print "[-] Searching in Hunter:" + print("[-] Searching in Hunter:") from discovery import huntersearch #import locally or won't work search = huntersearch.search_hunter(word, limit, start) @@ -287,11 +285,11 @@ def start(argv): all_hosts = search.get_hostnames() elif engineitem == "all": - print "Full harvest on " + word + print(("Full harvest on " + word)) all_emails = [] all_hosts = [] - print "[-] Searching in Google.." + print("[-] Searching in Google..") search = googlesearch.search_google(word, limit, start) search.process(google_dorking) emails = search.get_emails() @@ -303,7 +301,7 @@ def start(argv): db=stash.stash_manager() db.store_all(word,all_hosts,'host','google') - print "[-] Searching in PGP Key server.." + print("[-] Searching in PGP Key server..") search = pgpsearch.search_pgp(word) search.process() emails = search.get_emails() @@ -315,7 +313,7 @@ def start(argv): db=stash.stash_manager() db.store_all(word,all_hosts,'email','PGP') - print "[-] Searching in Netcraft server.." + print("[-] Searching in Netcraft server..") search = netcraft.search_netcraft(word) search.process() hosts = search.get_hostnames() @@ -323,7 +321,7 @@ def start(argv): db=stash.stash_manager() db.store_all(word,all_hosts,'host','netcraft') - print "[-] Searching in ThreatCrowd server.." + print("[-] Searching in ThreatCrowd server..") try: search = threatcrowd.search_threatcrowd(word) search.process() @@ -334,7 +332,7 @@ def start(argv): db.store_all(word,all_hosts,'host','threatcrowd') except Exception: pass - print "[-] Searching in CRTSH server.." + print("[-] Searching in CRTSH server..") search = crtsh.search_crtsh(word) search.process() hosts = search.get_hostnames() @@ -342,7 +340,7 @@ def start(argv): db=stash.stash_manager() db.store_all(word,all_hosts,'host','CRTsh') - print "[-] Searching in Virustotal server.." + print("[-] Searching in Virustotal server..") search = virustotal.search_virustotal(word) search.process() hosts = search.get_hostnames() @@ -350,7 +348,7 @@ def start(argv): db=stash.stash_manager() db.store_all(word,all_hosts,'host','virustotal') - print "[-] Searching in Bing.." + print("[-] Searching in Bing..") bingapi = "no" search = bingsearch.search_bing(word, limit, start) search.process(bingapi) @@ -363,7 +361,7 @@ def start(argv): #Clean up email list, sort and uniq all_emails=sorted(set(all_emails)) - print "[-] Searching in Hunter:" + print("[-] Searching in Hunter:") from discovery import huntersearch #import locally search = huntersearch.search_hunter(word, limit, start) @@ -379,34 +377,34 @@ def start(argv): else: #if engine not in ("baidu", "bing", "crtsh","bingapi","dogpile","google", "googleCSE","virustotal","threatcrowd", "googleplus", "google-profiles","linkedin", "pgp", "twitter", "vhost", "yahoo","netcraft","all"): usage() - print "Invalid search engine, try with: baidu, bing, bingapi, crtsh, dogpile, google, googleCSE, virustotal, netcraft, googleplus, google-profiles, linkedin, pgp, twitter, vhost, yahoo, hunter, all" + print("Invalid search engine, try with: baidu, bing, bingapi, crtsh, dogpile, google, googleCSE, virustotal, netcraft, googleplus, google-profiles, linkedin, pgp, twitter, vhost, yahoo, hunter, all") sys.exit() #else: # pass #Results############################################################ print("\n\033[1;32;40m Harvesting results") - print "\n\n[+] Emails found:" - print "------------------" + print("\n\n[+] Emails found:") + print("------------------") if all_emails == []: - print "No emails found" + print("No emails found") else: - print "\n".join(all_emails) + print(("\n".join(all_emails))) print("\033[1;33;40m \n[+] Hosts found in search engines:") - print "------------------------------------" + print("------------------------------------") if all_hosts == []: - print "No hosts found" + print("No hosts found") else: total = len(all_hosts) - print "\nTotal hosts: " + str(total) + "\n" + print(("\nTotal hosts: " + str(total) + "\n")) all_hosts=sorted(set(all_hosts)) - print "\033[94m[-] Resolving hostnames IPs...\033[1;33;40m \n " + print("\033[94m[-] Resolving hostnames IPs...\033[1;33;40m \n ") full_host = hostchecker.Checker(all_hosts) full = full_host.check() for host in full: ip = host.split(':')[1] - print host + print(host) if ip != "empty": if host_ip.count(ip.lower()): pass @@ -416,13 +414,13 @@ def start(argv): #DNS Brute force#################################################### dnsres = [] if dnsbrute == True: - print "\n\033[94m[-] Starting DNS brute force: \033[1;33;40m" + print("\n\033[94m[-] Starting DNS brute force: \033[1;33;40m") a = dnssearch.dns_force(word, dnsserver, verbose=True) res = a.process() - print "\n\033[94m[-] Hosts found after DNS brute force:" - print "---------------------------------------" + print("\n\033[94m[-] Hosts found after DNS brute force:") + print("---------------------------------------") for y in res: - print y + print(y) dnsres.append(y.split(':')[0]) if y not in full: full.append(y) @@ -436,35 +434,35 @@ def start(argv): host = x.split(':')[1] domain = x.split(':')[0] if host != "empty" : - print "- Scanning : " + host + print(("- Scanning : " + host)) ports = [80,443,22,8080,21] try: scan = port_scanner.port_scan(host,ports) openports = scan.process() if len(openports) > 1: - print "\t\033[91m Detected open ports: " + ','.join(str(e) for e in openports) + "\033[1;32;40m" + print(("\t\033[91m Detected open ports: " + ','.join(str(e) for e in openports) + "\033[1;32;40m")) takeover_check = 'True' if takeover_check == 'True': if len(openports) > 0: search_take = takeover.take_over(domain) search_take.process() - except Exception, e: - print e + except Exception as e: + print(e) #DNS reverse lookup################################################# dnsrev = [] if dnslookup == True: - print "\n[+] Starting active queries:" + print("\n[+] Starting active queries:") analyzed_ranges = [] for x in host_ip: - print x + print(x) ip = x.split(":")[0] range = ip.split(".") range[3] = "0/24" range = string.join(range, '.') if not analyzed_ranges.count(range): - print "\033[94m[-]Performing reverse lookup in : " + range + "\033[1;33;40m" + print(("\033[94m[-]Performing reverse lookup in : " + range + "\033[1;33;40m")) a = dnssearch.dns_reverse(range, True) a.list() res = a.process() @@ -476,29 +474,29 @@ def start(argv): dnsrev.append(x) if x not in full: full.append(x) - print "Hosts found after reverse lookup (in target domain):" - print "---------------------------------" + print("Hosts found after reverse lookup (in target domain):") + print("---------------------------------") for xh in dnsrev: - print xh + print(xh) #DNS TLD expansion################################################### dnstldres = [] if dnstld == True: - print "[-] Starting DNS TLD expansion:" + print("[-] Starting DNS TLD expansion:") a = dnssearch.dns_tld(word, dnsserver, verbose=True) res = a.process() - print "\n[+] Hosts found after DNS TLD expansion:" - print "------------------------------------------" + print("\n[+] Hosts found after DNS TLD expansion:") + print("------------------------------------------") for y in res: - print y + print(y) dnstldres.append(y) if y not in full: full.append(y) #Virtual hosts search############################################### if virtual == "basic": - print "\n[+] Virtual hosts:" - print "------------------" + print("\n[+] Virtual hosts:") + print("------------------") for l in host_ip: search = bingsearch.search_bing(l, limit, start) search.process_vhost() @@ -507,7 +505,7 @@ def start(argv): x = re.sub(r'[[\<\/?]*[\w]*>]*','',x) x = re.sub('<','',x) x = re.sub('>','',x) - print l + "\t" + x + print((l + "\t" + x)) vhost.append(l + ":" + x) full.append(l + ":" + x) vhost=sorted(set(vhost)) @@ -522,7 +520,7 @@ def start(argv): try: ip = x.split(":")[1] if not shodanvisited.count(ip): - print "\tSearching for: " + ip + print(("\tSearching for: " + ip)) a = shodansearch.search_shodan(ip) shodanvisited.append(ip) results = a.run() @@ -532,12 +530,12 @@ def start(argv): res['info'] = '' shodanres.append( x + "SAPO" + str(res['info']) + "SAPO" + str(res['data'])) - except: + except Exception: pass - print "\n [+] Shodan results:" - print "------------------" + print("\n [+] Shodan results:") + print("------------------") for x in shodanres: - print x.split("SAPO")[0] + ":" + x.split("SAPO")[1] + print((x.split("SAPO")[0] + ":" + x.split("SAPO")[1])) else: pass @@ -552,15 +550,15 @@ def start(argv): search.process(google_dorking) emails = search.get_emails() hosts = search.get_hostnames() - print emails - print hosts + print(emails) + print(hosts) else: pass #Reporting####################################################### if filename != "": try: - print "[+] Saving files..." + print("[+] Saving files...") html = htmlExport.htmlExport( all_emails, full, @@ -573,8 +571,8 @@ def start(argv): dnstldres) save = html.writehtml() except Exception as e: - print e - print "Error creating the file" + print(e) + print("Error creating the file") try: filename = filename.split(".")[0] + ".xml" file = open(filename, 'w') @@ -629,15 +627,15 @@ def start(argv): file.write('') file.flush() file.close() - print "Files saved!" + print("Files saved!") except Exception as er: - print "Error saving XML file: " + er + print(("Error saving XML file: " + er)) sys.exit() if __name__ == "__main__": try: start(sys.argv[1:]) except KeyboardInterrupt: - print "Search interrupted by user.." + print("Search interrupted by user..") except: sys.exit()