Skip to content
This repository was archived by the owner on Feb 22, 2025. It is now read-only.

Commit 44f0782

Browse files
authored
Merge pull request #798 from rix1337/dev
v.20.1.2 - Prevent SQL-Injection in sqlite db
2 parents c323ee8 + a930e2d commit 44f0782

File tree

4 files changed

+52
-52
lines changed

4 files changed

+52
-52
lines changed

feedcrawler/providers/sqlite_database.py

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ def __init__(self, table):
6464
self._conn = sqlite3.connect(shared_state.values["dbfile"], check_same_thread=False, timeout=5)
6565
self._table = table
6666
if not self._conn.execute(
67-
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '%s';" % self._table).fetchall():
68-
self._conn.execute("CREATE TABLE %s (key, value)" % self._table)
67+
f"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{self._table}';").fetchall():
68+
self._conn.execute(f"CREATE TABLE {self._table} (key, value)")
6969
self._conn.commit()
7070
except sqlite3.OperationalError as e:
7171
try:
@@ -75,78 +75,78 @@ def __init__(self, table):
7575
self._conn = sqlite3.connect(shared_state.values["dbfile"], check_same_thread=False, timeout=10)
7676
self._table = table
7777
if not self._conn.execute(
78-
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '%s';" % self._table).fetchall():
79-
self._conn.execute("CREATE TABLE %s (key, value)" % self._table)
78+
f"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{self._table}';").fetchall():
79+
self._conn.execute(f"CREATE TABLE {self._table} (key, value)")
8080
self._conn.commit()
8181
shared_state.logger.debug("Zugriff auf FeedCrawler.db nach Wartezeit war erfolgreich.")
8282
except sqlite3.OperationalError as e:
8383
print("Fehler bei Zugriff auf FeedCrawler.db: ", str(e))
8484

8585
def count(self):
86-
res = self._conn.execute("SELECT Count() FROM %s" % self._table).fetchone()
86+
res = self._conn.execute(f"SELECT Count() FROM {self._table}").fetchone()
8787
return res[0] if res else None
8888

8989
def retrieve(self, key):
90-
res = self._conn.execute(
91-
"SELECT value FROM %s WHERE key='%s'" % (self._table, key)).fetchone()
90+
query = f"SELECT value FROM {self._table} WHERE key=?"
91+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
92+
res = self._conn.execute(query, (key,)).fetchone()
9293
return res[0] if res else None
9394

9495
def retrieve_all(self, key):
95-
res = self._conn.execute(
96-
"SELECT distinct value FROM %s WHERE key='%s' ORDER BY value" % (self._table, key))
97-
items = []
98-
for r in res:
99-
items.append(str(r[0]))
96+
query = f"SELECT distinct value FROM {self._table} WHERE key=? ORDER BY value"
97+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
98+
res = self._conn.execute(query, (key,))
99+
items = [str(r[0]) for r in res]
100100
return items
101101

102102
def retrieve_all_beginning_with(self, key):
103-
res = self._conn.execute(
104-
"SELECT distinct key FROM " + self._table + " WHERE key LIKE '" + key + "%'")
105-
items = []
106-
for r in res:
107-
items.append(str(r[0]))
103+
query = f"SELECT distinct key FROM {self._table} WHERE key LIKE ?"
104+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
105+
res = self._conn.execute(query, (f"{key}%",))
106+
items = [str(r[0]) for r in res]
108107
return items
109108

110109
def retrieve_all_titles(self):
111-
res = self._conn.execute(
112-
"SELECT distinct key, value FROM %s ORDER BY key" % self._table)
113-
items = []
114-
for r in res:
115-
items.append([str(r[0]), str(r[1])])
110+
query = f"SELECT distinct key, value FROM {self._table} ORDER BY key"
111+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
112+
res = self._conn.execute(query)
113+
items = [[str(r[0]), str(r[1])] for r in res]
116114
return items if items else None
117115

118116
def retrieve_all_titles_unordered(self):
119-
res = self._conn.execute(
120-
"SELECT distinct key, value FROM %s" % self._table)
121-
items = []
122-
for r in res:
123-
items.append([str(r[0]), str(r[1])])
117+
query = f"SELECT distinct key, value FROM {self._table}"
118+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
119+
res = self._conn.execute(query)
120+
items = [[str(r[0]), str(r[1])] for r in res]
124121
return items if items else None
125122

126123
def store(self, key, value):
127-
self._conn.execute("INSERT INTO '%s' VALUES ('%s', '%s')" %
128-
(self._table, key, value))
124+
query = f"INSERT INTO {self._table} VALUES (?, ?)"
125+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
126+
self._conn.execute(query, (key, value))
129127
self._conn.commit()
130128

131129
def update_store(self, key, value):
132-
self._conn.execute("DELETE FROM %s WHERE key='%s'" %
133-
(self._table, key))
134-
self._conn.execute("INSERT INTO '%s' VALUES ('%s', '%s')" %
135-
(self._table, key, value))
130+
delete_query = f"DELETE FROM {self._table} WHERE key=?"
131+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
132+
self._conn.execute(delete_query, (key,))
133+
insert_query = f"INSERT INTO {self._table} VALUES (?, ?)"
134+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
135+
self._conn.execute(insert_query, (key, value))
136136
self._conn.commit()
137137

138138
def delete(self, key):
139-
self._conn.execute("DELETE FROM %s WHERE key='%s'" %
140-
(self._table, key))
139+
query = f"DELETE FROM {self._table} WHERE key=?"
140+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
141+
self._conn.execute(query, (key,))
141142
self._conn.commit()
142143

143144
def reset(self):
144-
self._conn.execute("DROP TABLE IF EXISTS %s" % self._table)
145+
self._conn.execute(f"DROP TABLE IF EXISTS {self._table}")
145146
self._conn.commit()
146147

147148
def rename_table(self, new_name):
148-
self._conn.execute("ALTER TABLE '%s' RENAME TO '%s'" %
149-
(self._table, new_name))
149+
self._conn.execute(f"ALTER TABLE '{self._table}' RENAME TO '{new_name}'")
150150
self._conn.commit()
151151

152152

@@ -155,23 +155,22 @@ def __init__(self, table):
155155
self._conn = sqlite3.connect(shared_state.values["dbfile"], check_same_thread=False, timeout=10)
156156
self._table = table
157157
if not self._conn.execute(
158-
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '%s';" % self._table).fetchall():
159-
self._conn.execute(
160-
'''CREATE TABLE %s (key)''' % self._table)
158+
f"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{self._table}';").fetchall():
159+
self._conn.execute(f"CREATE TABLE {self._table} (key)")
161160
self._conn.commit()
162161

163162
def retrieve(self):
164-
res = self._conn.execute(
165-
"SELECT distinct key FROM %s ORDER BY key" % self._table)
163+
res = self._conn.execute(f"SELECT distinct key FROM {self._table} ORDER BY key")
166164
items = []
167165
for r in res:
168166
items.append(str(r[0]))
169167
return items if items else None
170168

171169
def store(self, key):
172170
key = feedcrawler.providers.common_functions.keep_alphanumeric_with_special_characters(key)
173-
self._conn.execute("INSERT INTO '%s' VALUES ('%s')" %
174-
(self._table, key))
171+
query = f"INSERT INTO {self._table} VALUES (?)"
172+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
173+
self._conn.execute(query, (key,))
175174
self._conn.commit()
176175

177176
def store_list(self, keys):
@@ -196,10 +195,11 @@ def store_list(self, keys):
196195
self._conn.commit()
197196

198197
def delete(self, key):
199-
self._conn.execute("DELETE FROM %s WHERE key='%s'" %
200-
(self._table, key))
198+
query = f"DELETE FROM {self._table} WHERE key=?"
199+
# using this parameterized query to prevent SQL injection, which requires a tuple as second argument
200+
self._conn.execute(query, (key,))
201201
self._conn.commit()
202202

203203
def reset(self):
204-
self._conn.execute("DROP TABLE IF EXISTS %s" % self._table)
204+
self._conn.execute(f"DROP TABLE IF EXISTS {self._table}")
205205
self._conn.commit()

feedcrawler/providers/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
def get_version():
11-
return "20.1.1"
11+
return "20.1.2"
1212

1313

1414
def create_version_file():

feedcrawler/web_interface/vuejs_frontend/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

feedcrawler/web_interface/vuejs_frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "feedcrawler-web",
3-
"version": "20.1.1",
3+
"version": "20.1.2",
44
"type": "module",
55
"scripts": {
66
"dev": "vite",

0 commit comments

Comments
 (0)