aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.c17
-rw-r--r--portfolio.c194
-rw-r--r--portfolio.h7
-rw-r--r--rc4.c92
-rw-r--r--rc4.h62
-rw-r--r--string-tick.c6
6 files changed, 137 insertions, 241 deletions
diff --git a/main.c b/main.c
index a92e769e20b4..c3290c02cfed 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/rc4.c b/rc4.c
index bd3ecc9d3044..4fc722079ecb 100644
--- a/rc4.c
+++ b/rc4.c
@@ -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
diff --git a/rc4.h b/rc4.h
index 7f6a9eec428f..14affb53e5a1 100644
--- a/rc4.h
+++ b/rc4.h
@@ -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);
}