#define _GNU_SOURCE #include #include #include #include #include #include #include #include static MYSQL* conn2maria(); static int AddPost(char title[], int authorId, char datePosted[], char post[], int tags[], size_t tagSize, MYSQL* con); static int EditPost(int postID, char title[], char post[], MYSQL* con); static int AddFilePost(int authorID, char filePath[], MYSQL* con); static int BlogWrite(MYSQL* con); static int PullPostData(char* strings[6], int postID, MYSQL* con); static int AddTag(char tagTitle[], MYSQL* con); static int DeleteTag(int tagID, MYSQL* con); static int EditTag(int tagID, char tagTitle[], MYSQL* con); static int AssignTag(int tagID, int postID, MYSQL* con); static int RetractTag(int tagID, int postID, MYSQL* con); static int AddAuthor(char firstName[], char lastName[], char email[], MYSQL* con); static int PullAuthorData(char* strings[4], int authorID, MYSQL* con); static int ChangeAuthor(int postID, int authorID, MYSQL* con); static int TogglePost(int postID, MYSQL* con); static bool IsEnabled(int postID, MYSQL* con); static int* PostIDs(MYSQL* con); static int* ActivePostIDs(MYSQL* con); // Connects to the MariaDB database and returns the connection MYSQL* conn2maria() { // Initialize the connection MYSQL *con = mysql_init(NULL); // If successful, continue, else throw error if (con == NULL) { fprintf(stderr, "%s\n", mysql_error(con)); exit(1); } // Connect with specific details, if successful continue, else throw error if (mysql_real_connect(con, "localhost", "adam", "1234", "mydb", 0, NULL, 0) == NULL) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // return successful connection return con; } // Adds a new post to the database, with given values int AddPost(char title[], int authorId, char datePosted[], char post[], int tags[], size_t tagSize, MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Build a query char* query; if(0 > asprintf(&query, "INSERT INTO blog_posts (title,author_id,date_posted,post,state) VALUES (\"%s\", \"%d\", \"%s\", \"%s\", \"0\")", title, authorId, datePosted, post )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, query)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Free the memory of the query string free(query); if (mysql_query(con, "SELECT LAST_INSERT_ID()")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); // For all rows (only one ;P) MYSQL_ROW row; row = mysql_fetch_row(result); int output = atoi(row[0]); // Ignore all if tags is NULL pointer if (tags != NULL) { //printf("%d\n", tagSize / sizeof(int)); // for the size of tags for (int i = 0; i < tagSize / sizeof(int); i++) { printf("%d\n", i); AssignTag(tags[i], output, con); } } return output; } // Edits a post in the database, to the new given values int EditPost(int postID, char title[], char post[], MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM blog_posts WHERE id=(%d)", postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); if (result == NULL) { printf("Hey\n"); } MYSQL_ROW row; int tagFound = 1; if (mysql_fetch_row(result) == NULL) { printf("Hey4\n"); tagFound = 0; } free(selectQuery); char* updateQuery; if (!tagFound) { return postID; } // Build a query if (0 > asprintf(&updateQuery, "UPDATE blog_posts SET title=(\"%s\"), post=(\"%s\") WHERE id=(%d)", title, post, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, updateQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(updateQuery); return postID; } // Adds a post using file data int AddFilePost(int authorID, char filePath[], MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Author ID <= 0 should default to me. if (authorID <= 0) { authorID = 1; } // Get current data in string date time_t t = time(NULL); struct tm *tm = localtime(&t); char date[64]; assert(strftime(date, sizeof(date), "%F", tm)); // Define a file and buffer FILE* FilePointer; int BufferLength = 255; char Buffer[BufferLength]; char StringEnd[] = "\0"; // Open file FilePointer = fopen(filePath, "r"); // Get first line fgets(Buffer, BufferLength, FilePointer); // Get the substrings Buffer[0:3] and Buffer[-6:-1] // Buffer[BufferLength] is the same as "\0" but without warnings int LineLength = strlen(Buffer); char startTest[5] = {Buffer[0], Buffer[1], Buffer[2], Buffer[3], Buffer[BufferLength]}; char endTest[6] = {Buffer[LineLength - 6], Buffer[LineLength - 5], Buffer[LineLength - 4], Buffer[LineLength - 3], Buffer[LineLength - 2], Buffer[BufferLength]}; // Check that the firstline starts with "

" and ends with "

" if (!(strcmp(startTest, "

") == 0 && strcmp(endTest, "

") == 0)) { printf("%s What is this %s\n", startTest, endTest); return -1; } // This is equivalent to Buffer = Buffer[3:-6] // This is done to remove the

tags for (int i = 4; i < BufferLength; ++i) { if (Buffer[i + 6] == StringEnd[0]) { Buffer[i - 4] = StringEnd[0]; break; } Buffer[i-4] = Buffer[i]; } // Add a new post with correct title, author and date but with an empty post. int postID = AddPost(Buffer, authorID, date, "", NULL, 0, con); // Concat the rest of the file, line by line to the new post while (fgets(Buffer, BufferLength, FilePointer)) { // Build a query char* query; if(0 > asprintf(&query, "UPDATE blog_posts SET post = CONCAT(post, \"%s\n\") WHERE id=(%d)", Buffer, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, query)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Free the memory of the query string free(query); } // return the postID of the new post. return postID; } // Open a temporary file containing the standard template, // and add the contents as a post int BlogWrite(MYSQL* con) { FILE *fp; char* tmpName = tmpnam(NULL); //fp = tmpfile(); fp = fopen(tmpName, "w+"); fprintf(fp, "

\n

\n"); fclose(fp); char* command; if(0 > asprintf(&command, "$EDITOR %s", tmpName)) exit(1); system(command); AddFilePost(1, tmpName, con); remove(tmpName); return 1; } // Pulls a single post's data into the supplied array int PullPostData(char* strings[6], int postID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Build a query char* query; if(0 > asprintf(&query, "SELECT * FROM blog_posts WHERE id=(%d)", postID)) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, query)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Free the memory of the query string free(query); // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); // For all rows (only one ;P) MYSQL_ROW row; while ((row = mysql_fetch_row(result))) { // For all fields in row for(int i = 0; i < num_fields; i++) { // 'return' the output strings[i] = row[i]; } } return postID; } // Adds a tag int AddTag(char tagTitle[], MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* insertQuery; // Build a query if (0 > asprintf(&insertQuery, "INSERT INTO tags (name) VALUES (\"%s\")", tagTitle )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, insertQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(insertQuery); if (mysql_query(con, "SELECT LAST_INSERT_ID()")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); // For all rows (only one ;P) MYSQL_ROW row; row = mysql_fetch_row(result); int output = atoi(row[0]); return output; } // Removes a tag, and unassigns itself from any and all posts. int DeleteTag(int tagID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* deleteQuery; // Build a query if (0 > asprintf(&deleteQuery, "DELETE FROM tags WHERE id=(%d)", tagID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, deleteQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(deleteQuery); char* deleteTagsQuery; // Build a query if (0 > asprintf(&deleteTagsQuery, "DELETE FROM blog_post_tags WHERE tag_id=(%d)", tagID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, deleteTagsQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(deleteTagsQuery); return tagID; } // Edit the tag name int EditTag(int tagID, char tagTitle[], MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM tags WHERE id=(%d)", tagID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); MYSQL_ROW row; int tagFound = 1; if (mysql_fetch_row(result) == NULL) { tagFound = 0; } free(selectQuery); char* updateQuery; if (!tagFound) { return tagID; } // Build a query if (0 > asprintf(&updateQuery, "UPDATE tags SET name=(\"%s\") WHERE id=(%d)", tagTitle, tagID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, updateQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(updateQuery); return tagID; } // Assign a post a given tag. int AssignTag(int tagID, int postID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM blog_post_tags WHERE tag_id=(%d) AND blog_post_id=(%d)", tagID, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); if (result == NULL) { printf("Hey\n"); } MYSQL_ROW row; int tagFound = 1; if (mysql_fetch_row(result) == NULL) { printf("Hey4\n"); tagFound = 0; } free(selectQuery); char* insertQuery; if (tagFound) { return postID; } // Build a query if (0 > asprintf(&insertQuery, "INSERT INTO blog_post_tags (tag_id,blog_post_id) VALUES (%d, %d)", tagID, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, insertQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(insertQuery); return postID; } // Unassign a tag from the given post int RetractTag(int tagID, int postID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* deleteQuery; // Build a query if (0 > asprintf(&deleteQuery, "DELETE FROM blog_post_tags WHERE tag_id=(%d) AND blog_post_id=(%d)", tagID, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, deleteQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(deleteQuery); return postID; } // Add an author int AddAuthor(char firstName[], char lastName[], char email[], MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* insertQuery; // Build a query if (0 > asprintf(&insertQuery, "INSERT INTO people (first_name, last_name, email) VALUES (\"%s\", \"%s\", \"%s\")", firstName, lastName, email )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, insertQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(insertQuery); if (mysql_query(con, "SELECT LAST_INSERT_ID()")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); // For all rows (only one ;P) MYSQL_ROW row; row = mysql_fetch_row(result); int output = atoi(row[0]); return output; } // Pull the full name and email of the given author ID int PullAuthorData(char* strings[4], int authorID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Build a query char* query; if(0 > asprintf(&query, "SELECT * FROM people WHERE id=(%d)", authorID)) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, query)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Free the memory of the query string free(query); // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); // For all rows (only one ;P) MYSQL_ROW row; while ((row = mysql_fetch_row(result))) { // For all fields in row for(int i = 0; i < num_fields; i++) { // 'return' the output strings[i] = row[i]; } } return authorID; } // Change the author of a given post int ChangeAuthor(int postID, int authorID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM blog_posts WHERE id=(%d)", postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); MYSQL_ROW row; int postFound = 1; if (mysql_fetch_row(result) == NULL) { postFound = 0; } free(selectQuery); char* updateQuery; if (!postFound) { return postID; } // Build a query if (0 > asprintf(&updateQuery, "UPDATE blog_posts SET author_id=(%d) WHERE id=(%d)", authorID, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, updateQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(updateQuery); return postID; } // Toggles the posts state, which determines whether the code ignores it. int TogglePost(int postID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM blog_posts WHERE id=(%d)", postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); MYSQL_ROW row; row = mysql_fetch_row(result); if (row == NULL) { return postID; } int state = atoi(row[5]); free(selectQuery); char* updateQuery; // Build a query if (0 > asprintf(&updateQuery, "UPDATE blog_posts SET state=(%d) WHERE id=(%d)", !state, postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, updateQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } free(updateQuery); return postID; } // Return true if state is 0, false if it doesn't exist or 1 bool IsEnabled(int postID, MYSQL* con) { if (con == NULL) { con = conn2maria(); } char* selectQuery; if(0 > asprintf(&selectQuery, "SELECT * FROM blog_posts WHERE id=(%d)", postID )) exit(1); // Query the server, if successful continue, else throw error if (mysql_query(con, selectQuery)) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); int num_fields = mysql_num_fields(result); MYSQL_ROW row; int postFound = 1; row = mysql_fetch_row(result); if (row == NULL) { return false; } int state = atoi(row[5]); free(selectQuery); return !state; } // Returns an array of IDs for all posts, // the last element in the array is set to be negative as to prevent going into unallocated data. // Remember to free() the returned array int* PostIDs(MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Query the server, if successful continue, else throw error if (mysql_query(con, "SELECT COUNT(*) FROM blog_posts")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); MYSQL_ROW row; row = mysql_fetch_row(result); int count = atoi(row[0]); //printf("%d\n", count); free(result); // Query the server, if successful continue, else throw error if (mysql_query(con, "SELECT id FROM blog_posts")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } MYSQL_RES *result2 = mysql_store_result(con); int *arr = (int *)malloc(sizeof(int) * (count + 1)); //printf("arr was allocated: %db of memory\n", sizeof(int) * (count + 1)); for (int i = 0; i < count; ++i) { row = mysql_fetch_row(result2); if (row != NULL) { arr[i] = atoi(row[0]); } } arr[count] = -1; return arr; } // Returns an array of IDs for all the posts that have state=0, // the last element in the array is set to be negative as to prevent going into unallocated data. // Remember to free() the returned array int* ActivePostIDs(MYSQL* con) { if (con == NULL) { con = conn2maria(); } // Query the server, if successful continue, else throw error if (mysql_query(con, "SELECT COUNT(*) FROM blog_posts WHERE state=(0)")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } // Get results MYSQL_RES *result = mysql_store_result(con); MYSQL_ROW row; row = mysql_fetch_row(result); int count = atoi(row[0]); //printf("%d\n", count); free(result); // Query the server, if successful continue, else throw error if (mysql_query(con, "SELECT id FROM blog_posts WHERE state=(0)")) { fprintf(stderr, "%s\n", mysql_error(con)); mysql_close(con); exit(1); } MYSQL_RES *result2 = mysql_store_result(con); int *arr = (int *)malloc(sizeof(int) * (count + 1)); //printf("arr was allocated: %db of memory\n", sizeof(int) * (count + 1)); for (int i = 0; i < count; ++i) { row = mysql_fetch_row(result2); if (row != NULL) { arr[i] = atoi(row[0]); } } arr[count] = -1; return arr; } // Main int main(int argc, char *argv[]) { /* // =================================== // Example of using 'PullPostData()' // =================================== // Init array of six strings // Pull data of postID '1' into 'result' char *result[6]; PullPostData(result, 1, NULL); // Foreach in result for (int i = 0; i < sizeof(result)/sizeof(result[0]); i++) { // Print contents on a new line printf("%s\n", result[i]); } // =================================== */ /* // =================================== // Example of using 'PullAuthorData()' // =================================== // Init array of four strings // Pull data of authorID '1' into 'result' char *result[4]; PullAuthorData(result, 1, NULL); // Foreach in result for (int i = 0; i < sizeof(result)/sizeof(result[0]); i++) { // Print contents on a new line printf("%s\n", result[i]); } // =================================== */ /* // =================================== // Example of using 'ActivePostIDs()' // =================================== // Generate array of IDs int *num = ActivePostIDs(NULL); // Loop until element is negative i.e. the last for (int i = 0; num[i] > 0; ++i) { // Print contents on a new line printf("%d\n", num[i]); } // Free the memory free(num); // =================================== */ // =================================== // Example of using 'PostIDs()' // =================================== /* // Generate array of IDs int *num = PostIDs(NULL); // Loop until element is negative i.e. the last for (int i = 0; num[i] > 0; ++i) { // Print contents on a new line printf("%d\n", num[i]); } // Free the memory free(num); // =================================== */ // Open the connection MYSQL *con = conn2maria(); // AddPost return the inserted rows, NULL pointer for no tags, 0 for size // //int tags[] = {1, 2, 3}; //printf("%d", AddPost("Something", 1, "2020-01-01", "Ssdjshdjahdkjomething", tags, sizeof(tags))); //AssignTag(6, 42, con); //EditPost(69, "HEY", "THERE BUDDY", con); //printf("%d\n", AddTag("Test", con)); //DeleteTag(7, con); //RetractTag(1, 1, con); //EditTag(5, "Projects", con); //AddAuthor("Me", "Meson", "email@me.com", con); //ChangeAuthor(62, 2, con); //TogglePost(81, con); //printf("%s\n", IsEnabled(81, con) ? "True" : "False"); //AddFilePost(1, "/home/adam/Documents/html/linuxenv.html", con); //BlogWrite(con); // ================================= exit(0); }