Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
maurosoria
GitHub Repository: maurosoria/dirsearch
Path: blob/master/lib/report/factory.py
896 views
1
# -*- coding: utf-8 -*-
2
# This program is free software; you can redistribute it and/or modify
3
# it under the terms of the GNU General Public License as published by
4
# the Free Software Foundation; either version 2 of the License, or
5
# (at your option) any later version.
6
#
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
# GNU General Public License for more details.
11
#
12
# You should have received a copy of the GNU General Public License
13
# along with this program; if not, write to the Free Software
14
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15
# MA 02110-1301, USA.
16
#
17
# Author: Mauro Soria
18
19
from abc import ABC, abstractmethod
20
21
from lib.core.decorators import locked
22
from lib.core.exceptions import CannotConnectException, FileExistsException
23
from lib.utils.file import FileUtils
24
25
26
class BaseReport(ABC):
27
@abstractmethod
28
def initiate(self):
29
raise NotImplementedError
30
31
@abstractmethod
32
def save(self, result):
33
raise NotImplementedError
34
35
36
class FileReportMixin:
37
def initiate(self, file):
38
FileUtils.create_dir(FileUtils.parent(file))
39
if FileUtils.exists(file) and not FileUtils.is_empty(file):
40
self.validate(file)
41
else:
42
self.write(file, self.new())
43
44
def validate(self, file):
45
try:
46
self.parse(file)
47
except Exception:
48
raise FileExistsException(f"Output file {file} already exists")
49
50
def parse(self, file):
51
return open(file, "r").read()
52
53
def write(self, file, data):
54
with open(file, "w") as fh:
55
fh.write(data)
56
57
def finish(self):
58
pass
59
60
61
class SQLReportMixin:
62
# Reuse the connection
63
_conn = None
64
65
def get_connection(self, database):
66
# Reuse the old connection
67
if not self._reuse:
68
return self.connect(database)
69
70
if not self._conn:
71
self._conn = self.connect(database)
72
73
return self._conn
74
75
def get_drop_table_query(self, table):
76
return (f'''DROP TABLE IF EXISTS "{table}";''',)
77
78
def get_create_table_query(self, table):
79
return (f'''CREATE TABLE "{table}" (
80
time TIMESTAMP,
81
url TEXT,
82
status_code INTEGER,
83
content_length INTEGER,
84
content_type TEXT,
85
redirect TEXT
86
);''',)
87
88
def get_insert_table_query(self, table, values):
89
return (f'''INSERT INTO "{table}" (time, url, status_code, content_length, content_type, redirect)
90
VALUES
91
(%s, %s, %s, %s, %s, %s);''', values)
92
93
def initiate(self, database, table):
94
try:
95
conn = self.get_connection(database)
96
except Exception as e:
97
raise CannotConnectException(f"Cannot connect to the SQL database: {str(e)}")
98
99
cursor = conn.cursor()
100
101
cursor.execute(*self.get_drop_table_query(table))
102
cursor.execute(*self.get_create_table_query(table))
103
conn.commit()
104
105
if not self._reuse:
106
conn.close()
107
108
@locked
109
def save(self, database, table, result):
110
conn = self.get_connection(database)
111
cursor = conn.cursor()
112
113
cursor.execute(
114
*self.get_insert_table_query(
115
table,
116
(
117
result.datetime,
118
result.url,
119
result.status,
120
result.length,
121
result.type,
122
result.redirect,
123
),
124
)
125
)
126
conn.commit()
127
128
if not self._reuse:
129
conn.close()
130
131
def finish(self):
132
if self._conn:
133
self._conn.close()
134
135