Subversion Repositories kim

Rev

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

Rev Author Line No. Line
3 t00m 1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
"""
4
# Author: Tomás Vírseda <tomasvirseda@gmail.com>
5
# Version: 0.1
6
# License: GPLv3
7
# Description: KIM (Keep In Mind) is a little script to extract visited
8
#              SAP Notes from webbrowsers (currently Firefox and Chrome)
9
"""
10
 
11
import os
12
import sys
13
import shutil
14
import sqlite3
15
import logging
16
from subprocess import check_output
17
 
18
try:
19
    from .logger import Logger
20
    from .project import *
21
except:
22
    from logger import Logger
23
    from project import *
24
 
25
# Constants
26
ROOT = "https://launchpad.support.sap.com/#/notes/"
27
 
28
class Utils:
29
    log = None
6 t00m 30
    def __init__(self, options):
31
        self.log = Logger('Utils', level=options.LOGLEVEL).get_logger()
3 t00m 32
 
33
 
34
    def validate(self, url):
35
        chunk = url[len(ROOT):]
36
        if not chunk[0].isnumeric():
37
            return None
38
 
39
        sep = chunk.find('/')
40
        if sep > 0:
41
            chunk = chunk[:sep]
42
 
43
        numeric = True
44
        for char in chunk:
45
            if not char.isnumeric():
46
                numeric = False
47
 
48
        if numeric:
4 t00m 49
            return str(int(chunk))
3 t00m 50
        else:
51
            return None
52
 
53
 
54
    def get_firefox_profile_dir(self):
55
        if sys.platform in ['linux', 'linux2']:
56
            import subprocess
57
            cmd = "ls -d /home/$USER/.mozilla/firefox/*.default/"
58
            p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE)
59
            PRF_DIR = p.communicate()[0][0:-2]
60
            PRF_DIR = PRF_DIR.decode("utf-8")
61
        elif sys.platform == 'win32':
62
            import os
63
            import glob
64
            APPDATA = os.getenv('APPDATA')
65
            FF_PRF_DIR = "%s\\Mozilla\\Firefox\\Profiles\\" % APPDATA
66
            PATTERN = FF_PRF_DIR + "*default*"
67
            PRF_DIR = glob.glob(PATTERN)[0]
68
 
69
        self.log.debug("FIREFOX PROFILE DIRECTORY: %s", PRF_DIR)
70
 
71
        return PRF_DIR
72
 
73
 
74
    def get_firefox_history(self):
75
        profile_dir = self.get_firefox_profile_dir()
76
        if profile_dir is None:
77
            self.log.warning ("No Firefox profile path found")
78
            return None
79
        elif os.path.isdir(profile_dir) == False:
80
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
81
            return None
82
        else:
83
            placesDB = os.path.join(profile_dir, 'places.sqlite')
84
            self.log.debug("Firefox DB: %s", placesDB)
85
            if os.path.isfile(placesDB):
6 t00m 86
                return self.filter_firefox_history(placesDB)
3 t00m 87
            else:
88
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
89
                return None
90
 
91
 
92
    def get_chrome_profile_dir(self):
93
        if sys.platform in ['linux', 'linux2']:
94
            from subprocess import check_output
95
            try:
96
                cmd = "ls -d /home/$USER/.config/google-chrome/default"
97
                PRF_DIR = check_output(cmd)
98
                if not os.path.exists(PRF_DIR):
99
                    PRF_DIR = None
100
            except:
101
                PRF_DIR = None
102
        elif sys.platform == 'win32':
103
            import os
104
            USERNAME = os.getenv('USERNAME')
105
            PRF_DIR = "C:\\Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default" % USERNAME
106
 
107
        if PRF_DIR is not None:
108
            if type(PRF_DIR) != str:
109
                PRF_DIR = PRF_DIR.decode("utf-8")
110
            self.log.debug("CHROME PROFILE DIRECTORY: %s", PRF_DIR)
111
        else:
112
            PRF_DIR = None
113
            self.log.debug("CHROME PROFILE DIRECTORY: not found")
114
        return PRF_DIR
115
 
116
 
117
    def get_chrome_history(self):
5 t00m 118
        profile_dir = self.get_chrome_profile_dir()
7 t00m 119
        if profile_dir is None:
120
            self.log.debug ("No Chrome profile path found")
3 t00m 121
            return None
5 t00m 122
        elif os.path.isdir(profile_dir) == False:
123
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
3 t00m 124
            return None
125
        else:
5 t00m 126
            placesDB = os.path.join(profile_dir, 'history')
3 t00m 127
            self.log.debug("Chrome DB: %s", placesDB)
128
            if os.path.isfile(placesDB):
6 t00m 129
                return self.filter_chrome_history(placesDB)
3 t00m 130
            else:
131
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
132
                return None
133
 
5 t00m 134
    def filter_firefox_history(self, placesDB):
3 t00m 135
        sndict = {}
7 t00m 136
        self.log.debug('Searching SAP Notes in Firefox history')
3 t00m 137
        try:
138
            conn = sqlite3.connect(placesDB)
139
            c = conn.cursor()
140
            c.execute("select url, date(visit_date/1000000, \
141
              'unixepoch') from moz_places, moz_historyvisits \
142
              where visit_count > 0 and moz_places.id==\
143
              moz_historyvisits.place_id;")
144
 
145
            for row in c:
146
                url = str(row[0])
147
                date = str(row[1])
148
                if '/support/notes/' in url:
149
                    snid = self.validate(url)
150
                    if snid is not None:
151
                        try:
152
                            sndate = sndict[snid]
153
                            if date > sndate:
154
                                sndict[snid] = date
155
                        except:
156
                            sndict[snid] = date
157
 
158
            self.log.debug ("Firefox: %d SAP Notes found" % len(sndict))
159
            return sndict
160
        except Exception as error:
161
            if 'encrypted' in str(error):
162
                self.log.error ('Error reading your places database.')
163
                self.log.error ('Upgrade your Python-Sqlite3 Library')
164
                return None
165
            else:
166
                self.log.error(error)
167
                return None
168
 
5 t00m 169
    def filter_chrome_history(self, placesDB):
6 t00m 170
        sndict = {}
7 t00m 171
        self.log.debug('Searching SAP Notes in Chrome history')
3 t00m 172
        shutil.copy(placesDB, "history")
6 t00m 173
        conn = sqlite3.connect("history")
174
        c = conn.cursor()
3 t00m 175
        try:
176
            select_statement = "SELECT urls.url, date(visits.visit_time/1000000-11644473600, 'unixepoch') FROM urls, visits WHERE urls.id = visits.url;"
6 t00m 177
            c.execute(select_statement)
178
            for row in c:
179
                url = str(row[0])
180
                date = str(row[1])
181
                if '/support/notes/' in url:
182
                    snid = self.validate(url)
183
                    if snid is not None:
184
                        try:
185
                            sndate = sndict[snid]
186
                            if date > sndate:
187
                                sndict[snid] = date
188
                        except:
189
                            sndict[snid] = date
190
            self.log.debug ("Chrome: %d SAP Notes found" % len(sndict))
191
            return sndict
3 t00m 192
        except Exception as error:
193
            self.log.error (error)
194
            return None
195
 
196
 
6 t00m 197
    def get_uniq_sapnotes(self, sndicts):
198
        usndict = {}
199
        for sndict in sndicts:
7 t00m 200
            if sndict is not None:
201
                for snid in sndict:
202
                    try:
203
                        date = usndict[snid]
204
                        if sndict[snid] > date:
205
                            usndict[snid] = sndict[snid]
206
                    except:
6 t00m 207
                        usndict[snid] = sndict[snid]
7 t00m 208
            else:
209
                self.log.debug("Possibly there is no data for current dictionary")
6 t00m 210
        self.log.debug("Unique SAP Notes for all browsers: %d" % len(usndict))
211
        return usndict
3 t00m 212