Subversion Repositories kim

Rev

Rev 6 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
# Author: Tomás Vírseda <tomasvirseda@gmail.com>
# Version: 0.1
# License: GPLv3
# Description: KIM (Keep In Mind) is a little script to extract visited
#              SAP Notes from webbrowsers (currently Firefox and Chrome)
"""


import os
import sys
import shutil
import sqlite3
import logging
from subprocess import check_output

try:
    from .logger import Logger
    from .project import *
except:
    from logger import Logger
    from project import *

# Constants
ROOT = "https://launchpad.support.sap.com/#/notes/"

class Utils:
    log = None
    def __init__(self, options):
        self.log = Logger('Utils', level=options.LOGLEVEL).get_logger()


    def validate(self, url):
        chunk = url[len(ROOT):]
        if not chunk[0].isnumeric():
            return None

        sep = chunk.find('/')
        if sep > 0:
            chunk = chunk[:sep]

        numeric = True
        for char in chunk:
            if not char.isnumeric():
                numeric = False

        if numeric:
            return str(int(chunk))
        else:
            return None


    def get_firefox_profile_dir(self):
        if sys.platform in ['linux', 'linux2']:
            import subprocess
            cmd = "ls -d /home/$USER/.mozilla/firefox/*.default/"
            p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE)
            PRF_DIR = p.communicate()[0][0:-2]
            PRF_DIR = PRF_DIR.decode("utf-8")
        elif sys.platform == 'win32':
            import os
            import glob
            APPDATA = os.getenv('APPDATA')
            FF_PRF_DIR = "%s\\Mozilla\\Firefox\\Profiles\\" % APPDATA
            PATTERN = FF_PRF_DIR + "*default*"
            PRF_DIR = glob.glob(PATTERN)[0]

        self.log.debug("FIREFOX PROFILE DIRECTORY: %s", PRF_DIR)

        return PRF_DIR


    def get_firefox_history(self):
        profile_dir = self.get_firefox_profile_dir()
        if profile_dir is None:
            self.log.warning ("No Firefox profile path found")
            return None
        elif os.path.isdir(profile_dir) == False:
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
            return None
        else:
            placesDB = os.path.join(profile_dir, 'places.sqlite')
            self.log.debug("Firefox DB: %s", placesDB)
            if os.path.isfile(placesDB):
                return self.filter_firefox_history(placesDB)
            else:
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
                return None


    def get_chrome_profile_dir(self):
        if sys.platform in ['linux', 'linux2']:
            from subprocess import check_output
            try:
                cmd = "ls -d /home/$USER/.config/google-chrome/default"
                PRF_DIR = check_output(cmd)
                if not os.path.exists(PRF_DIR):
                    PRF_DIR = None
            except:
                PRF_DIR = None
        elif sys.platform == 'win32':
            import os
            USERNAME = os.getenv('USERNAME')
            PRF_DIR = "C:\\Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default" % USERNAME

        if PRF_DIR is not None:
            if type(PRF_DIR) != str:
                PRF_DIR = PRF_DIR.decode("utf-8")
            self.log.debug("CHROME PROFILE DIRECTORY: %s", PRF_DIR)
        else:
            PRF_DIR = None
            self.log.debug("CHROME PROFILE DIRECTORY: not found")
        return PRF_DIR


    def get_chrome_history(self):
        profile_dir = self.get_chrome_profile_dir()
        if profile_dir is None:
            self.log.debug ("No Chrome profile path found")
            return None
        elif os.path.isdir(profile_dir) == False:
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
            return None
        else:
            placesDB = os.path.join(profile_dir, 'history')
            self.log.debug("Chrome DB: %s", placesDB)
            if os.path.isfile(placesDB):
                return self.filter_chrome_history(placesDB)
            else:
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
                return None

    def filter_firefox_history(self, placesDB):
        sndict = {}
        self.log.debug('Searching SAP Notes in Firefox history')
        try:
            conn = sqlite3.connect(placesDB)
            c = conn.cursor()
            c.execute("select url, date(visit_date/1000000, \
              'unixepoch') from moz_places, moz_historyvisits \
              where visit_count > 0 and moz_places.id==\
              moz_historyvisits.place_id;"
)

            for row in c:
                url = str(row[0])
                date = str(row[1])
                if '/support/notes/' in url:
                    snid = self.validate(url)
                    if snid is not None:
                        try:
                            sndate = sndict[snid]
                            if date > sndate:
                                sndict[snid] = date
                        except:
                            sndict[snid] = date

            self.log.debug ("Firefox: %d SAP Notes found" % len(sndict))
            return sndict
        except Exception as error:
            if 'encrypted' in str(error):
                self.log.error ('Error reading your places database.')
                self.log.error ('Upgrade your Python-Sqlite3 Library')
                return None
            else:
                self.log.error(error)
                return None

    def filter_chrome_history(self, placesDB):
        sndict = {}
        self.log.debug('Searching SAP Notes in Chrome history')
        shutil.copy(placesDB, "history")
        conn = sqlite3.connect("history")
        c = conn.cursor()
        try:
            select_statement = "SELECT urls.url, date(visits.visit_time/1000000-11644473600, 'unixepoch') FROM urls, visits WHERE urls.id = visits.url;"
            c.execute(select_statement)
            for row in c:
                url = str(row[0])
                date = str(row[1])
                if '/support/notes/' in url:
                    snid = self.validate(url)
                    if snid is not None:
                        try:
                            sndate = sndict[snid]
                            if date > sndate:
                                sndict[snid] = date
                        except:
                            sndict[snid] = date
            self.log.debug ("Chrome: %d SAP Notes found" % len(sndict))
            return sndict
        except Exception as error:
            self.log.error (error)
            return None


    def get_uniq_sapnotes(self, sndicts):
        usndict = {}
        for sndict in sndicts:
            if sndict is not None:
                for snid in sndict:
                    try:
                        date = usndict[snid]
                        if sndict[snid] > date:
                            usndict[snid] = sndict[snid]
                    except:
                        usndict[snid] = sndict[snid]
            else:
                self.log.debug("Possibly there is no data for current dictionary")
        self.log.debug("Unique SAP Notes for all browsers: %d" % len(usndict))
        return usndict