Skip to content

Commit

Permalink
db.d: restore function for counting users
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiascode committed Sep 5, 2024
1 parent b1f7b39 commit 2c7c93e
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 73 deletions.
166 changes: 97 additions & 69 deletions src/db.d
Original file line number Diff line number Diff line change
Expand Up @@ -58,118 +58,144 @@ class Sdb

void init_config_option(string option, string value)
{
query("INSERT OR IGNORE INTO %s(option, value) VALUES('%s', '%s');".format(
config_table, option, escape(value)));
query(
"INSERT OR IGNORE INTO %s(option, value) VALUES('%s', '%s');".format(
config_table, option, escape(value)
));
}

void init_config_option(string option, uint value)
{
query("INSERT OR IGNORE INTO %s(option, value) VALUES('%s', %d);".format(
config_table, option, value));
query(
"INSERT OR IGNORE INTO %s(option, value) VALUES('%s', %d);".format(
config_table, option, value
));
}

void set_config_value(string option, string value)
{
query("REPLACE INTO %s(option, value) VALUES('%s', '%s');".format(
config_table, option, escape(value)));
query(
"REPLACE INTO %s(option, value) VALUES('%s', '%s');".format(
config_table, option, escape(value)
));
}

void set_config_value(string option, uint value)
{
query("REPLACE INTO %s(option, value) VALUES('%s', %d);".format(
config_table, option, value));
query(
"REPLACE INTO %s(option, value) VALUES('%s', %d);".format(
config_table, option, value
));
}

string get_config_value(string option)
{
const res = query("SELECT value FROM %s WHERE option = '%s';".format(
config_table, option));
return res[0][0];
return query(
"SELECT value FROM %s WHERE option = '%s';".format(
config_table, option)
)[0][0];
}

void add_admin(string username, uint level = 0)
{
query("REPLACE INTO %s(username, level) VALUES('%s', %d);".format(
admins_table, escape(username), level));
query(
"REPLACE INTO %s(username, level) VALUES('%s', %d);".format(
admins_table, escape(username), level
));
}

void del_admin(string username)
{
query("DELETE FROM %s WHERE username = '%s';".format(
admins_table, escape(username)));
query(
"DELETE FROM %s WHERE username = '%s';".format(
admins_table, escape(username)
));
}

string[] admins()
{
const res = query("SELECT username FROM %s;".format(admins_table));
string[] ret;

foreach (record ; res) ret ~= record[0];
foreach (record ; query("SELECT username FROM %s;".format(admins_table)))
ret ~= record[0];
return ret;
}

bool is_admin(string username)
{
const res = query("SELECT username FROM %s WHERE username = '%s';".format(
admins_table, escape(username)));
return res.length > 0;
return query(
"SELECT username FROM %s WHERE username = '%s';".format(
admins_table, escape(username)
)).length > 0;
}

void user_update_field(string username, string field, string value)
{
query("UPDATE %s SET %s = '%s' WHERE username = '%s';".format(
users_table, field, escape(value), escape(username)));
query(
"UPDATE %s SET %s = '%s' WHERE username = '%s';".format(
users_table, field, escape(value), escape(username)
));
}

void user_update_field(string username, string field, uint value)
{
query("UPDATE %s SET %s = %d WHERE username = '%s';".format(
users_table, field, value, escape(username)));
query(
"UPDATE %s SET %s = %d WHERE username = '%s';".format(
users_table, field, value, escape(username)
));
}

bool user_exists(string username)
{
const res = query("SELECT username FROM %s WHERE username = '%s';".format(
users_table, escape(username)));
return res.length > 0;
return query(
"SELECT username FROM %s WHERE username = '%s';".format(
users_table, escape(username)
)).length > 0;
}

string get_pass(string username)
{
const res = query("SELECT password FROM %s WHERE username = '%s';".format(
users_table, escape(username)));
return res[0][0];
return query(
"SELECT password FROM %s WHERE username = '%s';".format(
users_table, escape(username)
))[0][0];
}

void add_user(string username, string password)
{
query("INSERT INTO %s(username, password) VALUES('%s', '%s');".format(
users_table, escape(username), escape(password)));
query(
"INSERT INTO %s(username, password) VALUES('%s', '%s');".format(
users_table, escape(username), escape(password)
));
}

bool is_banned(string username)
{
const res = query("SELECT banned FROM %s WHERE username = '%s';".format(
users_table, escape(username)));
const res = query(
"SELECT banned FROM %s WHERE username = '%s';".format(
users_table, escape(username)
));

if (res.length == 1)
return(atoi(res[0][0]) != 0);
if (res.length > 0)
return atoi(res[0][0]) > 0;

return false;
}

bool get_user(string username, out uint speed, out uint upload_number, out uint something, out uint shared_files, out uint shared_folders)
{
debug(db) writeln("DB: Requested ", username, "'s info...");
const res = query("SELECT speed,ulnum,files,folders FROM %s WHERE username = '%s';".format(
users_table, escape(username)));
const res = query(
"SELECT speed,ulnum,files,folders FROM %s WHERE username = '%s';".format(
users_table, escape(username)
));

if (res.length > 0) {
const u = res[0];
const user = res[0];

speed = atoi(u[0]);
upload_number = atoi(u[1]);
shared_files = atoi(u[2]);
shared_folders = atoi(u[3]);
speed = atoi(user[0]);
upload_number = atoi(user[1]);
shared_files = atoi(user[2]);
shared_folders = atoi(user[3]);
something = 0;
return true;
}
Expand All @@ -179,16 +205,19 @@ class Sdb
bool get_user(string username, string password, out uint speed, out uint upload_number, out uint shared_files, out uint shared_folders, out uint privileges)
{
debug(db) writeln("DB: Requested ", username, "'s info...");
const res = query("SELECT speed,ulnum,files,folders,privileges FROM %s WHERE username = '%s' AND password = '%s';".format(
users_table, escape(username), escape(password)));
const res = query(
"SELECT speed,ulnum,files,folders,privileges FROM %s WHERE username = '%s' AND password = '%s';".format(
users_table, escape(username), escape(password)
));

if (res.length > 0) {
const u = res[0];
const user = res[0];

speed = atoi(u[0]);
upload_number = atoi(u[1]);
shared_files = atoi(u[2]);
shared_folders = atoi(u[3]);
privileges = atoi(u[4]);
speed = atoi(user[0]);
upload_number = atoi(user[1]);
shared_files = atoi(user[2]);
shared_folders = atoi(user[3]);
privileges = atoi(user[4]);
return true;
}
return false;
Expand All @@ -197,19 +226,23 @@ class Sdb
string[] usernames(string filter_field = null, uint min = 1, uint max = -1)
{
string[] ret;
string[][] res;

if (!filter_field) {
res = query("SELECT username FROM %s;".format(users_table)); // all rows
}
else {
res = query("SELECT username FROM %s WHERE %s BETWEEN %d AND %d;".format(
users_table, escape(filter_field), min, max));
}
foreach (record ; res) ret ~= record[0];
auto query_str = "SELECT username FROM %s".format(users_table);
if (filter_field) query_str ~= " WHERE %s BETWEEN %d AND %d".format(
escape(filter_field), min, max
);
foreach (record ; query(query_str)) ret ~= record[0];
return ret;
}

uint num_users(string filter_field = null, uint min = 1, uint max = -1)
{
auto query_str = "SELECT COUNT(1) FROM %s".format(users_table);
if (filter_field) query_str ~= " WHERE %s BETWEEN %d AND %d".format(
escape(filter_field), min, max

This comment has been minimized.

Copy link
@slook

slook Sep 5, 2024

Contributor

Invalid query syntax, it must always end with a semi-colon ;

Especially where a string variable is on the end, because that's where arbitrary structured code could get injected.

This comment has been minimized.

Copy link
@mathiascode

mathiascode Sep 5, 2024

Author Member

This comment has been minimized.

Copy link
@slook

slook Sep 5, 2024

Contributor

It's better but not it is still not safe enough having a free string entry as the last component of the statement like this, because filter_value can accept any arbitrary string that may include sub-queries containing anything like additional SELECT() expressions or PRAGMA() statements or whatever else.

Ideally we should constrain the string given via filter_value to validate that the input text does actually match one of the column names that do actually exist in the table...

... Any erroneous column name value given as input should be silently ignored by returning null or 0 to the caller in order to avoid any possibility getting a different result from the function or crashing the database engine.

);
return atoi(query(query_str)[0][0]);
}

@trusted
string[][] query(string query)
{
Expand Down Expand Up @@ -252,12 +285,7 @@ class Sdb

uint atoi(string str)
{
try {
const i = to!uint(str);
return i;
}
catch (ConvException e) {
return 0;
}
try {return to!uint(str);}
catch (ConvException e) {return 0;}
}
}
8 changes: 4 additions & 4 deletions src/soulsetup.d
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ void info()
auto menu = new Menu(
"Soulsetup for Soulfind %s (compiled on %s)".format(VERSION, __DATE__)
);
menu.info = "\t%d registered users".format(sdb.usernames.length);
menu.info ~= "\n\t%d privileged users".format(sdb.usernames("privileges").length);
menu.info ~= "\n\t%d banned users".format(sdb.usernames("banned").length);
menu.info = "\t%d registered users".format(sdb.num_users);
menu.info ~= "\n\t%d privileged users".format(sdb.num_users("privileges"));
menu.info ~= "\n\t%d banned users".format(sdb.num_users("banned"));

menu.add("1", "Recount", &info);
menu.add("q", "Return", &main_menu);
Expand All @@ -217,7 +217,7 @@ void info()

void banned_users()
{
auto menu = new Menu("Banned users (%d)".format(sdb.usernames("banned").length));
auto menu = new Menu("Banned users (%d)".format(sdb.num_users("banned")));

menu.add("1", "Ban user", &ban_user);
menu.add("2", "Unban user", &unban_user);
Expand Down

0 comments on commit 2c7c93e

Please sign in to comment.