diff options
-rw-r--r-- | api.c | 46 | ||||
-rw-r--r-- | api.h | 5 | ||||
-rw-r--r-- | main.c | 61 | ||||
-rw-r--r-- | portfolio.c | 300 | ||||
-rw-r--r-- | portfolio.h | 41 | ||||
-rw-r--r-- | rc4.c | 72 | ||||
-rw-r--r-- | rc4.h | 20 | ||||
-rw-r--r-- | string-tick.c | 8 | ||||
-rw-r--r-- | string-tick.h | 4 |
9 files changed, 252 insertions, 305 deletions
@@ -38,7 +38,7 @@ size_t api_string_writefunc(void* ptr, size_t size, size_t nmemb, String* hStrin } String* api_curl_data(char* url, char* post_field) { - String* pString = api_string_init(); + String* pString = string_init(); if (pString == NULL) return NULL; CURL* curl = curl_easy_init(); @@ -89,7 +89,7 @@ double* iex_get_price(const char* ticker_name_string) { sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/quote", ticker_name_string); String* pString = api_curl_data(iex_api_string, NULL); if (strcmp(pString->data, "Unknown symbol") == 0) { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Json* jobj = json_tokener_parse(pString->data); @@ -102,7 +102,7 @@ double* iex_get_price(const char* ticker_name_string) { const char* close_price_string = json_object_to_json_string(json_object_object_get(jobj, "previousClose")); ret[0] = strtod(price_string, NULL); //Intraday current price ret[1] = strtod(close_price_string, NULL); //Previous day's close price - api_string_destroy(&pString); + string_destroy(&pString); json_object_put(jobj); return ret; } @@ -122,7 +122,7 @@ double* morningstar_get_price(const char* ticker_name_string) { ticker_name_string, yesterday_char, today_char); String* pString = api_curl_data(morningstar_api_string, NULL); if (strcmp("null", pString->data) == 0) { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Json* jobj = json_tokener_parse(pString->data); @@ -141,7 +141,7 @@ double* morningstar_get_price(const char* ticker_name_string) { price = json_object_to_json_string(yesterday); ret[1] = strtod(price, NULL); //Close price before last close price json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); return ret; } @@ -150,7 +150,7 @@ double* coinmarketcap_get_price(const char* ticker_name_string) { sprintf(coinmarketcap_api_string, "https://api.coinmarketcap.com/v1/ticker/%s", ticker_name_string); String* pString = api_curl_data(coinmarketcap_api_string, NULL); if (pString->data[0] == '{') { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Json* jobj = json_tokener_parse(pString->data); @@ -166,7 +166,7 @@ double* coinmarketcap_get_price(const char* ticker_name_string) { } ret[0] = strtod(price, NULL); //Current real-time price ret[1] = ret[0] - ((strtod(change_1d, NULL) / 100) * ret[0]); //Price 24 hours earlier - api_string_destroy(&pString); + string_destroy(&pString); json_object_put(jobj); return ret; } @@ -190,7 +190,7 @@ void news_print_top_three(const char* ticker_name_string) { mktime(ts); strftime(yearchar, 16, "%Y-%m-%d", ts); sprintf(news_api_string, - "https://newsapi.org/v2/everything?sortBy=relevancy&pageSize=3&language=en&apiKey=1163c352d041460381f0a8273e60a9d1&from=%s&q=%s", + "https://newsapi.org/v2/everything?sortBy=popularity&pageSize=3&language=en&apiKey=1163c352d041460381f0a8273e60a9d1&from=%s&q=%s", yearchar, url_encoded_string); free(url_encoded_string); String* pString = api_curl_data(news_api_string, NULL); @@ -199,7 +199,7 @@ void news_print_top_three(const char* ticker_name_string) { 10) > 0) json_print_news(jobj); else printf("No articles. Try a different input.\n"); - api_string_destroy(&pString); + string_destroy(&pString); json_object_put(jobj); } @@ -269,7 +269,7 @@ Info* iex_get_info(const char* ticker_name_string) { sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/quote", ticker_name_string); String* pString = api_curl_data(iex_api_string, NULL); // API CALL 1 -- name, symbol, price, mcap, volume if (strcmp(pString->data, "Unknown symbol") == 0) { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Info* ticker_info = api_info_init(); @@ -280,18 +280,22 @@ Info* iex_get_info(const char* ticker_name_string) { ticker_info->marketcap = json_object_get_int64(json_object_object_get(jobj, "marketCap")); ticker_info->volume_1d = json_object_get_int64(json_object_object_get(jobj, "latestVolume")); json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/stats/dividendYield", ticker_name_string); pString = api_curl_data(iex_api_string, NULL); // API CALL 2 -- dividend if (strcmp("0", pString->data) != 0) ticker_info->div_yield = strtod(pString->data, NULL); - api_string_destroy(&pString); + string_destroy(&pString); sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/chart", ticker_name_string); pString = api_curl_data(iex_api_string, NULL); // API CALL 3 -- historical jobj = json_tokener_parse(pString->data); - Json* d_30 = json_object_array_get_idx(jobj, 0); - Json* d_7 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 6); - Json* d_1 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 2); + time_t now = time(NULL); + struct tm* ts = localtime(&now); + mktime(ts); + int after_close = ts->tm_hour > 16 && ts->tm_wday != 0 && ts->tm_wday != 6; + Json* d_30 = json_object_array_get_idx(jobj, (size_t)after_close); + Json* d_7 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 6 + after_close); + Json* d_1 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 2 + after_close); ticker_info->change_30d = 100 / ticker_info->price * (ticker_info->price - json_object_get_double(json_object_object_get(d_30, "close"))); ticker_info->change_7d = 100 / ticker_info->price * @@ -299,7 +303,7 @@ Info* iex_get_info(const char* ticker_name_string) { ticker_info->change_1d = 100 / ticker_info->price * (ticker_info->price - json_object_get_double(json_object_object_get(d_1, "close"))); json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); return ticker_info; } @@ -318,7 +322,7 @@ Info* morningstar_get_info(const char* ticker_name_string) { ticker_name_string, yesterday_char, today_char); String* pString = api_curl_data(morningstar_api_string, NULL); if (strcmp("null", pString->data) == 0) { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Info* ticker_info = api_info_init(); @@ -341,7 +345,7 @@ Info* morningstar_get_info(const char* ticker_name_string) { ticker_info->volume_1d = (long) (1000000 * json_object_get_double( // Data listed in millions json_object_array_get_idx(json_object_object_get(vol, "Datapoints"), days - 1))); json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); return ticker_info; } @@ -350,7 +354,7 @@ Info* coinmarketcap_get_info(const char* ticker_name_string) { sprintf(coinmarketcap_api_string, "https://api.coinmarketcap.com/v1/ticker/%s", ticker_name_string); String* pString = api_curl_data(coinmarketcap_api_string, NULL); if (pString->data[0] == '{') { //Invalid symbol - api_string_destroy(&pString); + string_destroy(&pString); return NULL; } Info* ticker_info = api_info_init(); @@ -364,7 +368,7 @@ Info* coinmarketcap_get_info(const char* ticker_name_string) { ticker_info->marketcap = strtol(json_object_get_string(json_object_object_get(data, "market_cap_usd")), NULL, 10); ticker_info->volume_1d = strtol(json_object_get_string(json_object_object_get(data, "24h_volume_usd")), NULL, 10); json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); return ticker_info; } @@ -383,7 +387,7 @@ char* google_shorten_link(const char* url_string) { strip_char(short_url, '\\'); strip_char(short_url, '\"'); json_object_put(jobj); - api_string_destroy(&pString); + string_destroy(&pString); return short_url; } @@ -11,9 +11,6 @@ #define EMPTY (-999) -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include <stddef.h> #include <curl/curl.h> #include <json-c/json_tokener.h> @@ -31,8 +28,6 @@ struct info { typedef struct info Info; -typedef struct json_object Json; - /** * Creates and returns an Info object * @return Info object @@ -10,14 +10,8 @@ int main(int argc, char* argv[]) { strcpy(cmd, argv[1]); strtolower(cmd); - // Init/open portfolio + // Init portfolio path portfolio_file_init(); - FILE* fp = fopen(portfolio_file, "r+"); - if (fp == NULL) { - printf("Could not open portfolio file\n"); - free(portfolio_file); - return 0; - } // Portfolio modify operation int modop = -1; @@ -28,16 +22,40 @@ int main(int argc, char* argv[]) { news_print_top_three(argv[2]); else printf("Invalid symbol.\n"); } - //Convert - else if (strcmp(cmd, "convert") == 0 && argc == 2) - portfolio_legacy_convert(); //Encrypt/decrypt - else if (strcmp(cmd, "encrypt") == 0 && argc == 2) - portfolio_encrypt_decrypt(ENCRYPT, fp, NULL); - else if (strcmp(cmd, "decrypt") == 0 && argc == 2) - portfolio_encrypt_decrypt(DECRYPT, fp, NULL); - + else if (strcmp(cmd, "encrypt") == 0 && argc == 2) { + String* pString = portfolio_file_get_string(); + if (pString == NULL){ + free(portfolio_file); + return 0; + } + String* encrypted = rc4_get_crypted_string(pString, NULL, ENCRYPT); + if (encrypted == NULL){ + string_destroy(&pString); + free(portfolio_file); + return 0; + } + string_write_portfolio(encrypted); + string_destroy(&pString); + string_destroy(&encrypted); + } + else if (strcmp(cmd, "decrypt") == 0 && argc == 2) { + String* pString = portfolio_file_get_string(); + if (pString == NULL){ + free(portfolio_file); + return 0; + } + String* decrypted = rc4_get_crypted_string(pString, NULL, DECRYPT); + if (decrypted == NULL){ + string_destroy(&pString); + free(portfolio_file); + return 0; + } + string_write_portfolio(decrypted); + string_destroy(&pString); + string_destroy(&decrypted); + } // Info else if (strcmp(cmd, "info") == 0 && argc == 3) { char sym[strlen(argv[2]) + 1]; @@ -49,15 +67,15 @@ int main(int argc, char* argv[]) { // Check else if (strcmp(cmd, "check") == 0) { if (argc < 3) { - portfolio_print_all(fp); + portfolio_print_all(); } else { char sym[strlen(argv[2]) + 1]; strcpy(sym, argv[2]); strtoupper(sym); if (strcmp(sym, "ALL") == 0) - portfolio_print_all(fp); + portfolio_print_all(); else { - double* data = portfolio_print_stock(sym, fp, NULL); + double* data = portfolio_print_stock(sym, NULL); if (data != NULL) free(data); } @@ -108,13 +126,13 @@ int main(int argc, char* argv[]) { switch (modop) { case ADD: - portfolio_modify(sym, qty, usd, fp, ADD); + portfolio_modify(sym, qty, usd, ADD); break; case REMOVE: - portfolio_modify(sym, qty, usd, fp, REMOVE); + portfolio_modify(sym, qty, usd, REMOVE); break; case SET: - portfolio_modify(sym, qty, usd, fp, SET); + portfolio_modify(sym, qty, usd, SET); break; default: break; @@ -122,6 +140,5 @@ int main(int argc, char* argv[]) { } } free(portfolio_file); - fclose(fp); return 0; }
\ No newline at end of file diff --git a/portfolio.c b/portfolio.c index 4a36fc30a619..02ae948ed5d3 100644 --- a/portfolio.c +++ b/portfolio.c @@ -13,23 +13,30 @@ void portfolio_file_init(void) { portfolio_file = path; } -char* portfolio_file_get_string(FILE* fp, size_t* len) { - char* portfolio_string = calloc(65536, 1); - if (portfolio_string == NULL) { - fprintf(stderr, "calloc() failed\n"); +String* portfolio_file_get_string(void) { + FILE* fp = fopen(portfolio_file, "r"); + if (fp == NULL) + return NULL; + String* pString = string_init(); + pString->data = realloc(pString->data, 65536); + memset(pString->data, '\0', 65536); + if (pString->data == NULL) { + fprintf(stderr, "realloc() failed\n"); exit(EXIT_FAILURE); } fseek(fp, 0, SEEK_END); - size_t portfolio_size = (size_t) ftell(fp); - if (len != NULL) - *len = portfolio_size; + pString->len = (size_t) ftell(fp); fseek(fp, 0, SEEK_SET); - if (fread(portfolio_string, sizeof(char), portfolio_size, fp) != portfolio_size) + if (fread(pString->data, sizeof(char), pString->len, fp) != pString->len) { + fclose(fp); + printf("Returning null\n"); return NULL; - return portfolio_string; + } + fclose(fp); + return pString; } -void portfolio_modify(const char* ticker_name_string, double quantity_shares, double usd_spent, FILE* fp, int option) { +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"); return; @@ -38,24 +45,25 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do printf("You cannot add or remove values of 0.\n"); return; } - size_t len; - char* portfolio_string = portfolio_file_get_string(fp, &len); + String* pString = portfolio_file_get_string(); + if (pString == NULL) { + printf("Error reading portfolio.\n"); + return; + } Json* jobj = NULL; - if (len == 0) //new file + if (pString->len == 0) //new file jobj = json_object_new_array(); - else jobj = json_tokener_parse(portfolio_string); //existing file + else jobj = json_tokener_parse(pString->data); //existing file char* password = NULL; if (jobj == NULL) { //ENCRYPTED PORTFOLIO password = rc4_getPassword(); printf("Decrypting portfolio...\n"); - portfolio_encrypt_decrypt(DECRYPT, fp, password); - fp = fopen(portfolio_file, "r+"); - free(portfolio_string); - portfolio_string = portfolio_file_get_string(fp, NULL); - json_object_put(jobj); - jobj = json_tokener_parse(portfolio_string); - if (jobj == NULL) { - free(portfolio_string); + String* temp = rc4_get_crypted_string(pString, password, DECRYPT); + string_destroy(&pString); + pString = temp; + jobj = json_tokener_parse(pString->data); + if (pString == NULL) { + free(password); return; } } @@ -63,8 +71,10 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do if (index == -1) { //if not already in portfolio if (option == REMOVE) { printf("You don't have any %s to remove.\n", ticker_name_string); - free(portfolio_string); json_object_put(jobj); + string_destroy(&pString); + if (password != NULL) + free(password); return; } if (strcmp("USD$", ticker_name_string) != 0) { @@ -72,7 +82,9 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do if (data == NULL) { printf("Invalid symbol.\n"); json_object_put(jobj); - free(portfolio_string); + string_destroy(&pString); + if (password != NULL) + free(password); return; } else free(data); } @@ -104,7 +116,9 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do 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); - free(portfolio_string); + string_destroy(&pString); + if (password != NULL) + free(password); return; } printf("Removed %lf %s bought for %lf to portfolio.\n", quantity_shares, ticker_name_string, usd_spent); @@ -118,43 +132,42 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do json_object_new_double(round(current_spent * 100) / 100)); } } - fp = fopen(portfolio_file, "w"); - fprintf(fp, "%s", json_object_to_json_string(jobj)); - if (password != NULL) { // If portfolio was decrypted, encrypt again - fflush(fp); - printf("Encrypting porfolio...\n"); - portfolio_encrypt_decrypt(ENCRYPT, fp, password); + if (password != NULL) { // If data must be re-encrypted + printf("Encrypting portfolio...\n"); + strcpy(pString->data, json_object_to_json_string(jobj)); + String* temp = rc4_get_crypted_string(pString, password, ENCRYPT); + string_destroy(&pString); + pString = temp; free(password); } json_object_put(jobj); - free(portfolio_string); + string_write_portfolio(pString); + string_destroy(&pString); } -void portfolio_print_all(FILE* fp) { - char* portfolio_string = portfolio_file_get_string(fp, NULL); +void portfolio_print_all(void) { + String* pString = portfolio_file_get_string(); + if (pString == NULL) + return; + if (strcmp(pString->data, "") == 0) { + string_destroy(&pString); + return; + } double* data, total_owned = 0, total_spent = 0, total_gain_1d = 0; - Json* jobj = json_tokener_parse(portfolio_string); + Json* jobj = json_tokener_parse(pString->data); char* password = NULL; if (jobj == NULL) { //ENCRYPTED PORTFOLIO password = rc4_getPassword(); printf("Decrypting portfolio...\n"); - portfolio_encrypt_decrypt(DECRYPT, fp, password); - fp = fopen(portfolio_file, "r+"); - free(portfolio_string); - portfolio_string = portfolio_file_get_string(fp, NULL); - json_object_put(jobj); - jobj = json_tokener_parse(portfolio_string); - if (jobj == NULL) { - free(portfolio_string); - return; - } + String* temp = rc4_get_crypted_string(pString, password, DECRYPT); + string_destroy(&pString); + pString = temp; + jobj = json_tokener_parse(pString->data); } - if (strcmp(portfolio_string, "") == 0) - return; int num_symbols = (int) json_object_array_length(jobj); printf(" AMOUNT SYMBOL VALUE SPENT PROFIT (%%) 24H (%%)\n"); for (int i = 0; i < num_symbols; i++) { - data = portfolio_print_stock(NULL, NULL, json_object_array_get_idx(jobj, (size_t) i)); + data = portfolio_print_stock(NULL, json_object_array_get_idx(jobj, (size_t) i)); if (data != NULL) { total_owned += data[0]; total_spent += data[1]; @@ -165,17 +178,13 @@ void portfolio_print_all(FILE* fp) { printf("\n TOTALS %8.2lf %8.2lf %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%)\n", total_owned, total_spent, total_owned - total_spent, (100 * (total_owned - total_spent)) / total_spent, total_gain_1d, 100 * total_gain_1d / total_spent); - if (password != NULL) { // If portfolio was decrypted, encrypt again - fflush(fp); - printf("Encrypting porfolio...\n"); - portfolio_encrypt_decrypt(ENCRYPT, fp, password); + if (password != NULL) free(password); - } json_object_put(jobj); - free(portfolio_string); + string_destroy(&pString); } -double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_index) { +double* portfolio_print_stock(char* ticker_name_string, Json* current_index) { /** * Values in USD * a[0] -- current balance @@ -184,29 +193,31 @@ double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_ */ char symbol[32]; double* data = malloc(sizeof(double) * 3); - char* portfolio_string = NULL; + if (data == NULL) { + fprintf(stderr, "malloc() failed\n"); + exit(EXIT_FAILURE); + } + String* pString = NULL; char* password = NULL; Json* jobj = NULL; - if (fp == NULL) { //if being called from portfolio_print_all + if (current_index != NULL) { //if being called from portfolio_print_all strcpy(symbol, json_object_get_string(json_object_object_get(current_index, "Symbol"))); strip_char(symbol, '\"'); data[0] = json_object_get_double(json_object_object_get(current_index, "Shares")); data[1] = json_object_get_double(json_object_object_get(current_index, "USD_Spent")); } else { //if being called directly from main strcpy(symbol, ticker_name_string); - portfolio_string = portfolio_file_get_string(fp, NULL); - jobj = json_tokener_parse(portfolio_string); + pString = portfolio_file_get_string(); + jobj = json_tokener_parse(pString->data); if (jobj == NULL) { //ENCRYPTED PORTFOLIO password = rc4_getPassword(); printf("Decrypting portfolio...\n"); - portfolio_encrypt_decrypt(DECRYPT, fp, password); - fp = fopen(portfolio_file, "r+"); - free(portfolio_string); - portfolio_string = portfolio_file_get_string(fp, NULL); - json_object_put(jobj); - jobj = json_tokener_parse(portfolio_string); - if (jobj == NULL) { - free(portfolio_string); + String* temp = rc4_get_crypted_string(pString, password, DECRYPT); + string_destroy(&pString); + pString = temp; + jobj = json_tokener_parse(pString->data); + if (pString == NULL) { + free(password); return NULL; } } @@ -216,6 +227,7 @@ double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_ return data; } current_index = json_object_array_get_idx(jobj, (size_t) index); + printf(" AMOUNT SYMBOL VALUE SPENT PROFIT (%%) 24H (%%)\n"); } data[0] = json_object_get_double(json_object_object_get(current_index, "Shares")); data[1] = json_object_get_double(json_object_object_get(current_index, "USD_Spent")); @@ -234,160 +246,22 @@ double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_ data[0] / ticker_current_price_usd, symbol, data[0], data[1], data[0] - data[1], (100 * (data[0] - data[1])) / data[1], data[2], ticker_1d_percent_change); - if (fp != NULL) { - json_object_put(jobj); - if (password != NULL) { // If portfolio was decrypted, encrypt again - fflush(fp); - printf("Encrypting porfolio...\n"); - portfolio_encrypt_decrypt(ENCRYPT, fp, password); - free(password); - } - } - free(portfolio_string); + if (password != NULL) + free(password); + json_object_put(jobj); + if (pString != NULL) + string_destroy(&pString); return data; } int portfolio_symbol_index(const char* ticker_name_string, Json* jarray) { char string[32]; - for (int i = 0; i < (int)json_object_array_length(jarray); i++) { - strcpy(string, json_object_to_json_string(json_object_object_get(json_object_array_get_idx(jarray, (size_t) i), "Symbol"))); + for (int i = 0; i < (int) json_object_array_length(jarray); i++) { + strcpy(string, json_object_to_json_string( + json_object_object_get(json_object_array_get_idx(jarray, (size_t) i), "Symbol"))); strip_char(string, '\"'); if (strcmp(string, ticker_name_string) == 0) return i; } return -1; -} - -char* portfolio_legacy_get_next_val(FILE* fp) { - char* val = calloc(16, 1); - char c; - for (int i = 0; i < 16; i++) { - c = (char) fgetc(fp); - if (c == ' ' || c == '\n' || feof(fp)) - break; - val[i] = c; - } - return val; -} - -void portfolio_legacy_convert(void) { - printf("Warning: this will overwrite your JSON formatted portfolio, which is stored at: \"$HOME/.tick_portfolio.json\". Continue? y/n\n"); - char c = 0; - while (c != 'y' && c != 'n') { - if (scanf("%c", &c) < 0) - c = 0; - } - if (c == 'n') { - printf("Aborted.\n"); - return; - } - FILE* fp = fopen(portfolio_file, "w"); - char* pf = portfolio_file_get_string(fp, NULL); - if (pf == NULL) { - fprintf(stderr, "fread() failed\n"); - exit(EXIT_FAILURE); - } - if (strcmp(pf, "") != 0) - remove(portfolio_file); - fclose(fp); - fp = fopen(portfolio_file, "a+"); - free(pf); - char* legacy_path = malloc(64); - strcpy(legacy_path, portfolio_file); - legacy_path[strlen(legacy_path) - 5] = '\0'; - FILE* fp_legacy = fopen(legacy_path, "r"); - free(legacy_path); - if (!fp) { - printf("Could not open legacy portfolio.\n"); - return; - } - char* symbol, * amount, * spent; - while (1) { - symbol = portfolio_legacy_get_next_val(fp_legacy); - amount = portfolio_legacy_get_next_val(fp_legacy); - spent = portfolio_legacy_get_next_val(fp_legacy); - portfolio_modify(symbol, strtod(amount, NULL), strtod(spent, NULL), fp, ADD); - free(symbol); - free(amount); - free(spent); - if (feof(fp_legacy)) - break; - } - printf("Successfully converted portfolio!\n"); - fclose(fp_legacy); - fclose(fp); -} - -char* portfolio_get_encrypt_string(char* input, size_t input_len, char* password) { - int keySchedule[256]; - rc4_key_exchange(keySchedule, password); - char* output = rc4_prga(keySchedule, input_len); - rc4_execute(output, input, input_len); - return output; -} - -void portfolio_encrypt_decrypt(int option, FILE* fp, char* password) { - int free_pw = 0; - if (password == NULL) - free_pw = 1; - fp = fopen(portfolio_file, "r+"); - size_t len; - char* ps = portfolio_file_get_string(fp, &len); - Json* jobj = json_tokener_parse(ps); - 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) { - 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); - free(ps); - json_object_put(jobj); - return; - } - free(passwordCheck); - } - } - char* encrypted = portfolio_get_encrypt_string(ps, len, password); - if (option == DECRYPT) { - json_object_put(jobj); - encrypted = realloc(encrypted, len + 1);// Realloc to add null terminator for json parsing - if (encrypted == NULL) { // Dealing with len is annoying so it's easier to just realloc - fprintf(stderr, "malloc() failed\n"); - exit(EXIT_FAILURE); - } - encrypted[len] = '\0'; - jobj = json_tokener_parse(encrypted); - if (jobj == NULL) { // If after decrypting, the portfolio is not JSON formatted, - printf("Wrong password!\n"); // then it's the wrong password - free(encrypted); - free(password); - free(ps); - return; - } - } - remove(portfolio_file); // Remove existing file and use fputc to write - 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)len; i++) // will be null terminated several times in the middle - fputc(encrypted[i], fp); - fclose(fp); - free(encrypted); - 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"); - } - } - if (jobj != NULL) - json_object_put(jobj); - free(ps); }
\ No newline at end of file diff --git a/portfolio.h b/portfolio.h index 42012d57113e..fe50b16ff1c7 100644 --- a/portfolio.h +++ b/portfolio.h @@ -2,15 +2,12 @@ #define PORTFOLIO_H #include <math.h> -#include <unistd.h> #include "api.h" #include "rc4.h" #define REMOVE 0 #define ADD 1 #define SET 2 -#define DECRYPT 0 -#define ENCRYPT 1 extern char* portfolio_file; @@ -26,7 +23,7 @@ void portfolio_file_init(void); * the returned string will be null terminated somewhere in the middle several times * @return the string containing the file */ -char* portfolio_file_get_string(FILE* fp, size_t* len); +String* portfolio_file_get_string(void); /** * Adds quantity_shares of given symbol at given price to portfolio @@ -35,7 +32,7 @@ char* portfolio_file_get_string(FILE* fp, size_t* len); * @param purchase_price quantity_shares of money spent * @param fp portfolio file */ -void portfolio_modify(const char* ticker_name_string, double quantity_shares, double usd_spent, FILE* fp, int option); +void portfolio_modify(const char* ticker_name_string, double quantity_shares, double usd_spent, int option); /** * Prints current holdings of all symbols @@ -43,7 +40,7 @@ void portfolio_modify(const char* ticker_name_string, double quantity_shares, do * @param crypto_data JSON to hold STRING data in * @param fp portfolio file */ -void portfolio_print_all(FILE* fp); +void portfolio_print_all(void); /** * Prints current holdings of a symbol @@ -51,7 +48,7 @@ void portfolio_print_all(FILE* fp); * @param fp portfolio file, NULL if printing all * @param current_index portfolio file index, NULL if printing one */ -double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_index); +double* portfolio_print_stock(char* ticker_name_string, Json* current_index); /** * Returns the index in the Json array of the given symbol @@ -61,34 +58,4 @@ double* portfolio_print_stock(char* ticker_name_string, FILE* fp, Json* current_ */ int portfolio_symbol_index(const char* ticker_name_string, Json* jarray); -/** - * Returns a string from the current stream pointer to the next space, newline, or EOF - * @param fp the file - * @return the string - */ -char* portfolio_legacy_get_next_val(FILE* fp); - -/** - * Adds contents of legacy portfolio to JSON formatted portfolio - * @param fp JSON formatted portfolio - */ -void portfolio_legacy_convert(void); - -/** - * Returns an either encrypted or decrypted string of the input - * @param input the string to encrypt or decrypt - * @param input_len the length of the string - * @param password the password to encrypt or decrypt with - * @return encrypted or decrypted string - */ -char* portfolio_get_encrypt_string(char* input, size_t input_len, char* password); - -/** - * Either encrypts or decrypts the portfolio file - * @param option ENCRYPT or DECRYPT - * @param fp portfolio file - * @param password the password to encrypt/decrypt with or NULL to ask user - */ -void portfolio_encrypt_decrypt(int option, FILE* fp, char* password); - #endif
\ No newline at end of file @@ -51,7 +51,7 @@ char* rc4_prga(int keySchedule[KEY_SCHEDULE_LENGTH], size_t len) { fprintf(stderr, "malloc() failed\n"); return NULL; } - for (int k = 0; k < (int)len; k++) { + for (int k = 0; k < (int) len; k++) { i = (i + 1) % KEY_SCHEDULE_LENGTH; j = (j + keySchedule[i]) % KEY_SCHEDULE_LENGTH; temp = keySchedule[i]; @@ -62,7 +62,71 @@ char* rc4_prga(int keySchedule[KEY_SCHEDULE_LENGTH], size_t len) { return output; } -void rc4_execute(char* output, char* message, size_t len) { - for (int i = 0; i < (int)len; i++) - output[i] ^= message[i]; +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); + output_pString->data = realloc(output_pString->data, output_pString->len + 1);// Realloc to add null terminator for json parsing + if (output_pString->data == NULL) { // Dealing with len is annoying so it's easier to just realloc + fprintf(stderr, "realloc() failed\n"); + exit(EXIT_FAILURE); + } + 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"); + } + } + json_object_put(jobj); + return output_pString; }
\ No newline at end of file @@ -4,10 +4,13 @@ #define PASS_MAX 32 #define BACKSPACE 127 #define KEY_SCHEDULE_LENGTH 256 +#define DECRYPT 0 +#define ENCRYPT 1 -#include <stdlib.h> -#include <string.h> #include <ncurses.h> +#include <json-c/json_tokener.h> +#include <unistd.h> +#include "string-tick.h" /** * Takes a password from user input and returns it (max 32 chars) @@ -36,6 +39,17 @@ char* rc4_prga(int keySchedule[KEY_SCHEDULE_LENGTH], size_t len); * @param message portoflio string * @param len length of portfolio in bytes */ -void rc4_execute(char* output, char* message, size_t len); +void rc4_execute(char* output, String* pString); + +/** + * Returns an either encrypted or decrypted string of the input + * @param input the string to encrypt or decrypt + * @param input_len the length of the string + * @param password the password to encrypt or decrypt with + * @return encrypted or decrypted string + */ +char* rc4_encode_string(String* pString, char* password); + +String* rc4_get_crypted_string(String* input_pString, char* password, int option); #endif
\ No newline at end of file diff --git a/string-tick.c b/string-tick.c index f3575d01a356..701c87463135 100644 --- a/string-tick.c +++ b/string-tick.c @@ -1,4 +1,5 @@ #include "string-tick.h" +#include "portfolio.h" String* string_init(void) { String* pString = (String*) malloc(sizeof(String)); @@ -39,6 +40,13 @@ char* strip_char(char* string, char c) { return string; } +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); + fclose(fp); +} + void string_destroy(String** phString) { String* pString = *phString; free(pString->data); diff --git a/string-tick.h b/string-tick.h index 3e9575560d3a..1397ee3fb2ef 100644 --- a/string-tick.h +++ b/string-tick.h @@ -13,6 +13,8 @@ struct string { typedef struct string String; +typedef struct json_object Json; + /** * Creates and returns a STRING * object with size 1 and no data @@ -40,6 +42,8 @@ void strtoupper(char* str); */ char* strip_char(char* string, char c); +void string_write_portfolio(String* pString); + /** * Destroys String object and frees memory * @param phString the String to destroy |