diff --git a/Makefile b/Makefile index e3f4a61..090b773 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS := -ggdb -Wall -pedantic +CFLAGS := -ggdb -Wall -pedantic -lpq SRC_DIR := src OBJ_DIR := src/obj diff --git a/src/db.c b/src/db.c new file mode 100644 index 0000000..5a15faa --- /dev/null +++ b/src/db.c @@ -0,0 +1,129 @@ +#include "db.h" +#include +#include + +#define UNUSED(x) (void)(x) +#define Q_LEN 128 + +static PGconn *conn = NULL; +static PGresult *res = NULL; + +// #define USR_NOT_FOUND "User with such credentials is not found!" + +static void clearRes() { + PQclear(res); + res = NULL; +} + +static int terminate(int code) { + if (code != 0) + fprintf(stderr, "%s\n", PQerrorMessage(conn)); + + if (res != NULL) + PQclear(res); + + if (conn != NULL) + PQfinish(conn); + + return code; +} + +static int exit_query(int code) { + if (code != 0) + fprintf(stderr, "%s\n", PQerrorMessage(conn)); + + if (res != NULL) + PQclear(res); + + return code; +} + +static void processNotice(void *arg, const char *message) { + UNUSED(arg); + UNUSED(message); + + // do nothing +} + +int init_connection() { + // TODO: get from external configs + conn = PQconnectdb("user=postgres password=dobro host=127.0.0.1 dbname=bbs"); + + if (PQstatus(conn) != CONNECTION_OK) + return terminate(1); + + int server_ver = PQserverVersion(conn); + char *user = PQuser(conn); + char *db_name = PQdb(conn); + + printf("Connection established! server version: %d, user: %s, db: %s\n", server_ver, + user, db_name); + return exit_query(0); +} + +int db_user_auth(i_auth_t *credentials, o_auth_t *response) { + char query[Q_LEN]; + response->is_logged = 0; + sprintf(query, + "SELECT username, password, privileges " + "FROM users " + "WHERE username= '%s'", + credentials->name); + res = PQexec(conn, query); + + if (PQresultStatus(res) != PGRES_TUPLES_OK && !PQntuples(res)) + return exit_query(1); + + const char *pass = PQgetvalue(res, 0, 1); + if (!strcmp(pass, credentials->pass)) { + response->is_logged = 1; + response->privileges = PQgetvalue(res, 0, 2)[0]; + return exit_query(0); + } + return exit_query(2); +} + +/*s + +int f_main() { + int libpq_ver = PQlibVersion(); + printf("Version of libpq: %d\n", libpq_ver); + + conn = PQconnectdb("user=postgres password=dobro host=127.0.0.1 dbname=bbs"); + if (PQstatus(conn) != CONNECTION_OK) + terminate(1); + + PQsetNoticeProcessor(conn, processNotice, NULL); + + int server_ver = PQserverVersion(conn); + char *user = PQuser(conn); + char *db_name = PQdb(conn); + + printf("Server version: %d\n", server_ver); + printf("User: %s\n", user); + printf("Database name: %s\n", db_name); + + res = PQexec(conn, "SELECT id, username, privileges, email " + "FROM users"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + terminate(1); + + int nrows = PQntuples(res); + for (int i = 0; i < nrows; i++) { + char *id = PQgetvalue(res, i, 0); + char *name = PQgetvalue(res, i, 1); + char *privileges = PQgetvalue(res, i, 2); + char *email = PQgetvalue(res, i, 3); + printf("Id: %s, Name: %s, Privileges: %d, Email: %s, \n", id, name, + privileges[0], email); + } + + printf("Total: %d rows\n", nrows); + + clearRes(); + terminate(0); + + return 0; +} + +*/ \ No newline at end of file diff --git a/src/db.h b/src/db.h new file mode 100644 index 0000000..08e48c7 --- /dev/null +++ b/src/db.h @@ -0,0 +1,12 @@ +typedef struct { + char *name; + char *pass; +} i_auth_t; + +typedef struct { + char privileges; + int is_logged; +} o_auth_t; + +int init_connection(); +int db_user_auth(i_auth_t *credentials, o_auth_t *response); diff --git a/src/deps.mk b/src/deps.mk new file mode 100644 index 0000000..bacbafa --- /dev/null +++ b/src/deps.mk @@ -0,0 +1,8 @@ +client.o: src/client.c src/client.h src/main.h src/file_p.h src/session.h +db.o: src/db.c src/db.h +file_p.o: src/file_p.c src/file_p.h src/main.h src/session.h +main.o: src/main.c src/main.h src/file_p.h src/server.h src/db.h +server.o: src/server.c src/main.h src/session.h src/user.h +session.o: src/session.c src/session.h src/main.h src/client.h \ + src/file_p.h src/user.h +user.o: src/user.c src/main.h src/session.h src/db.h diff --git a/src/main.c b/src/main.c index be2d5d3..ac92581 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,7 @@ #include "main.h" #include "file_p.h" #include "server.h" +#include "db.h" /* *** MAIN *** */ int main(int argc, char *argv[]) { @@ -9,6 +10,7 @@ int main(int argc, char *argv[]) { server_data.welcome_message = get_welcome_mes(); server_data.fl_start = NULL; server_data.fl_current = NULL; + init_connection(); get_files_descriptions(&server_data); server_data.ls = start_server(); server_main_loop(&server_data); diff --git a/src/main.h b/src/main.h index 5aba0c8..c755672 100644 --- a/src/main.h +++ b/src/main.h @@ -18,13 +18,16 @@ enum sess_states { OP_EDIT_USER, OP_LOGIN_USR, OP_LOGIN_PSS, + OP_LOGIN_ANON, OP_WAIT, OP_UPLOAD, OP_UPLOAD_DESCRIPTION, + OP_REGISTER, ERR, FIN }; + enum user_privileges { ADD_FILE = 01, EDIT_FILES = 02, diff --git a/src/session.c b/src/session.c index f4afff0..50e56b5 100644 --- a/src/session.c +++ b/src/session.c @@ -128,38 +128,15 @@ int query_extract_from_buf(session *sess, char **output_line) { void perform_session_action(session *sess, char *line, server_data_t *s_d) { int state = sess->state; - char tmp_buf[256]; int priv; - int tmp_buf_pos; int res; /* while (sess->buf_used) { */ switch (state) { case OP_LOGIN_USR: - res = find_user(line); - if (res == -2) { - sess->state = ERR; - sess->reason = EXIT; - session_send_string(sess, "Bye!"); - break; - } - sess->userpos = res; - sess->state = OP_LOGIN_PSS; - session_send_string(sess, "password> "); + process_user_name(line, sess); break; case OP_LOGIN_PSS: - if (sess->userpos == -1) { - sess->state = ERR; - sess->reason = LOGIN; - } else { - if (login(sess, line)) { - sess->state = OP_WAIT; - sprintf(tmp_buf, "Welcome, %s\n", sess->uname); - session_send_string(sess, tmp_buf); - } else { - sess->state = ERR; - sess->reason = LOGIN; - } - } + login(sess, line); break; case OP_WAIT: process_client_command(line, sess, s_d); diff --git a/src/user.c b/src/user.c index e296333..b2f4962 100644 --- a/src/user.c +++ b/src/user.c @@ -3,68 +3,55 @@ #include #include #include +#include "db.h" -long int find_user(char *uname) { - FILE *fptr = fopen(FILE_USER_LIST_NAME, "r"); - - if (fptr == NULL) { - perror(FILE_USER_LIST_NAME); - exit(9); - } - - char *line = NULL; - size_t bsize = WSIZE; - char b_uname[32]; - long int cur_pos = 0; - int lsize = 0; - +int process_user_name(char *uname, session *sess) { if (!strncmp(uname, "exit", sizeof "exit")) { - return -2; + sess->state = ERR; + sess->reason = EXIT; + session_send_string(sess, "Bye!"); + return 1; } - while (getline(&line, &bsize, fptr)) { - if (line[0] == '\b') - break; - sscanf(line, "%s", b_uname); - if (!strcmp(uname, b_uname)) { - line = NULL; - fclose(fptr); - return cur_pos; - } else { - cur_pos += lsize; - line = NULL; - } + if (!strncmp(uname, "register", sizeof "register")) { + sess->state = OP_REGISTER; + session_send_string(sess, "Your username > "); + return 2; } - fclose(fptr); - return -1; + if (!strncmp(uname, "anon", sizeof "anon")) { + sess->state = OP_LOGIN_ANON; + session_send_string(sess, "Welcome, Anonymous!"); + return 3; + } + + sess->uname = malloc(strlen(uname) + 1); + strcpy(sess->uname, uname); + sess->state = OP_LOGIN_PSS; + session_send_string(sess, "password> "); + + return 0; } /* returns 1 if success */ int login(session *sess, char *pass) { - FILE *fptr = fopen(FILE_USER_LIST_NAME, "r"); - fseek(fptr, sess->userpos, SEEK_SET); - int res = 0; - - char *line = NULL; - size_t lsize = WSIZE; - char *pass_tok, *name_tok, *priv_tok; - - getline(&line, &lsize, fptr); - name_tok = strtok(line, " "); - pass_tok = strtok(NULL, " "); - - if (!strcmp(pass_tok, pass)) { - int n_len = pass_tok - name_tok - 1; /* exclude space */ - sess->uname = malloc(n_len + 1); - strncpy(sess->uname, name_tok, n_len); - sess->uname[n_len] = 0; - priv_tok = strtok(NULL, " "); - sess->privileges = (char)atoi(priv_tok); - res = 1; + char tmp_string[256]; + i_auth_t cred; + o_auth_t response; + cred.name = sess->uname; + cred.pass = pass; + db_user_auth(&cred, &response); + if (response.is_logged) { + sess->state = OP_WAIT; + sess->privileges = (char)atoi(&response.privileges); + sprintf(tmp_string, "Welcome, %s\n", sess->uname); + session_send_string(sess, tmp_string); + return 0; + } else { + sess->state = ERR; + sess->reason = EXIT; + return 1; } - fclose(fptr); - return res; } // TODO: синхронизовать c C++ diff --git a/src/user.h b/src/user.h index 3e299bc..7a94a18 100644 --- a/src/user.h +++ b/src/user.h @@ -4,5 +4,5 @@ #include "main.h" int login(session *sess, char *pass); int process_error(session *sess); -long int find_user(char *uname); +int process_user_name(char *uname, session *sess); #endif \ No newline at end of file