Browse Source

Ported to Python3

epsylon 1 year ago
parent
commit
3185c63706

+ 0 - 60
.gitignore

@@ -1,60 +0,0 @@
-# ---> Python
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*,cover
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-

File diff suppressed because it is too large
+ 0 - 173
LICENSE


+ 60 - 8
README.md

@@ -1,6 +1,11 @@
-## PyDog4Apache
+  
+![c](https://03c8.net/images/pydo4apache_banner.png "Pydog4apache")
 
-Apache web logs sneaker - by psy
+----------
+
+#### Info:
+
+Apache web logs sneaker - 2016/2020 - by psy [03c8.net]
 
   With this tool you can search for specific keywords (such as: government, police...) 
   on Whois description of the IPs of your website visitors by -automagically- analyzing 
@@ -11,23 +16,70 @@ Apache web logs sneaker - by psy
 
 ----------
 
- + Web: http://pydog4apache.03c8.net [03c8.net]
- + Code: https://github.com/epsylon/pydog4apache
+ + Web: https://pydog4apache.03c8.net 
 
 ----------
 
-  Installing:
+#### Installing:
 
-  PyDog4Apache runs on many platforms.  It requires Python (2.x.y) and the following libraries:
+  PyDog4Apache runs on many platforms. It requires Python (3.x.y) and the following libraries:
 
-       python-pip - alternative Python package installer
+       python3-pip - Python package installer
+       ipwhois (0.10.3)  - Retrieve and parse whois data for IPv4 and IPv6 addresses.
 
   On Debian-based systems (ex: Ubuntu), run: 
 
-       sudo apt-get install python-pip && sudo pip install ipwhois
+       sudo apt-get install python3-pip && sudo pip3 install ipwhois
+
+  Or:
+
+       sudo apt-get install python3-pip && pip3 install ipwhois==0.10.3 --user
 
   Source libs:
 
        * Pypi-ipwhois: https://pypi.python.org/pypi/ipwhois/
 
 ----------
+
+#### Examples:
+
+  Verbose:
+
+    python3 pydog4apache -v 
+
+  Update:
+
+    python3 pydog4apache --update
+
+  Generate report file:
+
+    python3 pydog4apache -r my_visitants.txt
+
+  Notify results via email to some recipients:
+
+    python3 pydog4apache -n='root@localhost,foo@email.org,bar@email.net'
+
+  Combine options:
+
+    python3 pydog4apache -v -r my_visitants.txt -n epsylon@riseup.net
+
+  Launch it as daemon (notify via email when finish):
+
+    python3 pydog4apache -n epsylon@riseup.net &
+
+----------
+
+#### License:
+
+  Pydog4apache is released under the GPLv3.
+
+#### Contact:
+
+    - psy (epsylon@riseup.net)
+
+#### Contribute: 
+
+  To make donations use the following hash:
+  
+    - Bitcoin: 19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw
+

+ 2 - 2
pydog4apache/core/__init__.py

@@ -1,7 +1,7 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python3 
 # -*- coding: utf-8 -*-"
 """
-PyDog4Apache - 2016 - by psy (epsylon@riseup.net)
+PyDog4Apache - 2016/2020 - by psy (epsylon@riseup.net)
 
 You should have received a copy of the GNU General Public License along
 with PyDog4Apache; if not, write to the Free Software Foundation, Inc., 51

+ 85 - 78
pydog4apache/core/main.py

@@ -1,21 +1,21 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python3 
 # -*- coding: utf-8 -*-"
 """
-PyDog4Apache - 2015 - by psy (epsylon@riseup.net)
+PyDog4Apache - 2016/2020 - by psy (epsylon@riseup.net)
 
 You should have received a copy of the GNU General Public License along
 with PyDog4Apache; if not, write to the Free Software Foundation, Inc., 51
 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 """
-from options import PyDog4ApacheOptions
-from update import Updater
 import os, traceback, sys, re, gzip, datetime, string, stat
+from .options import PyDog4ApacheOptions
+from .update import Updater
 
 try:
     from ipwhois import IPWhois
 except:
-    print "\n[Warning] - Error importing: ipwhois lib. \n\n On Debian based systems:\n\n $ sudo apt-get install python-pip && sudo pip install ipwhois\n"
-    print "[Source] - Pypi-ipwhois: https://pypi.python.org/pypi/ipwhois/\n"
+    print("\n[Warning] - Error importing: ipwhois lib. \n\n On Debian based systems:\n\n $ sudo apt-get install python3-pip && sudo pip3 install ipwhois\n")
+    print("[Source] - Pypi-ipwhois: https://pypi.python.org/pypi/ipwhois/\n")
     sys.exit(2)
 
 DEBUG = 0
@@ -36,15 +36,15 @@ class PyDog4Apache(object):
         return self.options
 
     def banner(self):
-        print '='*75, "\n"
-        print " ____        ____              _  _     _                     _          "
-        print "|  _ \ _   _|  _ \  ___   __ _| || |   / \   _ __   __ _  ___| |__   ___ "
-        print "| |_) | | | | | | |/ _ \ / _` | || |_ / _ \ | '_ \ / _` |/ __| '_ \ / _ |"
-        print "|  __/| |_| | |_| | (_) | (_| |__   _/ ___ \| |_) | (_| | (__| | | |  __/"
-        print "|_|    \__, |____/ \___/ \__, |  |_|/_/   \_\ .__/ \__,_|\___|_| |_|\___|"
-        print "       |___/             |___/              |_|                          "
-        print self.optionParser.description, "\n"
-        print '='*75
+        print('='*75, "\n")
+        print(" ____        ____              _  _     _                     _          ")
+        print("|  _ \ _   _|  _ \  ___   __ _| || |   / \   _ __   __ _  ___| |__   ___ ")
+        print("| |_) | | | | | | |/ _ \ / _` | || |_ / _ \ | '_ \ / _` |/ __| '_ \ / _ |")
+        print("|  __/| |_| | |_| | (_) | (_| |__   _/ ___ \| |_) | (_| | (__| | | |  __/")
+        print("|_|    \__, |____/ \___/ \__, |  |_|/_/   \_\ .__/ \__,_|\___|_| |_|\___|")
+        print("       |___/             |___/              |_|                          ")
+        print(self.optionParser.description, "\n")
+        print('='*75)
 
     def try_running(self, func, error, args=None):
         options = self.options
@@ -52,14 +52,13 @@ class PyDog4Apache(object):
         try:
             return func(*args)
         except Exception as e:
-            print(error, "error")
-            if DEBUG:
+            print((error, "error"))
+            if DEBUG != 0:
                 traceback.print_exc()
 
     def check_root(self): # check root permissions
         if not os.geteuid()==0:
-            print "[Error] - Some of your 'sources' need more rights to be accessed."
-            sys.exit("\n[Info] - Try to launch it as root (ex: 'sudo ./pydog4apache')\n")
+            sys.exit("[Info] You need to launch it as root (ex: 'sudo python3 pydog4apache')...\n")
 
     def is_readable(self, folder): # check if logs are readable without root permissions
         try:
@@ -73,9 +72,9 @@ class PyDog4Apache(object):
         for folder in logs:
             root = self.is_readable(folder)
             if root == None: # wrong folder
-                print "[Error] - This source:", folder, "is not valid!. Passing..."
+                print("\n[Error] This source: [", folder, "] is not valid... [Passing!]")
             if root is 0: # root needed
-                check_perms = self.try_running(self.check_root, "\nInternal error checking root permissions.")
+                check_perms = self.try_running(self.check_root, "\n[Error] Internal error checking root permissions.")
 
     def extract_logs(self): # extract logs from folder (ex: 'sources.txt')
         try:
@@ -84,26 +83,24 @@ class PyDog4Apache(object):
             logs = [ log.replace('\n','') for log in logs ]
             f.close()
             if not logs:
-                print "\n[Error] - Imposible to retrieve 'sources' from file.\n"
+                print("\n[Error] Imposible to retrieve 'sources' from file... [Aborting!]\n")
                 return
             else:
                 return logs
         except:
             if os.path.exists('sources.txt') == True:
-                print '\n[Error] - Cannot open:', 'sources.txt', "\n"
+                print('\n[Error] Cannot open:', 'sources.txt', "[Aborting!]\n")
                 sys.exit(2)
             else:
-                print '\n[Error] - Cannot found:', 'sources.txt', "\n"
+                print('\n[Error] Cannot found:', 'sources.txt', "[Aborting!]\n")
                 sys.exit(2)
 
     def extract_whois(self, ip): # extract whois description
         try:
             if re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip): # only IPs
                 w = IPWhois(ip, timeout=5) # timeout 5
-                res = w.lookup_whois(retry_count=2) # legacy whois / retries 2
+                res = w.lookup(retry_count=2) # legacy whois / retries 2
                 descr = res["nets"][0]['description']
-                if self.options.verbose:
-                    print"[Verbose] - Resolving:", ip
             else:
                 descr = None
         except:
@@ -121,6 +118,7 @@ class PyDog4Apache(object):
     def check_visitants(self, descr): # check visitors list
         try:
             for v in self.keys:
+                v = v.rstrip()
                 if v.lower() in descr.lower(): # visitant found!
                     key = v.lower()
                     return key
@@ -130,7 +128,7 @@ class PyDog4Apache(object):
             if os.path.exists('keywords.txt') == True:
                 return
             else:
-                print '\n[Error] - Cannot found:', 'keywords.txt', "\n"
+                print('\n[Error] Cannot found:', 'keywords.txt', "[Aborting!]\n")
                 return
 
     def run(self, opts=None):
@@ -139,24 +137,20 @@ class PyDog4Apache(object):
             self.set_options(options)
         options = self.options
         self.banner()
-        if options.update:
-            try:
-                print("\n[Info] - Trying to update automatically to the latest stable version.\n")
-                Updater()
-            except:
-                print("\nSomething was wrong!. You should clone PyDog2Apache manually with:\n")
-                print("$ git clone https://github.com/epsylon/pydog2apache\n")
-            sys.exit(2)
-        print "\n[Info] - Sending dogs to sniff logs... Please wait!\n"
-        print "-"*22
+        if options.update: # auto-update tool
+            print("\n[Info] Trying to update automatically to the latest stable version...\n")
+            Updater()
+            sys.exit()
+        print("\n[Info] Sending 'dogs' to sniff 'logs'... [Waiting!]")
+        if self.options.verbose:
+            print("\n"+"="*40+"\n")
         logs = self.try_running(self.extract_logs, "\nInternal error extracting logs.")
         access = self.check_access(logs)
         f = open('keywords.txt')
         self.keys = f.readlines()
-        self.keys = [ self.key.replace('\n','') for self.key in self.keys ]
         f.close()
         if not self.keys:
-            print "\n[Error] - Imposible to retrieve 'visitants' from file.\n"
+            print("\n[Error] Imposible to retrieve 'visitants' from file... [Aborting!]\n")
             return
         for folder in logs:
             if not folder.endswith('/'):
@@ -165,69 +159,82 @@ class PyDog4Apache(object):
                 listing = os.listdir(folder)
                 for log in listing:
                     if self.options.verbose:
-                        print "[Verbose] - Analyzing:", folder+log
+                        print("[Info] Analyzing:", folder+log)
                     if log.endswith('.gz'): # also read on compressed logs
-                        with gzip.open(folder+log, 'rb') as f:
+                        with gzip.open(folder+log, 'r') as f:
                             dog_sniff = f.readlines()
+                            dog_sniff = [ dog_sniff[0].decode() for sniff in dog_sniff ]
                     else:
                         try:
                             f = open(folder+log)
+                            dog_sniff = f.readlines()
                         except:
                             return
-                        dog_sniff = f.readlines()
-                    sep = '-'
-                    sep2= '['
-                    for record in dog_sniff:
-                        ip = record.split(sep, 1)[0]
-                        ip = ''.join(ip.split())
-                        ip_found = self.is_valid_ip(ip)
-                        if ip_found is True: # extract info
-                            date = [record.split(']')[0] for p in record.split('[') if ']' in p]
-                            for d in date:
-                                date_visit = d.split(sep2, 1)[1]
-                            descr = self.extract_whois(ip)
-                            if descr is not None:
-                                key = self.check_visitants(descr)
-                                if key:
-                                    self.visitants[str(ip)] = "[" + str(key.upper()) + "]" + "|" + str(str(descr) + "|" + str(date_visit) + "|" + str(folder+log))
+                    if dog_sniff:
+                        sep = '-'
+                        sep2= '['
+                        for record in dog_sniff:
+                            ip = record.split(sep, 1)[0]
+                            ip = ''.join(ip.split())
+                            ip_found = self.is_valid_ip(ip)
+                            if ip_found is True: # extract info
+                                if self.options.verbose:
+                                    print("    |-> IP Found:", ip)
+                                date = [record.split(']')[0] for p in record.split('[') if ']' in p]
+                                for d in date:
+                                    date_visit = d.split(sep2, 1)[1]
+                                descr = self.extract_whois(ip)
+                                if descr is not None:
+                                    key = self.check_visitants(descr)
+                                    if key:
+                                        self.visitants[str(ip)] = "[ " + str(key.upper()) + " ]" + " | " + str(str(descr) + " | " + str(date_visit) + " | " + str(folder+log))
                     f.close()
             except:
                 pass
-        if self.options.verbose:
-            print "-"*22
+        print("\n"+"="*40+"\n")
         if self.options.file: # export results to file
             namefile = str(self.options.file)
             self.report = open(namefile, 'w')
-            self.report.write("# Apache web logs sneaker - GPLv3 - by psy\n")
-            self.report.write("# Project: https://github.com/epsylon/pydog4apache - 03c8.net\n")
+            self.report.write("# Apache web logs sneaker - 2016/2020 - by psy (https://03c8.net)\n")
+            self.report.write("# Project: https://code.03c8.net/epsylon/pydog4apache\n")
             self.report.write("# Reported at: " + str(datetime.datetime.now()) + "\n\n")
-        for key,val in self.visitants.items():
-            print("{} -> {}".format(key, val))
-            print "-"*12
-            if self.options.file: 
+        for key,val in list(self.visitants.items()):
+            print(("{} -> {}".format(key, val))+"\n")
+            if self.options.file:
+                self.report.write("Logs Analyzed:\n\n")
+                for log in listing:
+                    self.report.write(" -"+log+"\n")
+                self.report.write("\nResults:\n\n")
                 self.report.write(key + " -> " + val + "\n")
-                self.report.write("-"*12 + "\n")
-        if not self.visitants.items():
-            print "[Info] - Not any 'keyword' found on your 'visitants'.\n"
+        if not list(self.visitants.items()):
+            print("[Info] Not any 'keyword' found on your 'visitants'... [Exiting!]\n")
             if self.options.file:
-                self.report.write("Not any 'keyword' found on your 'visitants'.\n")
+                self.report.write("Logs Analyzed:\n\n")
+                for log in listing:
+                    self.report.write(" -"+log+"\n")
+                self.report.write("\nResults:\n\n")
+                self.report.write(" -Not any 'keyword' found on your 'visitants'...\n")
         if self.options.file: # close file containter
             self.report.close()
         if self.options.emails: # send results via email
+            print("-"*22+"\n")
             import smtplib, socket
             from email.mime.text import MIMEText
             self.notify = open('tempmail', 'w')
-            self.notify.write("# Apache web logs sneaker - GPLv3 - by psy\n")
-            self.notify.write("# Project: https://github.com/epsylon/pydog4apache - 03c8.net\n")
+            self.notify.write("# Apache web logs sneaker - 2016/2020 - by psy (https://03c8.net)\n")
+            self.notify.write("# Project: https://code.03c8.net/epsylon/pydog4apache\n")
             self.notify.write("# Reported at: " + str(datetime.datetime.now()) + "\n\n")
-            for key,val in self.visitants.items():
+            self.notify.write("Logs Analyzed:\n\n")
+            for log in listing:
+                self.notify.write(" -"+log+"\n")
+            self.notify.write("\nResults:\n\n")
+            for key,val in list(self.visitants.items()):
                 self.notify.write(key + " -> " + val + "\n")
-                self.notify.write("-"*12 + "\n")
-            if not self.visitants.items():
-                self.notify.write("Not any 'keyword' found on your 'visitants'.\n")
+            if not list(self.visitants.items()):
+                self.notify.write("Not any 'keyword' found on your 'visitants'...\n")
             self.notify.close()
             self.notify = open('tempmail', 'rb')
-            msg = MIMEText(self.notify.read())
+            msg = MIMEText(self.notify.read().decode('utf-8'))
             self.notify.close()
             doggy = 'pydog4apache@'+str(socket.gethostname())
             herd = self.options.emails
@@ -241,7 +248,7 @@ class PyDog4Apache(object):
                 s.sendmail(doggy, herd, msg.as_string())
                 s.quit()
             except:
-                print "[Error] - Not any SMTP server running on: '"+str(socket.gethostname())+"'. Aborting email report...\n"
+                print("[Error] Not any SMTP (email) server running on: '"+str(socket.gethostname())+"'... [Passing!]\n")
             os.remove('tempmail') # remove temporal email container
 
 if __name__ == "__main__":

+ 5 - 5
pydog4apache/core/options.py

@@ -1,7 +1,7 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python3 
 # -*- coding: utf-8 -*-"
 """
-PyDog4Apache - 2016 - by psy (epsylon@riseup.net)
+PyDog4Apache - 2016/2020 - by psy (epsylon@riseup.net)
 
 You should have received a copy of the GNU General Public License along
 with PyDog4Apache; if not, write to the Free Software Foundation, Inc., 51
@@ -12,13 +12,13 @@ import optparse
 class PyDog4ApacheOptions(optparse.OptionParser):
     def __init__(self, *args):
         optparse.OptionParser.__init__(self, 
-                           description='\nApache web logs sneaker - by psy',
+                           description='\nApache web logs sneaker - 2016/2020 - by psy (https://03c8.net)',
                            prog='pydog4apache.py',
-                           version='\nVersion: v0.1b\n')
+                           version='\nVersion: v0.2 (2020) - https://pydog4apache.03c8.net\n')
         self.add_option("-u", "--update", action="store_true", dest="update", help="check for latest stable version")
         self.add_option("-v", "--verbose", action="store_true", dest="verbose", help="active verbose output")
         group1 = optparse.OptionGroup(self, "*Reporting*")
-        group1.add_option("-r", action="store", dest="file", help="generate file output with 'visitants'")
+        group1.add_option("-r", action="store", dest="file", help="generate file with results (ex: -r 'visitants.txt')")
         group1.add_option("-n", action="store", dest="emails", help="notify via email (foo@email.net,bar@email.org,...)")
         self.add_option_group(group1)
 

+ 13 - 10
pydog4apache/core/update.py

@@ -1,7 +1,7 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python3 
 # -*- coding: utf-8 -*-"
 """
-PyDog4Apache - 2016/2018 - by psy (epsylon@riseup.net)
+PyDog4Apache - 2016/2020 - by psy (epsylon@riseup.net)
 
 You should have received a copy of the GNU General Public License along
 with PyDog4Apache; if not, write to the Free Software Foundation, Inc., 51
@@ -13,17 +13,20 @@ from subprocess import Popen as execute
         
 class Updater(object):     
     def __init__(self):
-        GIT_REPOSITORY = "https://github.com/epsylon/pydog4apache"
+        GIT_REPOSITORY = "https://code.03c8.net/epsylon/pydog4apache"
+        GIT_REPOSITORY2 = "https://github.com/epsylon/pydog4apache"
         rootDir = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', ''))
         if not os.path.exists(os.path.join(rootDir, ".git")):
-            print "Not any .git repository found!\n"
-            print "="*30
-            print "\nTo have working this feature, you should clone pydog4apache with:\n"
-            print "$ git clone %s" % GIT_REPOSITORY
+            print("-"*22)
+            print("\n[Info] Not any .git repository found!")
+            print("\nTo have working this feature, you should clone pydgo4apache with:\n")
+            print("$ git clone %s" % GIT_REPOSITORY)
+            print("\nAlso you can try this other mirror:\n")
+            print("$ git clone %s" % GIT_REPOSITORY2 + "\n")
         else:
             checkout = execute("git checkout . && git pull", shell=True, stdout=PIPE, stderr=PIPE).communicate()[0]
-            print checkout
+            print(checkout)
             if not "Already up-to-date" in checkout:
-                print "Congratulations!! pydog4apache has been updated... ;-)\n"
+                print("Congratulations!! pydog4apache has been updated... ;-)\n")
             else:
-                print "Your pydog4apache doesn't need to be updated... ;-)\n"
+                print("Your pydog4apache doesn't need to be updated... ;-)\n")

+ 43 - 0
pydog4apache/docs/AUTHOR

@@ -0,0 +1,43 @@
+========================
+
+ nick: psy (epsylon)
+  
+  <epsylon@riseup.net> 
+
+ web: https://03c8.net
+
+=======================
+
+ code:
+
+ - https://code.03c8.net/epsylon
+ - https://github.com/epsylon
+
+=======================
+
+ software/projects:
+
+ - AnonTwi: Tool for OAuth2 applications (such as: GNUSocial, Twitter) that provides different layers of privacy/encryption.
+ - Bordercheck: Tool to visualize 'real-time' on a world map the geolocation of data when surfing the web.
+ - CIntruder: Tool to bypass captchas using OCR (Optical Character Recognition) bruteforcing methods.
+ - Collatz: Tool to simulate the Collatz's conjeture.
+ - DieKunstDerFuge: Video on different topics related to hacktivism recorded during 2013 from an intimate narrative perspective.
+ - ECOin: Decentralized key/value registration and transfer system based on Bitcoin technology (a cryptocurrency).
+ - Euler-Bricks: Tool to search for Euler's "bricks".
+ - Goldbach: Tool to simulate the Goldbach's conjeture.
+ - Lorea: Social networking autonomous project to build a distributed, encrypted and federated network.
+ - Orb: Tool for massive footprinting.
+ - pArAnoIA-Browser: Tool designed to surf the Internet using some "paranoic" methods.
+ - Propagare: Tool for extraction, organization and semantic analysis of newspapers.
+ - PyAISnake: Tool to train AI models on solve spatial problems through the classic video game "snake".
+ - PyDog4Apache: Tool to sneak logs from Apache web server.
+ - UFONet: Denial of Service [DDoS & DoS attacks] Toolkit (a botnet of botnets).
+ - XSSer: Automatic -framework- to detect, exploit and report XSS vulnerabilities.
+
+=======================
+
+ BTC: 
+
+  19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw
+
+========================

+ 24 - 13
pydog4apache/docs/README.txt

@@ -7,7 +7,7 @@
 |_|    \__, |____/ \___/ \__, |  |_|/_/   \_\ .__/ \__,_|\___|_| |_|\___|
        |___/             |___/              |_|                          
 
-Apache web logs sneaker - by psy 
+Apache web logs sneaker - 2016/2020 - by psy 
 
 ===========================================================================
 
@@ -15,7 +15,7 @@ Apache web logs sneaker - by psy
 # Project info
 ###############################
 
-  Web: https://github.com/epsylon/pydog2apache [http://03c8.net]
+  Web: https://pydog4apache.03c8.net/ [https://03c8.net]
 
 ###############################
 # Summary
@@ -34,17 +34,18 @@ Apache web logs sneaker - by psy
 # Installing
 ###############################
 
-  PyDog4Apache runs on many platforms.  It requires Python (2.x.y) and the following libraries:
+  PyDog4Apache runs on many platforms. It requires Python (3.x.y) and the following libraries:
 
-     python-pip - alternative Python package installer
+      python3-pip - Python package installer
+      ipwhois (0.10.3)  - Retrieve and parse whois data for IPv4 and IPv6 addresses.
 
   On Debian-based systems (ex: Ubuntu), run: 
 
-     sudo apt-get install python-pip && sudo pip install ipwhois
+      sudo apt-get install python3-pip && pip3 install ipwhois==0.10.3 --user
 
   Source libs:
 
-     * Pypi-ipwhois: https://pypi.python.org/pypi/ipwhois/
+      * Pypi-ipwhois: https://pypi.python.org/pypi/ipwhois/
 
 ###############################
 # HowTo
@@ -63,28 +64,28 @@ Apache web logs sneaker - by psy
       -n EMAILS    notify via email (foo@email.net,bar@email.org,...)
 
 ###############################
-# Usage
+# Examples
 ###############################
 
   Verbose:
 
-    ./pydog4apache -v 
+    python3 pydog4apache -v
 
   Generate report file:
 
-    ./pydog4apache -r my_visitants.txt
+    python3 pydog4apache -r 'visitants.txt'
 
   Notify results via email to some recipients:
 
-    ./pydog4apache -n='root@localhost,foo@email.org,bar@email.net'
+    python3 pydog4apache -n='root@localhost,foo@email.org,bar@email.net'
 
   Combine options:
 
-    ./pydog4apache -v -r my_visitants.txt -n epsylon@riseup.net
+    python3 pydog4apache -v -r 'visitants.txt' -n 'epsylon@riseup.net'
 
   Launch it as daemon (notify via email when finish):
 
-    ./pydog4apache -n epsylon@riseup.net &
+    python3 pydog4apache -n 'epsylon@riseup.net' &
 
 ###############################
 # Updating
@@ -96,7 +97,7 @@ Apache web logs sneaker - by psy
 
   To check your version you should launch:
 
-    ./pydog4apache --update
+    python3 pydog4apache --update
 
   This will update the tool automatically removing all files from old package.
 
@@ -104,8 +105,18 @@ Apache web logs sneaker - by psy
 # Timelog
 ###############################
 
+--------------------------
+  08.01.2020 : v.0.2
 --------------------------
   11.04.2016 : v.0.1b
 --------------------------
 
+###############################
+# Contribute
+###############################
+
+ To make donations use the following hash:
+  
+  - Bitcoin: 19aXfJtoYJUoXEZtjNwsah2JKN9CK5Pcjw
+
 ############

+ 3 - 1
pydog4apache/docs/requirements.txt

@@ -1 +1,3 @@
-pip==1.5.6-7
+ipwhois==0.10.3
+dnspython==1.15.0
+dnspython3==1.15.0

+ 7 - 0
pydog4apache/keywords.txt

@@ -1,8 +1,10 @@
 Estate
+Bureau
 Army
 Association
 Bank
 Business
+Center
 Company
 Office
 Military
@@ -10,6 +12,7 @@ Federal
 Consultory
 Academy
 Financial
+International
 Department
 Lawyers
 Ministery
@@ -29,6 +32,7 @@ School
 Laboratory
 Society
 Estado
+Bufete
 Ejercito
 Asociacion
 Banco
@@ -45,10 +49,13 @@ Agencia
 Policia
 Tienda
 Gobierno
+Compañia
 Nacional
 Educacion
+Centro
 Equipo
 Grupo
+Internacional
 Universidad
 Industria
 Escuela

+ 2 - 2
pydog4apache/pydog4apache

@@ -1,7 +1,7 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python3 
 # -*- coding: utf-8 -*-"
 """
-PyDog4Apache - 2016 - by psy (epsylon@riseup.net)
+PyDog4Apache - 2016/2020 - by psy (epsylon@riseup.net)
 
 You should have received a copy of the GNU General Public License along
 with PyDog4Apache; if not, write to the Free Software Foundation, Inc., 51