diff options
-rw-r--r-- | main.c | 17 | ||||
-rw-r--r-- | portfolio.c | 194 | ||||
-rw-r--r-- | portfolio.h | 7 | ||||
-rw-r--r-- | rc4.c | 92 | ||||
-rw-r--r-- | rc4.h | 62 | ||||
-rw-r--r-- | string-tick.c | 6 |
6 files changed, 137 insertions, 241 deletions
@@ -22,7 +22,7 @@ int main(int argc, char* argv[]) { portfolio_file_init(); // Portfolio modify operation - int modop = -1, cryptopt; + int modop = -1; // News if (strcmp(cmd, "news") == 0) { @@ -32,18 +32,9 @@ int main(int argc, char* argv[]) { } //Encrypt/decrypt - else if ((strcmp(cmd, "encrypt") == 0 || strcmp(cmd, "decrypt") == 0) && argc == 2) { - cryptopt = strcmp(cmd, "encrypt") == 0; // 1 if encrypting, 0 if decrypting - String* pString = portfolio_file_get_string(); - if (pString != NULL && pString->len != 0) { // NULL if error opening portfolio - String* crypted = rc4_get_crypted_string(pString, NULL, cryptopt); - string_destroy(&pString); - if (crypted != NULL) { // NULL if password error - string_write_portfolio(crypted); - string_destroy(&crypted); - } - } - } + else if ((strcmp(cmd, "encrypt") == 0 || strcmp(cmd, "decrypt") == 0) && argc == 2) + portfolio_encrypt_decrypt(strcmp(cmd, "encrypt") == 0); + // Info else if (strcmp(cmd, "info") == 0 && argc == 3) api_print_info(sym); diff --git a/portfolio.c b/portfolio.c index df7d25936ef9..52393d70af78 100644 --- a/portfolio.c +++ b/portfolio.c @@ -4,81 +4,99 @@ char* portfolio_file; void portfolio_file_init(void) { char* home = getenv("HOME"); - char* path = (char*) malloc(strlen(home) + 30); + char* path = malloc(strlen(home) + 30); pointer_alloc_check(path); sprintf(path, "%s/.tick_portfolio.json", home); portfolio_file = path; } -String* portfolio_file_get_string(void) { - FILE* fp = fopen(portfolio_file, "r"); // Must be w+ because r will fail if portfolio doesn't exist - if (fp == NULL) +String* portfolio_file_get_string(char** password) { + struct stat file_info; + if (stat(portfolio_file, &file_info)) { + puts("Portfolio file doesn't exist."); return NULL; + } + FILE* fp = fopen(portfolio_file, "r"); + if (fp == NULL) { + puts("Error opening portfolio."); + return NULL; + } String* pString = string_init(); - pString->data = realloc(pString->data, 65536); + if (file_info.st_size == 0) + return pString; + pString->len = (size_t) file_info.st_size; + pString->data = realloc(pString->data, pString->len + 1); // Alloc file size pointer_alloc_check(pString->data); - memset(pString->data, '\0', 65536); - fseek(fp, 0, SEEK_END); - pString->len = (size_t) ftell(fp); - fseek(fp, 0, SEEK_SET); + pString->data[pString->len] = '\0'; + if (pString->len == 0) { // If empty file (from portfolio_modify) + fclose(fp); + return pString; + } if (fread(pString->data, sizeof(char), pString->len, fp) != pString->len) { + puts("Error reading file."); fclose(fp); + string_destroy(&pString); return NULL; } fclose(fp); + Json* jobj = json_tokener_parse(pString->data); // Check if encrypted + if (jobj == NULL) { + char* pw = rc4_getPassword(); + puts("Decrypting portfolio..."); + rc4_encode_string(pString, pw); + jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { + puts("Wrong password!"); + free(pw); + string_destroy(&pString); + return NULL; + } + if (password != NULL) + *password = pw; + else free(pw); + } + json_object_put(jobj); return pString; } void portfolio_modify(const char* ticker_name_string, double quantity_shares, double usd_spent, int option) { if (quantity_shares < 0 || usd_spent < 0) { // Negative numbers - printf("You must use positive values.\n"); + puts("You must use positive values."); return; } if (option != SET && quantity_shares == 0 && usd_spent == 0) { // Adding or removing 0 - printf("You cannot add or remove values of 0.\n"); + puts("You cannot add or remove values of 0."); return; } - String* pString = portfolio_file_get_string(); - if (pString == NULL) { - FILE* fp = fopen(portfolio_file, "a"); // Creates if doesn't exist - fclose(fp); + FILE* fp = fopen(portfolio_file, "a"); // Creates portfolio if it doesn't exist + if (fp == NULL) { + puts("Error opening porfolio."); + return; } + fclose(fp); + char* password = NULL; + String* pString = portfolio_file_get_string(&password); + if (pString == NULL) + return; + + // pString is now guaranteed to be valid unencrypted String (may be length 0) + Json* jobj = NULL; - if (pString == NULL || pString->len == 0) { //new file - if (pString != NULL && pString->len == 0) - string_destroy(&pString); + if (pString->len == 0) //new file jobj = json_object_new_array(); - } else jobj = json_tokener_parse(pString->data); //existing file - char* password = NULL; - if (jobj == NULL) { //ENCRYPTED PORTFOLIO - password = rc4_getPassword(); - printf("Decrypting portfolio...\n"); - String* temp = rc4_get_crypted_string(pString, password, DECRYPT); - string_destroy(&pString); - pString = temp; - if (pString == NULL) - return; - jobj = json_tokener_parse(pString->data); - } + else jobj = json_tokener_parse(pString->data); //existing file + int index = portfolio_symbol_index(ticker_name_string, jobj); if (index == -1) { //if not already in portfolio if (option == REMOVE) { printf("You don't have any %s to remove.\n", ticker_name_string); - json_object_put(jobj); - string_destroy(&pString); - if (password != NULL) - free(password); - return; + goto cleanup; } if (strcmp("USD$", ticker_name_string) != 0) { - double* data = api_get_current_price(ticker_name_string); // Curl data and check if NULL + double* data = api_get_current_price(ticker_name_string); // Make sure symbol is valid if (data == NULL) { - printf("Invalid symbol.\n"); - json_object_put(jobj); - string_destroy(&pString); - if (password != NULL) - free(password); - return; + puts("Invalid symbol."); + goto cleanup; } else free(data); } Json* new_object = json_object_new_object(); // Creates new array index and adds values to it @@ -88,9 +106,8 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do json_object_object_add(new_object, "USD_Spent", json_object_new_double(usd_spent)); printf("Added %lf %s bought for %lf to portfolio.\n", quantity_shares, ticker_name_string, usd_spent); } else { //if already in portfolio - Json* current_index = json_object_array_get_idx(jobj, (size_t) index); - double current_shares = json_object_get_double( - json_object_object_get(current_index, "Shares")); // Stores values already there + Json* current_index = json_object_array_get_idx(jobj, (size_t) index); // Store current values + double current_shares = json_object_get_double(json_object_object_get(current_index, "Shares")); double current_spent = json_object_get_double(json_object_object_get(current_index, "USD_Spent")); json_object_object_del(current_index, "Shares"); // Deletes the objects already there json_object_object_del(current_index, "USD_Spent"); @@ -108,70 +125,45 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do current_spent -= usd_spent; if (current_shares < 0 || current_spent < 0) { // If you try to remove more than you have printf("You do not have that many %s to remove.\n", ticker_name_string); - json_object_put(jobj); - string_destroy(&pString); - if (password != NULL) - free(password); - return; + goto cleanup; } printf("Removed %lf %s bought for %lf to portfolio.\n", quantity_shares, ticker_name_string, usd_spent); } if (current_shares == 0 && usd_spent == 0) // Deletes index from portfolio if values are 0 json_object_array_del_idx(jobj, (size_t) index, 1); - else { - json_object_object_add(current_index, "Shares", json_object_new_double( - round(current_shares * 100) / 100)); // Adds computed values to index + else { // Adds computed values to index + json_object_object_add(current_index, "Shares", json_object_new_double(round(current_shares * 100) / 100)); json_object_object_add(current_index, "USD_Spent", json_object_new_double(round(current_spent * 100) / 100)); } } - if (pString == NULL) // If new portfolio - pString = string_init(); - pString->len = strlen(json_object_to_json_string(jobj)); pString->data = realloc(pString->data, pString->len + 1); pointer_alloc_check(pString->data); - strcpy(pString->data, json_object_to_json_string(jobj)); if (password != NULL) { // If data must be re-encrypted - printf("Encrypting portfolio...\n"); - String* temp = rc4_get_crypted_string(pString, password, ENCRYPT); - string_destroy(&pString); - pString = temp; - free(password); + puts("Re-encrypting portfolio..."); + rc4_encode_string(pString, password); } string_write_portfolio(pString); + cleanup: // CLEANUP + if (password != NULL) + free(password); json_object_put(jobj); string_destroy(&pString); } SDA* portfolio_get_data_array(void) { - String* pString = portfolio_file_get_string(); - if (pString == NULL) { - puts("Empty portfolio."); + String* pString = portfolio_file_get_string(NULL); + if (pString == NULL) return NULL; - } - if (strcmp(pString->data, "") == 0) { + if (pString->len == 0) { puts("Empty portfolio."); string_destroy(&pString); return NULL; } Json* jobj = json_tokener_parse(pString->data); - char* password = NULL; - if (jobj == NULL) { //ENCRYPTED PORTFOLIO - password = rc4_getPassword(); - printf("Decrypting portfolio...\n"); - String* temp = rc4_get_crypted_string(pString, password, DECRYPT); - string_destroy(&pString); - pString = temp; - if (pString == NULL) - return NULL; - jobj = json_tokener_parse(pString->data); - if (password != NULL) - free(password); - } - size_t portfolio_size = json_object_array_length(jobj); if (portfolio_size == 0) return NULL; @@ -295,7 +287,7 @@ void portfolio_print_all(int SORT) { sda_destroy(&sda_data); } -void portfolio_print_stock(char* ticker_name_string) { +void portfolio_print_stock(const char* ticker_name_string) { SDA* sda_data = portfolio_get_data_array(); SD* sec_data = NULL; for (size_t i = 0; i < sda_data->length; i++) { @@ -310,7 +302,7 @@ void portfolio_print_stock(char* ticker_name_string) { return; } portfolio_store_api_data(sec_data); - printf(" AMOUNT SYMBOL VALUE SPENT PROFIT (%%) 24H (%%) 24H (%%)\n"); + printf(" AMOUNT SYMBOL VALUE SPENT PROFIT (%%) 24H (%%) 7D (%%)\n"); printf("%8.2lf %6s %8.2lf %8.2lf %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%)\n", sec_data->amount, sec_data->symbol, sec_data->current_value, sec_data->total_spent, sec_data->total_profit, sec_data->total_profit_percent, sec_data->one_day_profit, sec_data->one_day_profit_percent, @@ -330,6 +322,42 @@ int portfolio_symbol_index(const char* ticker_name_string, Json* jarray) { return -1; } +void portfolio_encrypt_decrypt(int CRYPT) { + char* password = NULL; + String* pString = portfolio_file_get_string(&password); + if (pString == NULL) { + free(password); + return; + } + if (CRYPT == ENCRYPT && password != NULL) { + puts("Portfolio is already encrypted."); + goto cleanup; + } + if (CRYPT == DECRYPT && password == NULL) { + puts("Portfolio isn't encrypted."); + goto cleanup; + } + if (CRYPT == DECRYPT) { + string_write_portfolio(pString); + goto cleanup; + } + password = rc4_getPassword(); + puts("You will be asked to enter your password again to make sure the entries match."); + sleep(2); + char* passwordCheck = rc4_getPassword(); + if (strcmp(password, passwordCheck) != 0) { + puts("Passwords do not match!"); + free(passwordCheck); + goto cleanup; + } + rc4_encode_string(pString, password); + string_write_portfolio(pString); + free(passwordCheck); + cleanup: // CLEANUP + free(password); + string_destroy(&pString); +} + void sda_destroy(SDA** phSDA) { SDA* ptr = *phSDA; for (size_t i = 0; i < ptr->length; i++) diff --git a/portfolio.h b/portfolio.h index 2f59113a86df..4611b8e89945 100644 --- a/portfolio.h +++ b/portfolio.h @@ -2,6 +2,7 @@ #define PORTFOLIO_H #include <math.h> +#include <sys/stat.h> #include "api.h" #include "rc4.h" @@ -50,7 +51,7 @@ void portfolio_file_init(void); * @return pointer to a allocated String containing the contents of the portfolio or NULL on error opening * or reading portfolio */ -String* portfolio_file_get_string(void); +String* portfolio_file_get_string(char** password); /** * Precondition: portfolio_file has been initialized @@ -121,7 +122,7 @@ void portfolio_print_all(int SORT); * current value, profit, and 24h profit. * @param ticker_name_string the security to print */ -void portfolio_print_stock(char* ticker_name_string); +void portfolio_print_stock(const char* ticker_name_string); /** * Goes through the given JSON array until the JSON object at the given index's key "Symbol" contains @@ -132,6 +133,8 @@ void portfolio_print_stock(char* ticker_name_string); */ int portfolio_symbol_index(const char* ticker_name_string, Json* jarray); +void portfolio_encrypt_decrypt(int CRYPT); + /** * Frees all memory associated with a SDA struct and sets the handle to NULL * @param phSDA @@ -27,98 +27,32 @@ char* rc4_getPassword(void) { return (char*) pass; } -void rc4_key_exchange(int keySchedule[KEY_SCHEDULE_LENGTH], char* key) { - size_t len = strlen(key); - int j = 0; +void rc4_encode_string(String* pString, char* password) { + int keySchedule[256]; + size_t key_len = strlen(password); + int j = 0, out; + + // KEY EXCHANGE for (int i = 0; i < KEY_SCHEDULE_LENGTH; i++) keySchedule[i] = i; int temp; for (int i = 0; i < KEY_SCHEDULE_LENGTH; i++) { - j = (j + keySchedule[i] + key[i % len]) % KEY_SCHEDULE_LENGTH; + j = (j + keySchedule[i] + password[i % key_len]) % KEY_SCHEDULE_LENGTH; temp = keySchedule[i]; keySchedule[i] = keySchedule[j]; keySchedule[j] = temp; } -} -char* rc4_prga(int keySchedule[KEY_SCHEDULE_LENGTH], size_t len) { - int i = 0, j = 0, temp; - char* output = malloc(len); - pointer_alloc_check(output); - for (int k = 0; k < (int) len; k++) { + // PRGA + int i = 0; + j = 0; + for (size_t k = 0; k < pString->len; k++) { i = (i + 1) % KEY_SCHEDULE_LENGTH; j = (j + keySchedule[i]) % KEY_SCHEDULE_LENGTH; temp = keySchedule[i]; keySchedule[i] = keySchedule[j]; keySchedule[j] = temp; - output[k] = (unsigned char) keySchedule[(keySchedule[i] + keySchedule[j]) % KEY_SCHEDULE_LENGTH]; - } - return output; -} - -void rc4_execute(char* output, String* pString) { - for (int i = 0; i < (int) pString->len; i++) - output[i] ^= pString->data[i]; -} - -char* rc4_encode_string(String* pString, char* password) { - int keySchedule[256]; - rc4_key_exchange(keySchedule, password); - char* output = rc4_prga(keySchedule, pString->len); - rc4_execute(output, pString); - return output; -} - -String* rc4_get_crypted_string(String* input_pString, char* password, int option) { - String* output_pString = NULL; - int free_pw = (password == NULL); - Json* jobj = json_tokener_parse(input_pString->data); - if (option == ENCRYPT && jobj == NULL) // If trying to encrypt an encrypted portfolio - printf("Your portfolio is already encrypted.\n"); - else if (option == DECRYPT && jobj != NULL) // If trying to decrypt an unencrypted portfolio - printf("Your portfolio isn't encrypted.\n"); - else { - if (password == NULL) { // Get password if not provided - password = rc4_getPassword(); - if (option == ENCRYPT) { // When encrypting, ask to enter pw twice to make sure - printf("You will be asked to enter your password again to make sure the entries match.\n"); - sleep(2); - char* passwordCheck = rc4_getPassword(); - if (strcmp(password, passwordCheck) != 0) { - printf("Passwords do not match!\n"); - free(password); - free(passwordCheck); - json_object_put(jobj); - return NULL; - } - free(passwordCheck); - } - } - output_pString = string_init(); // Set ouput string to en/decrypted data - free(output_pString->data); - output_pString->data = rc4_encode_string(input_pString, password); - output_pString->len = input_pString->len; - if (option == DECRYPT) { - json_object_put(jobj); - // Realloc to add null terminator for json parsing - output_pString->data = realloc(output_pString->data, output_pString->len + 1); - pointer_alloc_check(output_pString->data); // Dealing with len is annoying so it's easier to just realloc - output_pString->data[output_pString->len] = '\0'; // Null terminate string for parsing - jobj = json_tokener_parse(output_pString->data); - if (jobj == NULL) { // If after decrypting, the portfolio is not JSON formatted, - printf("Wrong password!\n"); // then it's the wrong password - free(password); - string_destroy(&output_pString); - return NULL; - } - } - if (free_pw) { // If being called from main - free(password); - if (option == ENCRYPT) - printf("Successfully encrypted your portfolio.\n"); - else printf("Successfully decrypted your portfolio.\n"); - } + out = (unsigned char) keySchedule[(keySchedule[i] + keySchedule[j]) % KEY_SCHEDULE_LENGTH]; + pString->data[k] ^= out; // XOR to encode/decode } - json_object_put(jobj); - return output_pString; }
\ No newline at end of file @@ -20,70 +20,10 @@ char* rc4_getPassword(void); /** - * Precondition: keySchedule is an int array of size 256 and key is a valid string - * Postcondition: keySchedule values have been initialized by the RC4 key-scheduling algorithm. - * Performs the RC4 key exchange with keylength 256. Pseudocode example: - * for i from 0 to 255 - * S[i] := i - * endfor - * j := 0 - * for i from 0 to 255 - * j := (j + S[i] + key[i mod keylength]) mod 256 - swap values of S[i] and S[j] - * endfor - * - * @param keySchedule int array of size keylength - * @param key user given password - */ -void rc4_key_exchange(int keySchedule[KEY_SCHEDULE_LENGTH], char* key); - -/** - * Precondition: keySchedule is an int array of size 256 already initialized by the RC4 key-scheduling algorithm - * Performs the RC4 pseudo-random generation algorithm with keylength 256. Returns a string of length len with output - * frm this algorithm. Pseudocode example: - * i := 0 - * j := 0 - * while GeneratingOutput: - * i := (i + 1) mod 256 - * j := (j + S[i]) mod 256 - * swap values of S[i] and S[j] - * K := S[(S[i] + S[j]) mod 256] - * output K - * endwhile - * - * @param keySchedule int array of size keylength (already initialized) - * @param len size of portfolio in bytes - * @return string of size len that can be XOR'ed with message to be en/decoded - */ -char* rc4_prga(int keySchedule[KEY_SCHEDULE_LENGTH], size_t len); - -/** - * Precondition: output is a string containing the output of the RC4 pseudo-random generation algorithm. pString - * is a String object containing the portfolio. - * XOR's the each index of output by each index of the char* in pString and stores that in the index of output - * @param output string - * @param message portoflio String - */ -void rc4_execute(char* output, String* pString); - -/** * Returns an encoded string given a String object and password used to encode it. * @param pString The String to encode. * @param password the key used to encode - * @return encoded string - */ -char* rc4_encode_string(String* pString, char* password); - -/** - * Given input input_pString, returns an encrypted or decrypted version of it. If trying to encrypt a non-JSON - * formatted input_pString, abort. Similarly, if trying to decrypt a JSON-formatted input_pString, abort. password may - * be a string or NULL. If NULL, get a password from the user if encrypting, ask for the password again to confirm - * inputs are the same. If decrypting and the decrypted String is not JSON formatted, abort (wrong password). - * @param input_pString the String to encrypt/decrypt - * @param password the key or NULL - * @param option ENCRYPT or DECRYPT - * @return encrypted or decrypted String */ -String* rc4_get_crypted_string(String* input_pString, char* password, int option); +void rc4_encode_string(String* pString, char* password); #endif
\ No newline at end of file diff --git a/string-tick.c b/string-tick.c index c5cf0ab31e8a..a65a4d58b31c 100644 --- a/string-tick.c +++ b/string-tick.c @@ -33,9 +33,9 @@ char* strip_char(char* string, char c) { } void string_write_portfolio(String* pString) { - FILE* fp = fopen(portfolio_file, "w"); // fprintf %s won't work since there some chars are encoded to '\0', so it - for (int i = 0; i < (int) pString->len; i++) // will be null terminated several times in the middle - fputc(pString->data[i], fp); + FILE* fp = fopen(portfolio_file, "w"); + if (fwrite(pString->data, sizeof(char), pString->len, fp) != pString->len) + puts("Error writing file."); fclose(fp); } |