Guest User

Untitled

a guest
Oct 25th, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.90 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <mysql.h>
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <netinet/in.h>
  8. #include <string.h>
  9. #include <signal.h>
  10.  
  11. /*definitions*/
  12. //the number of clients that can connect at once
  13. #define NUM_CLIENTS 10
  14. #define PORT 55555
  15. #define INPUT_SIZE 256
  16. #define MYSQL_SERVER "localhost"
  17. #define MYSQL_USER "root"
  18. #define MYSQL_PASSWORD "12345"
  19. #define DATABASE "BBS"
  20.  
  21. struct threadData {
  22. int threadId;
  23. int connfd;
  24. int userId;
  25. //can add more here if we need it (sql connection?)
  26. };
  27.  
  28. struct threadData threadDataArray[NUM_CLIENTS];
  29. int authenticate(struct threadData *);
  30. void browseTopics(struct threadData *);
  31. void listAll(struct threadData *);
  32. void listByUser(struct threadData *);
  33. void addPost(struct threadData *, int, int);
  34. void deletePost(struct threadData *);
  35. void addThread(struct threadData *, int);
  36. void terminate (int param);
  37.  
  38. static void *clientLoop(void *threadarg){
  39. int taskId, connfd, menulen, errlen, n, i, quit;
  40. struct threadData *clientData;
  41. char input[INPUT_SIZE];
  42. char option[INPUT_SIZE];
  43. int authenticated = 0;
  44.  
  45. char menuText [200]= {"Please select an option:\n1) Browse topic boards\n2) List all messages\n3) List all messages by a user\n4) Quit\n>"};
  46.  
  47. char errText[30] = "Invalid option.\n";
  48. char browsing[30] = "Browsing function\n";
  49. char listing[30] = "Listall function\n";
  50.  
  51. menulen = strlen(menuText);
  52. errlen = strlen(errText);
  53. clientData = (struct thread_data *) threadarg;
  54. taskId = clientData->threadId;
  55. connfd = clientData->connfd;
  56.  
  57. //1. authenticate user
  58. //2. send menu
  59. //3. receive choice
  60. //4. call function that handles that choice
  61. //5. loop to send menu again
  62.  
  63. //1. authenticate user
  64. //TODO: test authenticate function
  65. authenticated = authenticate(clientData);
  66. //printf("Authenticated %d", authenticated);
  67.  
  68. /*
  69. if(authenticated) {
  70. send(connfd, menuText, strlen(menuText) + 1, 0);
  71. printf("Sending options menu...");
  72. } else
  73. {
  74. write(connfd, "Authentication Failed", 22);
  75. printf("Authetication Failed");
  76. }
  77. */
  78. quit= 0;
  79. while(!quit && authenticated)
  80. {
  81. send(connfd, menuText, strlen(menuText) + 1, 0);
  82. printf("Sending options menu...\n");
  83. fflush(stdout);
  84.  
  85. //3. receive choice
  86. if ( ( n = recv (connfd, input, 12, 0) ) == 0 ) {
  87. //connection closed
  88. shutdown(connfd, SHUT_RDWR);
  89. close(connfd);
  90. connfd = -1;
  91. }
  92. /*else {
  93. if(strlen(input)>0) input[strlen(input)-1]='\0';
  94. printf("choice received %d \n", input[0]);
  95. sprintf(option, "Choice received %d \n", input[0]);
  96. send(connfd, option, strlen(option) + 1, 0);
  97. }*/
  98. else {
  99. if(strlen(input)>0) input[strlen(input)-1]='\0';
  100. i=0;
  101. while(input[i]!='\0')
  102. {
  103. if(input[i]>33 && input[i]<123)
  104. {
  105. input[i]=input[i];
  106. }
  107. i++;
  108. }
  109.  
  110. //4. call function that handles that choice
  111. switch (input[0]) {
  112. case '1':
  113. //TODO: test browse topic boards function
  114. browseTopics(clientData);
  115. // send(connfd, browsing, strlen(browsing) + 1, 0);
  116. break;
  117. case '2':
  118. //TODO: test list all messages function
  119. listAll(clientData);
  120. // send(connfd, listing, strlen(listing) + 1, 0);
  121. break;
  122. case '3':
  123. //TODO: test list all messages by a user function
  124. listByUser(clientData);
  125. break;
  126. case '4':
  127. quit = 1;
  128. break;
  129. default:
  130. send(connfd, errText, strlen(errText) + 1, 0);
  131. break;
  132. }
  133. }
  134.  
  135. }//5. loop to send menu again
  136. shutdown(connfd, SHUT_RDWR);
  137. close(connfd);
  138. }
  139.  
  140.  
  141. /* allows the user to log in
  142. returns if user is valid */
  143. int authenticate(struct threadData *clientData) {
  144. // 1) Prompts user for username
  145. // 2) Prompts user for password
  146. // 3) Connects to db
  147. // 4) Checks db for validity
  148. // 5) Returns if user is valid
  149. // 6) Disconnects from db
  150.  
  151. MYSQL *conn;
  152. MYSQL_RES *res;
  153. MYSQL_ROW row;
  154. int i, n, userId, connfd;
  155. struct threadData thisData = *clientData;
  156. char temp[INPUT_SIZE];
  157. char input[INPUT_SIZE];
  158. char username[INPUT_SIZE];
  159. char password[INPUT_SIZE];
  160. char query[256];
  161.  
  162. for(i= 0; i<INPUT_SIZE; i++)
  163. {
  164. input[i]= 0;
  165. }
  166.  
  167. connfd = clientData->connfd;
  168.  
  169. // 1) Prompts user for username
  170. send(connfd, "user: ", 7, 0);
  171. if ( (n = recv(connfd, input, 12, 0)) == 0){
  172. //connection closed
  173. shutdown(connfd, SHUT_RDWR);
  174. close(connfd);
  175. clientData->connfd = -1;
  176. return 0;
  177. }
  178. else {
  179. if(strlen(input)>0) input[strlen(input)-1]='\0';
  180. //strcpy(username, input);
  181. i=0;
  182. while(input[i]!='\0')
  183. {
  184. if(input[i]>33 && input[i]<123)
  185. {
  186. username[i]=input[i];
  187. }
  188. i++;
  189. }
  190. printf("username received\n");
  191. }
  192.  
  193. // 2) Prompts user for password
  194. send(connfd, "password: ", 11, 0);
  195. if ( (n = recv(connfd, input, 12, 0)) == 0){
  196. //connection closed
  197. shutdown(connfd, SHUT_RDWR);
  198. close(connfd);
  199. clientData->connfd = -1;
  200. return 0;
  201. }
  202. else {
  203. if(strlen(input)>0) input[strlen(input)-1]='\0';
  204. //strcpy(password, input);
  205. i=0;
  206. while(input[i]!='\0')
  207. {
  208. if(input[i]>33 && input[i]<123)
  209. {
  210. password[i]=input[i];
  211. }
  212. i++;
  213. }
  214. printf("password received\n");
  215. }
  216.  
  217. printf("'%s'", username);
  218. printf("\n");
  219. printf("'%s'", password);
  220. printf("\n");
  221.  
  222. // 3) Connects to db
  223. printf("connecting... %s", username);
  224. printf("\n");
  225.  
  226. conn= NULL;
  227. conn = mysql_init(NULL);
  228. if(conn!=NULL)
  229. {
  230. printf("initialized the database\n");
  231. } else {
  232. printf("Error initializing database\n");
  233. }
  234.  
  235. if (mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, DATABASE, 0, NULL, 0) == NULL) {
  236. printf("mysql error: %s\n", mysql_error(conn));
  237. printf("could not find connect");
  238. mysql_close(conn);
  239. return 0;
  240. } else {
  241. printf("Connected to database\n");
  242. }
  243.  
  244. // 4) Checks db for validity
  245. //sanitize this
  246.  
  247. sprintf(query, "SELECT id FROM Users WHERE username LIKE '%s' AND password LIKE SHA('%s')",
  248. username, password);
  249. if (mysql_query(conn, query)) {
  250. printf("query error: %s\n", mysql_error(conn));
  251. printf("could not find user\n");
  252. mysql_close(conn);
  253. return 0;
  254. } else {
  255. printf("Found user\n");
  256. }
  257.  
  258. // 5) Returns if user is valid
  259.  
  260. res = mysql_use_result(conn);
  261. if ( (row = mysql_fetch_row(res)) != NULL) {
  262. userId = *row[0] - 48;
  263. if (userId != 0) {
  264. thisData.userId = userId;
  265. printf("Authenication flag set\n");
  266. }
  267. else {
  268. mysql_free_result(res);
  269. mysql_close(conn);
  270. return 0;
  271. }
  272. } else {
  273. mysql_free_result(res);
  274. mysql_close(conn);
  275. send(connfd, "Authentication failed.\n", 24, 0);
  276. return 0;
  277. }
  278. *clientData = thisData;
  279.  
  280. // 6) Disconnects from db
  281.  
  282. mysql_free_result(res);
  283. mysql_close(conn);
  284.  
  285. return 1;
  286. }
  287.  
  288. /* allows the user to view the threads in each topical board */
  289. void browseTopics(struct threadData *clientData) {
  290. // 1) Connects to db
  291. // 2) Retrieves list of topics
  292. // 3) Sends menu with list to user
  293. // 4) Receives choice of topic
  294. // 5) Retrieves threads in topic
  295. // 6) Sends menu with thread titles to user
  296. // 7) Receives choice of threads
  297. // 8) Retrieves posts in thread
  298. // 9) Sends posts to user
  299. //10) Send menu with reply or quit to last menu (?)
  300. //11) Receieve menu choice
  301. //12) Calls addPost function if necessary
  302. //13) Disconnects from db
  303.  
  304. MYSQL *conn;
  305. MYSQL_RES *res;
  306. MYSQL_ROW row;
  307. int i, n, length, chosenTopicId, chosenThreadId, chosenPostId;
  308. int connfd;
  309. int topicIds[256], threadIds[256], postIds[256];
  310. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  311. char threadAuthors[256][16], postAuthors[256][16];
  312. char * posts[256];
  313. struct threadData thisData = *clientData;
  314. char input[INPUT_SIZE];
  315. char output[INPUT_SIZE];
  316. char query[256];
  317. char temp[10];
  318.  
  319. connfd = clientData->connfd;
  320.  
  321. // 1) Connects to db
  322.  
  323. conn = mysql_init(NULL);
  324. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  325. DATABASE, 0, NULL, 0)) {
  326. printf("mysql error: %s\n", mysql_error(conn));
  327. mysql_close(conn);
  328. return;
  329. }
  330.  
  331. // 2) Retrieves list of topics
  332. sprintf(query, "SELECT id, subject FROM Topics ORDER BY id ASC;");
  333. if (mysql_query(conn, query)) {
  334. printf("query error: %s\n", mysql_error(conn));
  335. mysql_close(conn);
  336. return;
  337. }
  338.  
  339. res = mysql_use_result(conn);
  340.  
  341. // 3) Sends list of topics to user
  342. send (connfd, "All topics:\n", 12, 0);
  343.  
  344. for ( i = 0; (row = mysql_fetch_row(res)) != NULL; i++) {
  345. temp[0] = row[0][0];
  346. temp[1] = row[0][1];
  347. topicIds[i] = atoi(temp);
  348. strcpy(topicSubjects[i], row[1]);
  349. sprintf(output, "%0d) %s\n", topicIds[i], topicSubjects[i]);
  350. length = strlen(output);
  351. send(connfd, output, length, 0);
  352. }
  353.  
  354. send (connfd, "\nPlease enter the number of the topic to view\n>", 47, 0);
  355.  
  356. // 4) Receives choice of topic
  357. // send(connfd, "user: ", 7, 0);
  358. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  359. //connection closed
  360. shutdown(connfd, SHUT_RDWR);
  361. close(connfd);
  362. clientData->connfd = -1;
  363. return;
  364. }
  365. else {
  366. //TODO: check that this is valid, sanitize
  367. chosenTopicId = atoi(input);
  368. }
  369.  
  370. // 5) Retrieves threads in topic
  371. sprintf(query, "SELECT Threads.title, Users.username, Threads.topic_id, Threads.id, Threads.user_id, Users.id FROM Threads, Users WHERE Threads.topic_id = '%d' AND Threads.user_id = Users.id ORDER BY Threads.id DESC;", chosenTopicId);
  372. if (mysql_query(conn, query)) {
  373. printf("query error: %s\n", mysql_error(conn));
  374. mysql_close(conn);
  375. return;
  376. }
  377.  
  378. row = NULL;
  379. mysql_free_result(res);
  380. res = mysql_use_result(conn);
  381.  
  382. // 6) Sends menu with thread titles to user
  383. for ( i = 0; (row = mysql_fetch_row(res)) != NULL; i++ ){
  384. temp[0] = row[3][0];
  385. temp[1] = row[3][1];
  386. threadIds[i] = atoi(temp);
  387. strcpy(threadTitles[i], row[0]);
  388. strcpy(threadAuthors[i], row[1]);
  389. sprintf(output, "\n%d) %s: %s\n", threadIds[i], threadAuthors[i], threadTitles[i]);
  390. length = strlen(output);
  391. send(connfd, output, length, 0);
  392. }
  393. sprintf(output, "\nNumber of the topic, or (n)ew topic\n>");
  394. length = strlen(output) + 1;
  395. send(connfd, output, length, 0);
  396.  
  397. // 7) Recieves choice of threads
  398. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  399. //connection closed
  400. shutdown(connfd, SHUT_RDWR);
  401. close(connfd);
  402. clientData->connfd = -1;
  403. return;
  404. }
  405. else {
  406. if (input[0] == 'n' || input[0] == 'N')
  407. {
  408. addThread(clientData, chosenTopicId);
  409. mysql_free_result(res);
  410. mysql_close(conn);
  411. return;
  412. }
  413. //TODO: check that this is valid, sanitize
  414. chosenThreadId = atoi(input);
  415. }
  416.  
  417. // 8) Retrieves posts in thread
  418. sprintf(query, "SELECT Posts.title, Posts.message, Posts.id, Posts.user_id, Posts.thread_id, Posts.time, Users.username, Users.id, Posts.topic_id FROM Posts, Users WHERE Posts.topic_id = %d AND Posts.thread_id = %d AND Posts.user_id = Users.id ORDER BY Posts.time ASC;", chosenTopicId, chosenThreadId);
  419. if (mysql_query(conn, query)) {
  420. printf("query error: %s\n", mysql_error(conn));
  421. mysql_close(conn);
  422. return;
  423. }
  424. //printf(query);
  425.  
  426. row = NULL;
  427. send (connfd, "Posts:\n\n", 8, 0);
  428. mysql_free_result(res);
  429. res = mysql_use_result(conn);
  430.  
  431. // 9) Sends posts to user
  432. for ( i = 0; (row = mysql_fetch_row(res)) != NULL; i++ ){
  433. strcpy( postTitles[i], row[0] );
  434. temp[0] = row[2][0];
  435. temp[1] = row[2][1];
  436. postIds[i] = atoi(temp);
  437. strcpy (postAuthors[i], row[6]);
  438. posts[i] = malloc ( strlen(row[1]) );
  439. strcpy( posts[i], row[1] );
  440. sprintf(output, "%d) %s: %s\n--\n%s\n\n", postIds[i], postAuthors[i], postTitles[i], posts[i]);
  441. length = strlen(output);
  442. send(connfd, output, length, 0);
  443. }
  444.  
  445. //10) Sends menu with reply or go to main menu
  446. send (connfd, "\n(r)eply, or (d)elete, or (m)ain menu\n>", 40, 0);
  447.  
  448. //11) Receive menu choice
  449. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  450. //connection closed
  451. shutdown(connfd, SHUT_RDWR);
  452. close(connfd);
  453. clientData->connfd = -1;
  454. return;
  455. }
  456.  
  457. //12) Calls addPost function if necessary
  458. if (input[0] == 'r' || input[0] == 'R') {
  459. //TODO: implement post reply
  460. addPost(clientData, chosenTopicId, chosenThreadId);
  461. }else if (input[0] == 'd' || input[0] == 'D') {
  462. deletePost(clientData);
  463. }else if (input[0] == 'm' || input[0] == 'M') {
  464. mysql_free_result(res);
  465. mysql_close(conn);
  466. return;
  467. }
  468.  
  469. //13) Disconnects from db
  470. mysql_free_result(res);
  471. mysql_close(conn);
  472. }
  473.  
  474. /* lists all posts in any thread */
  475. void listAll(struct threadData *clientData) {
  476. // 1) Connects to db
  477. // 2) Retrieves all posts
  478. // 3) Sends all posts to user (descending by timestamp)
  479. // 4) Receives menu choice
  480. // 5) Calls deletePost if necessary
  481. // 6) Disconnects from database
  482.  
  483. MYSQL *conn;
  484. MYSQL_RES *res;
  485. MYSQL_ROW row;
  486. int i, n, length, chosenId, connfd;
  487. int topicIds[256], threadIds[256], postIds[256];
  488. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  489. char threadAuthors[256][16], postAuthors[256][16];
  490. char * posts[256];
  491. struct threadData thisData = *clientData;
  492. char input[INPUT_SIZE];
  493. char output[INPUT_SIZE];
  494. char query[256];
  495. char temp[10];
  496.  
  497. connfd = clientData->connfd;
  498.  
  499. printf("listing all posts...\n");
  500. // 1) Connects to db
  501.  
  502. conn = mysql_init(NULL);
  503. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  504. DATABASE, 0, NULL, 0)) {
  505. printf("mysql error: %s\n", mysql_error(conn));
  506. mysql_close(conn);
  507. return;
  508. }
  509.  
  510. printf("retrieving results...\n");
  511. // 2) Retrieves posts in any thread
  512. sprintf(query, "SELECT Posts.title, Posts.message, Posts.id, Posts.user_id, Posts.thread_id, Posts.time, Users.username, Users.id FROM Posts, Users WHERE Posts.user_id= Users.id ORDER BY Posts.time DESC;");
  513. if (mysql_query(conn, query)) {
  514. printf("query error: %s\n", mysql_error(conn));
  515. mysql_close(conn);
  516. return;
  517. }
  518.  
  519. row = NULL;
  520. send (connfd, "Posts:\n", 7, 0);
  521. res = mysql_use_result(conn);
  522.  
  523. // 3) Sends posts to user
  524. for ( i = 0; (row = mysql_fetch_row(res)) != NULL; i++ ){
  525. strcpy( postTitles[i], row[0] );
  526. temp[0] = row[2][0];
  527. temp[1] = row[2][1];
  528. postIds[i] = atoi(temp);
  529. strcpy (postAuthors[i], row[6]);
  530. posts[i] = malloc ( strlen(row[1]) + 1 );
  531. strcpy( posts[i], row[1] );
  532. sprintf(output, "%d) %s: %s\n%s\n--\n\n", postIds[i], postAuthors[i], postTitles[i], posts[i]);
  533. length = strlen(output);
  534. send(connfd, output, length, 0);
  535. }
  536.  
  537. send (connfd, "\n\n(d)elete, or (m)ain menu\n>", 28, 0);
  538.  
  539. // 4) Receive menu choice
  540. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  541. //connection closed
  542. shutdown(connfd, SHUT_RDWR);
  543. close(connfd);
  544. clientData->connfd = -1;
  545. return;
  546. }
  547.  
  548. // 5) Calls deletePost function if necessary
  549. if (input[0] == 'd' || input[0] == 'D') {
  550. deletePost(clientData);
  551. }else if (input[0] == 'm' || input[0] == 'M') {
  552. mysql_free_result(res);
  553. mysql_close(conn);
  554. return;
  555. }
  556.  
  557. // 6) Disconnects from db
  558. mysql_free_result(res);
  559. mysql_close(conn);
  560. }
  561.  
  562. /* lists all posts by the specifed user */
  563. void listByUser(struct threadData *clientData) {
  564. // 1) Connects to db
  565. // 2) Requests a username to use
  566. // 3) Retrieves username
  567. // 4) Retrieves posts by username
  568. // 5) Sends posts to user
  569. // 6) Receives menu choice
  570. // 7) Calls deletePost if necessary
  571. // 8) Disconnects from db
  572.  
  573. MYSQL *conn;
  574. MYSQL_RES *res;
  575. MYSQL_ROW row;
  576. int i, n, length, chosenId, connfd;
  577. int topicIds[256], threadIds[256], postIds[256];
  578. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  579. char threadAuthors[256][16], postAuthors[256][16];
  580. char * posts[256];
  581. struct threadData thisData = *clientData;
  582. char input[INPUT_SIZE];
  583. char output[INPUT_SIZE];
  584. char username[INPUT_SIZE];
  585. char query[256];
  586. char temp[10];
  587.  
  588. connfd = clientData->connfd;
  589. chosenId = clientData->userId;
  590.  
  591. // 1) Connects to db
  592.  
  593. conn = mysql_init(NULL);
  594. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  595. DATABASE, 0, NULL, 0)) {
  596. printf("mysql error: %s\n", mysql_error(conn));
  597. mysql_close(conn);
  598. return;
  599. }
  600.  
  601. fflush(stdin);
  602. // 2) Requests a username to use
  603. send (connfd, "Enter a username\n>", 18, 0);
  604.  
  605. for(i=0; i<INPUT_SIZE; i++)
  606. {
  607. username[i]='\0';
  608. }
  609. // 3) Retrieves username
  610. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  611. //connection closed
  612. shutdown(connfd, SHUT_RDWR);
  613. close(connfd);
  614. clientData->connfd = -1;
  615. return;
  616. }
  617.  
  618. else {
  619. if(strlen(input)>0) input[strlen(input)-1]='\0';
  620. i=0;
  621. while(input[i]!='\0')
  622. {
  623. if(input[i]>33 && input[i]<123)
  624. {
  625. username[i]=input[i];
  626. }
  627. i++;
  628. }
  629. username[i]='\0';
  630. }
  631.  
  632. // 4) Retrieves posts by username
  633. sprintf(query, "SELECT Posts.title, Posts.message, Posts.id, Posts.user_id, Posts.thread_id, Posts.time, Users.username, Users.id FROM Posts, Users WHERE Users.username = '%s' AND Posts.user_id = Users.id ORDER BY Posts.time DESC;", username);
  634. printf(query);
  635. if (mysql_query(conn, query)) {
  636. printf("query error: %s\n", mysql_error(conn));
  637. mysql_close(conn);
  638. return;
  639. }
  640.  
  641. fflush(stdout);
  642. row = NULL;
  643. send (connfd, "Posts:\n", 7, 0);
  644. res = mysql_use_result(conn);
  645.  
  646. // 5) Sends posts to user
  647. for ( i = 0; (row = mysql_fetch_row(res)) != NULL; i++ ){
  648. strcpy( postTitles[i], row[0] );
  649. temp[0] = row[2][0];
  650. temp[1] = row[2][1];
  651. postIds[i] = atoi(temp);
  652. strcpy (postAuthors[i], row[6]);
  653. posts[i] = malloc ( strlen(row[1]) );
  654. strcpy( posts[i], row[1] );
  655. sprintf(output, "%d) %s: %s\n--\n%s\n\n", postIds[i], postAuthors[i], postTitles[i], posts[i]);
  656. length = strlen(output);
  657. send(connfd, output, length, 0);
  658. }
  659.  
  660. send (connfd, "\n\n(d)elete, or (m)ain menu\n>", 28, 0);
  661.  
  662. // 6) Receive menu choice
  663. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  664. //connection closed
  665. shutdown(connfd, SHUT_RDWR);
  666. close(connfd);
  667. clientData->connfd = -1;
  668. return;
  669. }
  670.  
  671. // 7) Calls deletePost function if necessary
  672. if (input[0] == 'd' || input[0] == 'D') {
  673. deletePost(clientData);
  674. }else if (input[0] == 'm' || input[0] == 'M') {
  675. mysql_free_result(res);
  676. mysql_close(conn);
  677. return;
  678. }
  679.  
  680. // 8) Disconnects from db
  681. mysql_free_result(res);
  682. mysql_close(conn);
  683. }
  684.  
  685. /* adds a reply to a thread */
  686. void addPost(struct threadData *clientData, int topicId, int threadId) {
  687. // 1) Connects to db
  688. // 2) Prompts user for post
  689. // 3) Inserts post into thread
  690. // 4) Disconnects from db
  691.  
  692. MYSQL *conn;
  693. MYSQL_RES *res;
  694. MYSQL_ROW row;
  695. int i, n, length, chosenId, connfd, userId;
  696. int topicIds[256], threadIds[256], postIds[256];
  697. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  698. char threadAuthors[256][16], postAuthors[256][16];
  699. char * posts[256];
  700. struct threadData thisData = *clientData;
  701. char input[INPUT_SIZE];
  702. char output[INPUT_SIZE];
  703. char query[256];
  704. char post[INPUT_SIZE];
  705. char title[INPUT_SIZE];
  706.  
  707. connfd = thisData.connfd;
  708. userId = thisData.userId;
  709.  
  710. // 1) Connects to db
  711.  
  712. // 2) Prompts for post input
  713. send(connfd, "Enter your title\n", 17, 0);
  714.  
  715. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  716. //connection closed
  717. shutdown(connfd, SHUT_RDWR);
  718. close(connfd);
  719. clientData->connfd = -1;
  720. return;
  721. }
  722.  
  723. else {
  724. if(strlen(input)>0) input[strlen(input)-1]='\0';
  725. i=0;
  726. while(input[i]!='\0')
  727. {
  728. if(input[i]>31 && input[i]<123)
  729. {
  730. title[i]=input[i];
  731. }
  732. i++;
  733. }
  734. // strcpy(title, input);
  735. printf("title received: '%s'\n", title);
  736. }
  737. input[0] = '\0';
  738.  
  739. send(connfd, "Enter your post\n>", 18, 0);
  740.  
  741. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  742. //connection closed
  743. shutdown(connfd, SHUT_RDWR);
  744. close(connfd);
  745. clientData->connfd = -1;
  746. return;
  747. }
  748. else {
  749. if(strlen(input)>0) input[strlen(input)-1]='\0';
  750. i=0;
  751. while(input[i]!='\0')
  752. {
  753. if(input[i]>31 && input[i]<123)
  754. {
  755. post[i]=input[i];
  756. }
  757. i++;
  758. }
  759. //strcpy(post, input);
  760. printf("post received: '%s'\n", post);
  761. }
  762. // 3) Inserts post into db
  763. // 1) Connects to db
  764.  
  765. conn = mysql_init(NULL);
  766. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  767. DATABASE, 0, NULL, 0)) {
  768. printf("mysql error: %s\n", mysql_error(conn));
  769. mysql_close(conn);
  770. return;
  771. }
  772. printf("connection established\n");
  773. sprintf(query, "INSERT INTO Posts (topic_id, thread_id, user_id, title, message) VALUES (%d, %d, %d, '%s', '%s');", topicId, threadId, userId, title, post);
  774. printf("executing query: '%s'\n", query);
  775. if (mysql_query(conn, query)) {
  776. printf("query error: %s\n", mysql_error(conn));
  777. mysql_close(conn);
  778. return;
  779. }
  780. printf("query done");
  781.  
  782. // 4) Closes database
  783. mysql_close(conn);
  784. }
  785.  
  786. /* deletes a post from a thread */
  787. void deletePost(struct threadData *clientData) {
  788. // 1) Connect to db
  789. // 2) Prompt user for post
  790. // 3) Check if user has permissions
  791. // 4) Deletes post from thread
  792. // 5) Disconnects from db
  793.  
  794. MYSQL *conn;
  795. MYSQL_RES *res;
  796. MYSQL_ROW row;
  797. int i, n, length, chosenId, connfd, userId, postId, deletePostId;
  798. int topicIds[256], threadIds[256], postIds[256];
  799. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  800. char threadAuthors[256][16], postAuthors[256][16];
  801. char * posts[256];
  802. struct threadData thisData = *clientData;
  803. char input[INPUT_SIZE];
  804. char output[INPUT_SIZE];
  805. char query[256];
  806. char post[INPUT_SIZE];
  807. char title[INPUT_SIZE];
  808. char temp[10];
  809.  
  810. connfd = clientData->connfd;
  811. userId = clientData->userId;
  812.  
  813. // 1) Connects to db
  814.  
  815. conn = mysql_init(NULL);
  816. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  817. DATABASE, 0, NULL, 0)) {
  818. printf("mysql error: %s\n", mysql_error(conn));
  819. mysql_close(conn);
  820. return;
  821. }
  822.  
  823. // 2) Prompts for post id
  824. send(connfd, "Enter post ID to delete:\n", 25, 0);
  825. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0) {
  826. //connection closed
  827. shutdown(connfd, SHUT_RDWR);
  828. close(connfd);
  829. clientData->connfd = -1;
  830. return;
  831. }
  832. else {
  833. postId= atoi(input);
  834. }
  835.  
  836. // 3) Check if user has permissions
  837.  
  838. sprintf(query, "Delete from Posts WHERE id = %d AND user_id = %d;", postId, userId);
  839. printf(query);
  840. if (mysql_query(conn, query)) {
  841. printf("query error: %s\n", mysql_error(conn));
  842. mysql_close(conn);
  843. return;
  844. }
  845.  
  846. if(mysql_affected_rows(conn) == 0)
  847. {
  848. send(connfd, "Access Denied. Post was not deleted\n\n", 37, 0);
  849. }else {
  850. printf("Post deleted successfully");
  851. send(connfd, "Post deleted succesfully\n\n", 27, 0);
  852. }
  853.  
  854. mysql_close(conn);
  855. }
  856.  
  857. /* adds a new thread to a topic */
  858. void addThread(struct threadData *clientData, int topicNum) {
  859. // 1) Connects to db
  860. // 2) Prompts user for thread
  861. // 3) Creates thread in db
  862. // 4) Queries db for the thread ID that was used
  863. // 5) Disconnects from db
  864. // 6) Calls addPost
  865.  
  866. MYSQL *conn;
  867. MYSQL_RES *res;
  868. MYSQL_ROW row;
  869. int i, n, length, topicId, connfd, userId, threadId;
  870. int topicIds[256], threadIds[256], postIds[256];
  871. char topicSubjects[256][20], threadTitles[256][20], postTitles[256][20];
  872. char threadAuthors[256][16], postAuthors[256][16];
  873. char * posts[256];
  874. struct threadData thisData = *clientData;
  875. char input[INPUT_SIZE];
  876. char output[INPUT_SIZE];
  877. char query[256];
  878. char * post;
  879. char title[INPUT_SIZE];
  880.  
  881. connfd = thisData.connfd;
  882. userId = thisData.userId;
  883. topicId = topicNum;
  884.  
  885. // 1) Connects to db
  886.  
  887. conn = mysql_init(NULL);
  888. if (!mysql_real_connect(conn, MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD,
  889. DATABASE, 0, NULL, 0)) {
  890. printf("mysql error: %s\n", mysql_error(conn));
  891. mysql_close(conn);
  892. return;
  893. }
  894.  
  895. // 2) Prompts for post input
  896. send(connfd, "Enter a thread title\n>", 23, 0);
  897.  
  898. if ( (n = recv(connfd, input, INPUT_SIZE, 0)) == 0){
  899. //connection closed
  900. shutdown(connfd, SHUT_RDWR);
  901. close(connfd);
  902. clientData->connfd = -1;
  903. return;
  904. }
  905.  
  906. else {
  907. if(strlen(input)>0) input[strlen(input)-1]='\0';
  908. i=0;
  909. while(input[i]!='\0')
  910. {
  911. if(input[i]>33 && input[i]<123)
  912. {
  913. title[i]=input[i];
  914. }
  915. i++;
  916. }
  917. }
  918.  
  919. // 3) Creates thread in db
  920. sprintf(query, "INSERT INTO Threads (topic_id, user_id, title) VALUE (%d, %d, '%s');", topicId, userId, input);
  921. if (mysql_query(conn, query)) {
  922. printf("query error: %s\n", mysql_error(conn));
  923. mysql_close(conn);
  924. return;
  925. }
  926.  
  927. // 4) Queries db for the thread ID that was used
  928. sprintf(query, "SELECT id FROM Threads WHERE Threads.user_id = %d ORDER BY Threads.id DESC LIMIT 1;");
  929. if (mysql_query(conn, query)) {
  930. printf("query error: %s\n", mysql_error(conn));
  931. mysql_close(conn);
  932. return;
  933. }
  934.  
  935. row = NULL;
  936. res = mysql_use_result(conn);
  937.  
  938. if ( (row = mysql_fetch_row(res) ) != NULL)
  939. {
  940. threadId = *row[0] - 0x30;
  941. }
  942.  
  943. // 5) Disconnects from db
  944. mysql_free_result(res);
  945. mysql_close(conn);
  946.  
  947. // 6) Calls addPost
  948. addPost(clientData, topicId, threadId);
  949.  
  950. }
  951.  
  952.  
  953. /*entry point of server*/
  954. int main(int argc, char ** argv){
  955. /*variables*/
  956. int i, maxi, maxfd, listenfd, connfd, sockfd, nready;
  957. pthread_t threads[NUM_CLIENTS];
  958. ssize_t n;
  959. fd_set rset, allset;
  960. struct sockaddr_in cliaddr, servaddr;
  961. void (*prev_fn)(int);
  962.  
  963. //Handle kill signal
  964. prev_fn = signal (SIGINT, terminate);
  965.  
  966. printf("starting server...\n");
  967. /*prepare port*/
  968. listenfd = socket (AF_INET, SOCK_STREAM, 0);
  969. bzero (&servaddr, sizeof(servaddr));
  970. servaddr.sin_family = AF_INET;
  971. servaddr.sin_port = htons(PORT);
  972. servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  973.  
  974. if(bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))==-1)
  975. {
  976. perror ("on bind");
  977. exit (-1);
  978. }
  979. listen(listenfd, 1);
  980. printf("waiting for clients\n");
  981.  
  982. /*initialize*/
  983. for (i = 0; i < NUM_CLIENTS; i++){
  984. threadDataArray[i].connfd = -1;
  985. }
  986.  
  987. int sizeofCliaddr = sizeof(cliaddr);
  988. /*main loop*/
  989. for ( ; ; ) {
  990. if ( (connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &sizeofCliaddr)) > 0 ){
  991. printf("client accepted\n");
  992. //new client connection
  993. //we are going to save where we put it in a struct array
  994. //then spawn a thread to deal with the new struct
  995. for (i = 0; i < NUM_CLIENTS; i++) {
  996. if (threadDataArray[i].connfd < 0) {
  997. printf("creating thread...\n");
  998. threadDataArray[i].connfd = connfd;
  999. threadDataArray[i].threadId = i;
  1000. int rc = pthread_create(&threads[i], NULL, &clientLoop, &threadDataArray[i]);
  1001. if (rc)
  1002. {
  1003. printf("thread create failed. return code is %d\n", rc);
  1004. }
  1005. //send(connfd, "user: ", 7);
  1006. //clientLoop(&threadDataArray[i]);
  1007.  
  1008. break;
  1009. }
  1010. }
  1011. }
  1012. }
  1013. }
  1014.  
  1015. void terminate (int param)
  1016. {
  1017. printf("terminating server...");
  1018. char *cmd = "killall bbs.out";
  1019. system(cmd);
  1020. exit(1);
  1021. }
Add Comment
Please, Sign In to add comment