Subversion Repositories kim

Rev

Rev 4 | Rev 6 | Go to most recent revision | 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
import argparse
17
from subprocess import check_output
18
 
19
try:
20
    from .logger import Logger
21
    from .project import *
22
except:
23
    from logger import Logger
24
    from project import *
25
 
26
# Constants
27
ROOT = "https://launchpad.support.sap.com/#/notes/"
28
 
29
class Utils:
30
    log = None
31
    def __init__(self):
32
        self.log = Logger('Utils').get_logger()
33
 
34
 
35
    def validate(self, url):
36
        chunk = url[len(ROOT):]
37
        if not chunk[0].isnumeric():
38
            return None
39
 
40
        sep = chunk.find('/')
41
        if sep > 0:
42
            chunk = chunk[:sep]
43
 
44
        numeric = True
45
        for char in chunk:
46
            if not char.isnumeric():
47
                numeric = False
48
 
49
        if numeric:
4 t00m 50
            return str(int(chunk))
3 t00m 51
        else:
52
            return None
53
 
54
 
55
    def get_firefox_profile_dir(self):
56
        if sys.platform in ['linux', 'linux2']:
57
            import subprocess
58
            cmd = "ls -d /home/$USER/.mozilla/firefox/*.default/"
59
            p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE)
60
            PRF_DIR = p.communicate()[0][0:-2]
61
            PRF_DIR = PRF_DIR.decode("utf-8")
62
        elif sys.platform == 'win32':
63
            import os
64
            import glob
65
            APPDATA = os.getenv('APPDATA')
66
            FF_PRF_DIR = "%s\\Mozilla\\Firefox\\Profiles\\" % APPDATA
67
            PATTERN = FF_PRF_DIR + "*default*"
68
            PRF_DIR = glob.glob(PATTERN)[0]
69
 
70
        self.log.debug("FIREFOX PROFILE DIRECTORY: %s", PRF_DIR)
71
 
72
        return PRF_DIR
73
 
74
 
75
    def get_firefox_history(self):
76
        profile_dir = self.get_firefox_profile_dir()
77
        if profile_dir is None:
78
            self.log.warning ("No Firefox profile path found")
79
            return None
80
        elif os.path.isdir(profile_dir) == False:
81
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
82
            return None
83
        else:
84
            placesDB = os.path.join(profile_dir, 'places.sqlite')
85
            self.log.debug("Firefox DB: %s", placesDB)
86
            if os.path.isfile(placesDB):
5 t00m 87
                ff = self.filter_firefox_history(placesDB)
3 t00m 88
                return ff
89
            else:
90
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
91
                return None
92
 
93
 
94
    def get_chrome_profile_dir(self):
95
        if sys.platform in ['linux', 'linux2']:
96
            from subprocess import check_output
97
            try:
98
                cmd = "ls -d /home/$USER/.config/google-chrome/default"
99
                PRF_DIR = check_output(cmd)
100
                if not os.path.exists(PRF_DIR):
101
                    PRF_DIR = None
102
            except:
103
                PRF_DIR = None
104
        elif sys.platform == 'win32':
105
            import os
106
            USERNAME = os.getenv('USERNAME')
107
            PRF_DIR = "C:\\Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default" % USERNAME
108
 
109
        if PRF_DIR is not None:
110
            if type(PRF_DIR) != str:
111
                PRF_DIR = PRF_DIR.decode("utf-8")
112
            self.log.debug("CHROME PROFILE DIRECTORY: %s", PRF_DIR)
113
        else:
114
            PRF_DIR = None
115
            self.log.debug("CHROME PROFILE DIRECTORY: not found")
116
        return PRF_DIR
117
 
118
 
119
    def get_chrome_history(self):
5 t00m 120
        profile_dir = self.get_chrome_profile_dir()
121
        if profile_dir == None:
3 t00m 122
            self.log.warning ("No Chrome profile path found")
123
            return None
5 t00m 124
        elif os.path.isdir(profile_dir) == False:
125
            self.log.warning ('Path Does Not Exist: %s' % profile_dir)
3 t00m 126
            return None
127
        else:
5 t00m 128
            placesDB = os.path.join(profile_dir, 'history')
3 t00m 129
            self.log.debug("Chrome DB: %s", placesDB)
130
            if os.path.isfile(placesDB):
5 t00m 131
                self.filter_chrome_history(placesDB)
3 t00m 132
            else:
133
                self.log.warning ('PlacesDb does not exist: %s' % placesDB)
134
                return None
135
 
5 t00m 136
    def filter_firefox_history(self, placesDB):
3 t00m 137
        sndict = {}
138
        self.log.debug('Printing Firefox history')
139
        try:
140
            conn = sqlite3.connect(placesDB)
141
            c = conn.cursor()
142
            c.execute("select url, date(visit_date/1000000, \
143
              'unixepoch') from moz_places, moz_historyvisits \
144
              where visit_count > 0 and moz_places.id==\
145
              moz_historyvisits.place_id;")
146
 
147
            for row in c:
148
                #~ self.log.info(row)
149
                url = str(row[0])
150
                date = str(row[1])
151
                if '/support/notes/' in url:
152
                    snid = self.validate(url)
153
                    if snid is not None:
154
                        try:
155
                            sndate = sndict[snid]
156
                            if date > sndate:
157
                                sndict[snid] = date
158
                        except:
159
                            sndict[snid] = date
160
 
161
            self.log.debug ("Firefox: %d SAP Notes found" % len(sndict))
162
            return sndict
163
        except Exception as error:
164
            if 'encrypted' in str(error):
165
                self.log.error ('Error reading your places database.')
166
                self.log.error ('Upgrade your Python-Sqlite3 Library')
167
                return None
168
            else:
169
                self.log.error(error)
170
                return None
171
 
5 t00m 172
    def filter_chrome_history(self, placesDB):
3 t00m 173
        self.log.debug('Printing Chrome history')
174
        shutil.copy(placesDB, "history")
175
        c = sqlite3.connect("history")
176
        cursor = c.cursor()
177
        try:
178
            select_statement = "SELECT urls.url, date(visits.visit_time/1000000-11644473600, 'unixepoch') FROM urls, visits WHERE urls.id = visits.url;"
179
            cursor.execute(select_statement)
180
            results = cursor.fetchall() #tuple
181
            count = 0
182
            for url, vtime in results:
183
                if url.startswith("https://launchpad.support.sap.com/#/notes/"):
184
                    SAPNOTE = validate(url)
185
                    if SAPNOTE is not None:
186
                        line = "%s:%s" % (vtime, SAPNOTE)
187
                        self.log.debug("\tFound: %s", line)
188
                        snotes.add(line)
189
                        # ~ fout.write ("%s:%s\n" % (vtime, SAPNOTE))
190
                    count = count + 1
191
            self.log.debug ("Chrome: %d SAP Notes found" % count)
192
        except Exception as error:
193
            self.log.error (error)
194
            return None
195
 
196
 
197
    def printUniqueSAPNotes(self):
198
        unique = set()
199
        for line in snotes:
200
            # Get SAP Note number
201
            sep = line.rfind('/')
202
            snid = line[sep+1:]
203
            unique.add(snid)
204
            # Get visited date and add it to set
205
            sep = line.find(':')
206
            visited = line[:sep]
207
            try:
208
                svdate = dnotes['visited']
209
                if not visited in svdate:
210
                    svdate.add(visited)
211
            except:
212
                svdate = set()
213
                svdate.add(visited)
214
                dnotes[snid] = {}
215
                dnotes[snid]['visited'] = svdate
216
 
217
 
218
 
219
    def get_app_options(self):
220
        parser = argparse.ArgumentParser(description='%s by %s <%s>' % (name, author, author_email))
221
        #~ parser.add_argument('-a', '--all', action='all', help='Get SAP Notes from all browsers')
222
        #~ parser = parser.add_mutually_exclusive_group(required=False)
223
        #~ parser.add_argument('-f', '--firefox', action='store_true', dest='Firefox', help='Get SAP Notes from Firefox')
224
        #~ parser.add_argument('-c', '--chrome', dest='Chrome', help='Get SAP Notes from Chrome')
225
        parser.add_argument('-d',  '--debug',   dest='LOGLEVEL',    help='Increase output verbosity', action='store', default='INFO')
226
        parser.add_argument('-v', '--version', action='version', version='%s %s' % (name, version))
227
        params = parser.parse_args()
228
 
229
        return params