aboutsummaryrefslogtreecommitdiffstats
path: root/src/util.cpp
diff options
context:
space:
mode:
authorMatt Strapp <matt@mattstrapp.net>2022-04-25 17:48:52 -0500
committerMatt Strapp <matt@mattstrapp.net>2022-04-25 17:49:31 -0500
commit6889e2d66b710c241b3884fc28610a9e6be4e610 (patch)
tree30aabe5e28a4306c41d7d73a248ed174bd36f0a5 /src/util.cpp
downloadcsci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar.gz
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar.bz2
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar.lz
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar.xz
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.tar.zst
csci4211-6889e2d66b710c241b3884fc28610a9e6be4e610.zip
A
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp398
1 files changed, 398 insertions, 0 deletions
diff --git a/src/util.cpp b/src/util.cpp
new file mode 100644
index 0000000..142fcbd
--- /dev/null
+++ b/src/util.cpp
@@ -0,0 +1,398 @@
+#include <string>
+#include <string.h>
+#include <cstddef>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <sys/timeb.h>
+
+#include "util.hpp"
+
+#define VALID_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+
+enum Command parse_command(char* line){
+ /* Find a valid command in the first word of the line (case sensitive)
+ args:
+ line (char*): string of characters from the input file
+
+ returns:
+ (command): Returns the found command. Returns else if first word is invalid.
+ */
+ if (line == NULL){
+ return INVALID;
+ }
+
+ char* rest;
+ char* tok = strtok_r(line, " ", &rest);
+
+ if (tok == NULL){
+ return INVALID;
+ }
+
+ // REGISTER [username] [password]
+ if (strcmp(tok, "REGISTER") == 0){
+ char* username = strtok_r(rest, " ", &rest);
+ if(!isValidUsername(username)) return INVALID;
+
+ char* password = strtok_r(rest, " ", &rest);
+ if(password == NULL) return INVALID;
+ if(!isValidPassword(password)) return INVALID;
+
+ char* misc = strtok_r(rest, " ", &rest);
+ if(misc != NULL) return INVALID;
+
+ return REGISTER;
+ }
+
+ // LOGIN [username] [password]
+ if (strcmp(tok, "LOGIN") == 0){
+ char* username = strtok_r(rest, " ", &rest);
+ if(!isValidUsername(username)) return INVALID;
+
+ char* password = strtok_r(rest, " ", &rest);
+ if(password == NULL) return INVALID;
+ if(!isValidPassword(password)) return INVALID;
+
+ char* misc = strtok_r(rest, " ", &rest);
+ if(misc != NULL) return INVALID;
+
+ return LOGIN;
+ }
+
+ // LOGOUT
+ if (strcmp(tok, "LOGOUT") == 0){
+ char* misc = strtok_r(rest, " ", &rest);
+ if(misc != NULL) return INVALID;
+
+ return LOGOUT;
+ }
+
+ // SEND [msg]
+ if (strcmp(tok, "SEND") == 0){
+ if (int(strlen(rest) == 0)) return INVALID;
+
+ return SEND;
+ }
+
+ // SEND2 [username] [msg]
+ if (strcmp(tok, "SEND2") == 0){
+ char* username = strtok_r(rest, " ", &rest);
+ if(!isValidUsername(username)) return INVALID;
+
+ if (int(strlen(rest) == 0)) return INVALID;
+
+ return SEND2;
+ }
+
+ // SENDA [msg]
+ if (strcmp(tok, "SENDA") == 0){
+ if (int(strlen(rest) == 0)) return INVALID;
+
+ return SENDA;
+ }
+
+ // SENDA2 [username] [msg]
+ if (strcmp(tok, "SENDA2") == 0){
+ char* username = strtok_r(rest, " ", &rest);
+ if(!isValidUsername(username)) return INVALID;
+
+ if (int(strlen(rest) == 0)) return INVALID;
+
+ return SENDA2;
+ }
+
+ // SENDF [local file]
+ if (strcmp(tok, "SENDF") == 0){
+ char* file_name = strtok_r(rest, " ", &rest);
+ if(file_name == NULL) return INVALID;
+
+ if (int(strlen(rest) != 0)) return INVALID;
+
+ return SENDF;
+ }
+
+ // SENDF2 [username] [local file]
+ if (strcmp(tok, "SENDF2") == 0){
+ char* username = strtok_r(rest, " ", &rest);
+ if(!isValidUsername(username)) return INVALID;
+
+ char* file_name = strtok_r(rest, " ", &rest);
+ if(file_name == NULL) return INVALID;
+
+ if (int(strlen(rest) != 0)) return INVALID;
+
+ return SENDF2;
+ }
+
+ // LIST
+ if (strcmp(tok, "LIST") == 0){
+ char* misc = strtok_r(rest, " ", &rest);
+ if(misc != NULL) return INVALID;
+
+ return LIST;
+ }
+
+ // DELAY
+ if (strcmp(tok, "DELAY") == 0){
+ char* delay_time = strtok_r(rest, " ", &rest);
+ if(delay_time == NULL) return INVALID;
+
+ std::string str(delay_time);
+ std::size_t found = str.find_first_not_of("0123456789");
+ if(found != std::string::npos) return INVALID;
+
+ if (int(strlen(rest) != 0)) return INVALID;
+
+ return DELAY;
+ }
+
+ // default
+ return INVALID;
+}
+
+
+bool isValidUsername(char* username){
+ /* Helper function to check if a username string is valid
+ args:
+ username (char*): Username to be tested.
+
+ returns:
+ bool: Username is valid ? true, false
+ */
+ if(username == NULL) return false;
+ else if ((strlen(username) > MAX_USERNAME_LEN)||(strlen(username) < MIN_USERNAME_LEN)) return false;
+ else{
+ std::string str(username);
+ std::size_t found = str.find_first_not_of(VALID_CHARACTERS);
+ if(found != std::string::npos) return false;
+ }
+
+ return true;
+}
+
+
+bool isValidPassword(char* password){
+ if(password == NULL) return false;
+ else if ((strlen(password) > MAX_PASSWORD_LEN)||(strlen(password) < MIN_PASSWORD_LEN)) return false;
+ else{
+ std::string str(password);
+ std::size_t found = str.find_first_not_of(VALID_CHARACTERS);
+ if(found != std::string::npos) return false;
+ }
+
+ return true;
+}
+
+
+void Error(const char * format, ...) {
+ char msg[4096];
+ va_list argptr;
+ va_start(argptr, format);
+ vsprintf(msg, format, argptr);
+ va_end(argptr);
+ fprintf(stderr, "Error: %s\n", msg);
+ exit(-1);
+}
+
+void Log(const char * format, ...) {
+ char msg[2048];
+ va_list argptr;
+ va_start(argptr, format);
+ vsprintf(msg, format, argptr);
+ va_end(argptr);
+ fprintf(stderr, "%s\n", msg);
+}
+
+// convert buf[0:3] to int
+void buf2i(BYTE * buf, int &i){
+ // No way to avoid Segmentation fault. Some bytes may be 0
+ i = 0;
+ i += buf[3];
+ i += ((int)(buf[2])) << 8;
+ i += ((int)(buf[1])) << 16;
+ i += ((int)(buf[0])) << 24;
+}
+
+// convert int to buf[4] where buf[0] contains MSB's and buf[3] contains LSB's
+void i2buf(int &i, BYTE * buf){
+ // No way to avoid Segmentation fault. Some bytes may be 0
+ buf[0] = (BYTE)((i & 0xFF000000) >> 24);
+ buf[1] = (BYTE)((i & 0x00FF0000) >> 16);
+ buf[2] = (BYTE)((i & 0x0000FF00) >> 8);
+ buf[3] = (BYTE)(i & 0x000000FF);
+}
+
+const char * com2str(enum Command command){
+ const char * com2str[] = {"REGISTER",
+ "LOGIN",
+ "LOGOUT",
+ "SEND",
+ "SEND2",
+ "SENDA",
+ "SENDA2",
+ "SENDF",
+ "SENDF2",
+ "LIST",
+ "DELAY",
+ "GETF",
+ "PING",
+ "CONNECT",
+ "",
+ "INVALID"
+ };
+ return com2str[command];
+}
+
+// Computes the difference between times a and b in seconds
+// a - b = result
+double timeDifference(struct timeb a, struct timeb b){
+ return (a.time + a.millitm / (double) 1000.0f) - (b.time + b.millitm / (double) 1000.0f);
+}
+
+int getNumEntries(const char* database){
+ FILE* fp = fopen(database, "r");
+ if (!fp){
+ Log("Username check failed to open the file: %s", database);
+ return -1;
+ }
+
+ int numEntries = 0;
+
+ char line[LINE_SIZE] = {0};
+ while(fgets(line, LINE_SIZE, fp) != NULL){
+ char* new_line_pos = strchr(line, '\n');
+ if(new_line_pos != NULL)
+ *new_line_pos = 0;
+ // Including blank lines as entries. Don't use any blank lines.
+ numEntries++;
+ memset(line, 0, LINE_SIZE);
+ }
+
+ fclose(fp);
+ return numEntries;
+}
+
+// User/password is in registry: true
+// User/password is not in registry: false
+bool loginQuery(const char * database, char* username, char* password){
+ FILE* fp = fopen(database, "r");
+ if (!fp){
+ Log("Registry check failed to open the file: %s", database);
+ return false;
+ }
+
+ char line[LINE_SIZE] = {0};
+ while(fgets(line, LINE_SIZE, fp) != NULL){
+ char* new_line_pos = strchr(line, '\n');
+ if(new_line_pos != NULL)
+ *new_line_pos = 0;
+
+ char* rest;
+ char* usr = strtok_r(line, " ", &rest);
+ char* pswd = strtok_r(rest, " ", &rest);
+
+ //Log("username: |%s| Password: |%s|", usr, pswd);
+
+ if((strcmp(username, usr) == 0) && (strcmp(password, pswd) == 0)){
+ fclose(fp);
+ return true;
+ }
+
+ memset(line, 0, LINE_SIZE);
+ }
+
+ fclose(fp);
+ return false;
+}
+
+// User is in registry: true
+// User is not in registry: false
+bool usernameQuery(const char * database, char* username){
+ FILE* fp = fopen(database, "r");
+ if (!fp){
+ Log("Username check failed to open the file: %s", database);
+ return false;
+ }
+
+ char line[LINE_SIZE] = {0};
+ while(fgets(line, LINE_SIZE, fp) != NULL){
+ char* new_line_pos = strchr(line, '\n');
+ if(new_line_pos != NULL)
+ *new_line_pos = 0;
+
+ char* rest;
+ char* usr = strtok_r(line, " ", &rest);
+
+ //Log("username: |%s|", usr);
+
+ if(strcmp(username, usr) == 0){
+ fclose(fp);
+ return true;
+ }
+
+ memset(line, 0, LINE_SIZE);
+ }
+
+ fclose(fp);
+ return false;
+}
+
+void recordEntry(const char * database, char* key, char* value){
+ FILE* fp = fopen(database, "a");
+
+ if (!fp){
+ Log("Registry append failed to open the file: %s", database);
+ return;
+ }
+
+ char line[LINE_SIZE] = {0};
+ strcat(line, key);
+ strcat(line, " ");
+ strcat(line, value);
+ strcat(line, "\n");
+
+ fputs(line, fp);
+ fclose(fp);
+}
+
+void clearDatabase(const char * database){
+ FILE* fp = fopen(database, "w");
+ fclose(fp);
+}
+
+
+int buf2file(BYTE* buf, int nbytes, char* filename){
+ FILE* f = fopen(filename, "w");
+ if(!f) return -1;
+
+ fwrite(buf, 1, nbytes, f);
+ fclose(f);
+ return 0;
+}
+
+
+int file2buf(char* filename, BYTE* buf){
+ FILE* f = fopen(filename, "r");
+ if(!f){
+ Log("Error: Cannot open %s", filename);
+ return -1;
+ }
+
+ fseek(f, 0, SEEK_END); // jump to end of file
+ long nbytes = ftell(f); // find current offset on file f
+ fseek(f, 0, SEEK_SET); // jump to beginning of file
+
+ if(nbytes > MAX_REQUEST_SIZE){
+ Log("Error: File %s is too big: %d", filename, nbytes);
+ return -1;
+ }
+
+ int nread = fread(buf, 1, nbytes, f);
+ if(nread != nbytes){
+ Log("Error: Byte count mismatch with fread: %d, %d", nbytes, nread);
+ return -1;
+ }
+
+ fclose(f);
+ return nbytes;
+}