ServerMain.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. #define _POSIX_C_SOURCE 1
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <signal.h>
  6. #include <string.h>
  7. #include <dirent.h>
  8. #include <sys/stat.h>
  9. #include <sys/types.h>
  10. #include <sys/file.h>
  11. #include <fcntl.h>
  12. #include <dirent.h>
  13. #include <assert.h>
  14. #include "Server.h"
  15. #include "String.h"
  16. #include <string.h>
  17. int getMailCounter()
  18. {
  19. FILE* test = fopen("mailcounter", "r+");
  20. if(test == NULL)
  21. {
  22. if(creat("mailcounter", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
  23. {
  24. return 0;
  25. }
  26. test = fopen("mailcounter", "r+");
  27. if(test == NULL)
  28. {
  29. return 0;
  30. }
  31. }
  32. flock(fileno(test), LOCK_EX);
  33. int counter;
  34. if(fread(&counter, sizeof(int), 1, test) == 0)
  35. {
  36. counter = -1;
  37. }
  38. counter++;
  39. rewind(test);
  40. if(fwrite(&counter, sizeof(int), 1, test) == 0)
  41. {
  42. return 0;
  43. }
  44. if(fflush(test) == EOF)
  45. {
  46. return 0;
  47. }
  48. flock(fileno(test), LOCK_UN);
  49. if(fclose(test) == EOF)
  50. {
  51. return 0;
  52. }
  53. return counter;
  54. }
  55. int isSpecialFolder(char* folder)
  56. {
  57. return strcmp(folder, ".") == 0 || strcmp(folder, "..") == 0;
  58. }
  59. Server server;
  60. void interruptHandler(int signal)
  61. {
  62. serverRemove(&server);
  63. exit(EXIT_SUCCESS);
  64. }
  65. void ensureBufferIndex(char** data, int* size, int index)
  66. {
  67. if(index >= *size)
  68. {
  69. int newSize = *size;
  70. while(newSize <= index)
  71. {
  72. newSize *= 2;
  73. }
  74. char* newData = malloc(sizeof(char) * newSize);
  75. memcpy(newData, *data, *size);
  76. *size = newSize;
  77. free(*data);
  78. *data = newData;
  79. }
  80. }
  81. void packageSendFailAnswer(int clientSocket)
  82. {
  83. Stream out;
  84. streamInit(&out, 16);
  85. streamWriteChars(&out, "ERR\n");
  86. serverSend(clientSocket, &out);
  87. streamRemove(&out);
  88. }
  89. void packageSendOkAnswer(int clientSocket)
  90. {
  91. Stream out;
  92. streamInit(&out, 16);
  93. streamWriteChars(&out, "OK\n");
  94. serverSend(clientSocket, &out);
  95. streamRemove(&out);
  96. }
  97. int createDirectory(char* path)
  98. {
  99. DIR* dir = opendir(path);
  100. if(dir == NULL)
  101. {
  102. if(mkdir(path, S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
  103. {
  104. perror("create dir fail");
  105. return -1;
  106. }
  107. dir = opendir(path);
  108. if(dir == NULL)
  109. {
  110. perror("open dir fail");
  111. return -1;
  112. }
  113. }
  114. if(closedir(dir))
  115. {
  116. perror("close dir fail");
  117. return -1;
  118. }
  119. if(chdir(path) == -1)
  120. {
  121. perror("change dir fail");
  122. return -1;
  123. }
  124. return 0;
  125. }
  126. void storeMail(char* sender, char* receiver, char* subject, char* message)
  127. {
  128. if(createDirectory(receiver) == -1)
  129. {
  130. return;
  131. }
  132. int id = getMailCounter();
  133. if(createDirectory(sender) == -1)
  134. {
  135. return;
  136. }
  137. char buffer[12];
  138. snprintf(buffer, 12, "%d", id);
  139. if(creat(buffer, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
  140. {
  141. return;
  142. }
  143. FILE* file = fopen(buffer, "w");
  144. if(file == NULL)
  145. {
  146. perror("cant open file");
  147. return;
  148. }
  149. if(fputs(sender, file) == EOF)
  150. {
  151. perror("cant write to file");
  152. return;
  153. }
  154. if(fputc('\n', file) == EOF)
  155. {
  156. perror("cant write to file");
  157. return;
  158. }
  159. if(fputs(receiver, file) == EOF)
  160. {
  161. perror("cant write to file");
  162. return;
  163. }
  164. if(fputc('\n', file) == EOF)
  165. {
  166. perror("cant write to file");
  167. return;
  168. }
  169. if(fputs(subject, file) == EOF)
  170. {
  171. perror("cant write to file");
  172. return;
  173. }
  174. if(fputc('\n', file) == EOF)
  175. {
  176. perror("cant write to file");
  177. return;
  178. }
  179. if(fputs(message, file) == EOF)
  180. {
  181. perror("cant write to file");
  182. return;
  183. }
  184. if(fflush(file) == EOF)
  185. {
  186. perror("cant flush the file");
  187. return;
  188. }
  189. if(fclose(file) == EOF)
  190. {
  191. perror("cant close");
  192. return;
  193. }
  194. }
  195. int packageSend(int client, int clientSocket, Stream* in)
  196. {
  197. char* user = serverGetUser(&server, client);
  198. if(user == NULL)
  199. {
  200. packageSendFailAnswer(clientSocket);
  201. return 0;
  202. }
  203. int length;
  204. // receiver
  205. String receiver;
  206. stringInit(&receiver);
  207. stringReadStreamLine(&receiver, in);
  208. length = stringGetLength(&receiver);
  209. if(length == 0 || length > 8)
  210. {
  211. packageSendFailAnswer(clientSocket);
  212. stringRemove(&receiver);
  213. return 0;
  214. }
  215. // subject
  216. String subject;
  217. stringInit(&subject);
  218. stringReadStreamLine(&subject, in);
  219. length = stringGetLength(&subject);
  220. if(length == 0 || length > 80)
  221. {
  222. packageSendFailAnswer(clientSocket);
  223. stringRemove(&subject);
  224. return 0;
  225. }
  226. // message
  227. int index = 0;
  228. int buffer = 16;
  229. char* message = malloc(sizeof(char) * buffer);
  230. String sMessage;
  231. stringInit(&sMessage);
  232. while(streamHasData(in))
  233. {
  234. stringReadStreamLine(&sMessage, in);
  235. if(stringCompare(&sMessage, ".") || buffer > 60)
  236. {
  237. break;
  238. }
  239. int length = stringGetLength(&sMessage);
  240. // "i + length" is one too much but right for "length + \n"
  241. ensureBufferIndex(&message, &buffer, index + length);
  242. memcpy(message + index, sMessage.data, length);
  243. index += length;
  244. message[index] = '\n';
  245. index++;
  246. }
  247. stringRemove(&sMessage);
  248. char workingPath[256];
  249. if(getcwd(workingPath, 256) != NULL)
  250. {
  251. storeMail(user, receiver.data, subject.data, message);
  252. assert(chdir(workingPath) == 0);
  253. }
  254. stringRemove(&receiver);
  255. stringRemove(&subject);
  256. free(message);
  257. packageSendOkAnswer(clientSocket);
  258. return 0;
  259. }
  260. void sendMailList(char* user, Stream* out)
  261. {
  262. DIR* receiverDir = opendir(user);
  263. if(receiverDir == NULL)
  264. {
  265. streamWriteChars(out, "0\n");
  266. return;
  267. }
  268. assert(chdir(user) == 0);
  269. // count mails first, this is easier than buffering everything else
  270. int counter = 0;
  271. struct dirent* receiverIterator = readdir(receiverDir);
  272. while(receiverIterator != NULL)
  273. {
  274. if(!isSpecialFolder(receiverIterator->d_name))
  275. {
  276. DIR* senderDir = opendir(receiverIterator->d_name);
  277. if(senderDir != NULL)
  278. {
  279. assert(chdir(receiverIterator->d_name) == 0);
  280. struct dirent* senderIterator = readdir(senderDir);
  281. while(senderIterator != NULL)
  282. {
  283. if(!isSpecialFolder(senderIterator->d_name))
  284. {
  285. // mails found
  286. counter++;
  287. }
  288. senderIterator = readdir(senderDir);
  289. }
  290. assert(chdir("../") == 0);
  291. closedir(senderDir);
  292. }
  293. }
  294. receiverIterator = readdir(receiverDir);
  295. }
  296. // write the number of mails
  297. char buffer[12];
  298. snprintf(buffer, 12, "%d", counter);
  299. streamWriteChars(out, buffer);
  300. streamWriteChar(out, '\n');
  301. // add the mail subjects
  302. assert(chdir("../") == 0);
  303. closedir(receiverDir);
  304. receiverDir = opendir(user);
  305. if(receiverDir == NULL)
  306. {
  307. return;
  308. }
  309. assert(chdir(user) == 0);
  310. receiverIterator = readdir(receiverDir);
  311. while(receiverIterator != NULL)
  312. {
  313. if(!isSpecialFolder(receiverIterator->d_name))
  314. {
  315. DIR* senderDir = opendir(receiverIterator->d_name);
  316. if(senderDir != NULL)
  317. {
  318. assert(chdir(receiverIterator->d_name) == 0);
  319. struct dirent* senderIterator = readdir(senderDir);
  320. while(senderIterator != NULL)
  321. {
  322. if(!isSpecialFolder(senderIterator->d_name))
  323. {
  324. // reading subject from first line
  325. FILE* file = fopen(senderIterator->d_name, "r");
  326. if(file != NULL)
  327. {
  328. streamWriteChars(out, senderIterator->d_name);
  329. streamWriteChars(out, " - ");
  330. //skip first 2 lines (receiver, sender)
  331. int skip = 0;
  332. int data;
  333. while(1)
  334. {
  335. data = fgetc(file);
  336. if(data == '\n' || data == EOF)
  337. {
  338. skip++;
  339. if(skip == 2)
  340. {
  341. break;
  342. }
  343. }
  344. }
  345. while(1)
  346. {
  347. data = fgetc(file);
  348. if(data == '\n' || data == EOF)
  349. {
  350. break;
  351. }
  352. streamWriteChar(out, data);
  353. }
  354. streamWriteChar(out, '\n');
  355. if(fclose(file) == EOF)
  356. {
  357. perror("cannot close file");
  358. }
  359. }
  360. else
  361. {
  362. streamWriteChars(out, "ERR\n");
  363. }
  364. }
  365. senderIterator = readdir(senderDir);
  366. }
  367. assert(chdir("../") == 0);
  368. closedir(senderDir);
  369. }
  370. }
  371. receiverIterator = readdir(receiverDir);
  372. }
  373. closedir(receiverDir);
  374. }
  375. int packageList(int client, int clientSocket, Stream* in)
  376. {
  377. char* user = serverGetUser(&server, client);
  378. if(user == NULL)
  379. {
  380. packageSendFailAnswer(clientSocket);
  381. return 0;
  382. }
  383. Stream out;
  384. streamInit(&out, 16);
  385. char workingPath[256];
  386. if(getcwd(workingPath, 256) != NULL)
  387. {
  388. sendMailList(user, &out);
  389. assert(chdir(workingPath) == 0);
  390. }
  391. serverSend(clientSocket, &out);
  392. streamRemove(&out);
  393. return 0;
  394. }
  395. void readMail(char* user, char* number, Stream* out)
  396. {
  397. DIR* receiverDir = opendir(user);
  398. if(receiverDir == NULL)
  399. {
  400. streamWriteChars(out, "ERR\n");
  401. return;
  402. }
  403. assert(chdir(user) == 0);
  404. struct dirent* receiverIterator;
  405. receiverIterator = readdir(receiverDir);
  406. while(receiverIterator != NULL)
  407. {
  408. if(!isSpecialFolder(receiverIterator->d_name))
  409. {
  410. if(chdir(receiverIterator->d_name) == 0)
  411. {
  412. FILE* file = fopen(number, "r");
  413. if(file != NULL)
  414. {
  415. streamWriteChars(out, "OK\n");
  416. // write data to stream
  417. int data;
  418. while(1)
  419. {
  420. data = fgetc(file);
  421. if(data == EOF)
  422. {
  423. break;
  424. }
  425. streamWriteChar(out, data);
  426. }
  427. if(fclose(file) == EOF)
  428. {
  429. perror("cannot close file");
  430. }
  431. if(closedir(receiverDir) == -1)
  432. {
  433. perror("cannot close receiver dir");
  434. }
  435. return;
  436. }
  437. assert(chdir("../") == 0);
  438. }
  439. }
  440. receiverIterator = readdir(receiverDir);
  441. }
  442. if(closedir(receiverDir) == -1)
  443. {
  444. perror("cannot close dir");
  445. }
  446. streamWriteChars(out, "ERR\n");
  447. }
  448. int packageRead(int client, int clientSocket, Stream* in)
  449. {
  450. char* user = serverGetUser(&server, client);
  451. if(user == NULL)
  452. {
  453. packageSendFailAnswer(clientSocket);
  454. return 0;
  455. }
  456. // number
  457. String number;
  458. stringInit(&number);
  459. stringReadStreamLine(&number, in);
  460. if(stringGetLength(&number) == 0)
  461. {
  462. packageSendFailAnswer(clientSocket);
  463. stringRemove(&number);
  464. return 0;
  465. }
  466. Stream out;
  467. streamInit(&out, 16);
  468. char workingPath[256];
  469. if(getcwd(workingPath, 256) != NULL)
  470. {
  471. readMail(user, number.data, &out);
  472. assert(chdir(workingPath) == 0);
  473. }
  474. else
  475. {
  476. streamWriteChars(&out, "ERR\n");
  477. }
  478. stringRemove(&number);
  479. serverSend(clientSocket, &out);
  480. streamRemove(&out);
  481. return 0;
  482. }
  483. int deleteMail(char* user, char* number)
  484. {
  485. DIR* receiverDir = opendir(user);
  486. if(receiverDir == NULL)
  487. {
  488. return 0;
  489. }
  490. assert(chdir(user) == 0);
  491. int rValue = 0;
  492. struct dirent* receiverIterator;
  493. receiverIterator = readdir(receiverDir);
  494. while(receiverIterator != NULL)
  495. {
  496. if(!isSpecialFolder(receiverIterator->d_name))
  497. {
  498. if(chdir(receiverIterator->d_name) == 0)
  499. {
  500. if(remove(number) == 0)
  501. {
  502. rValue = 1;
  503. break;
  504. }
  505. assert(chdir("../") == 0);
  506. }
  507. }
  508. receiverIterator = readdir(receiverDir);
  509. }
  510. if(closedir(receiverDir) == -1)
  511. {
  512. perror("cannot close dir");
  513. }
  514. return rValue;
  515. }
  516. int packageDelete(int client, int clientSocket, Stream* in)
  517. {
  518. char* user = serverGetUser(&server, client);
  519. if(user == NULL)
  520. {
  521. packageSendFailAnswer(clientSocket);
  522. return 0;
  523. }
  524. // number
  525. String number;
  526. stringInit(&number);
  527. stringReadStreamLine(&number, in);
  528. if(stringGetLength(&number) == 0)
  529. {
  530. packageSendFailAnswer(clientSocket);
  531. stringRemove(&number);
  532. return 0;
  533. }
  534. Stream out;
  535. streamInit(&out, 16);
  536. char workingPath[256];
  537. if(getcwd(workingPath, 256) != NULL)
  538. {
  539. if(deleteMail(user, number.data))
  540. {
  541. streamWriteChars(&out, "OK\n");
  542. }
  543. else
  544. {
  545. streamWriteChars(&out, "ERR\n");
  546. }
  547. assert(chdir(workingPath) == 0);
  548. }
  549. else
  550. {
  551. streamWriteChars(&out, "ERR\n");
  552. }
  553. stringRemove(&number);
  554. serverSend(clientSocket, &out);
  555. streamRemove(&out);
  556. return 0;
  557. }
  558. int packageLogin(int client, int clientSocket, Stream* in)
  559. {
  560. int length;
  561. // receiver
  562. String user;
  563. stringInit(&user);
  564. stringReadStreamLine(&user, in);
  565. length = stringGetLength(&user);
  566. if(length == 0 || length > 8)
  567. {
  568. packageSendFailAnswer(clientSocket);
  569. stringRemove(&user);
  570. return 0;
  571. }
  572. // password
  573. String password;
  574. stringInit(&password);
  575. stringReadStreamLine(&password, in);
  576. printf("%s %s\n", user.data, password.data);
  577. // insert LDAP check here
  578. stringRemove(&password);
  579. if(serverSetUser(&server, client, user.data))
  580. {
  581. packageSendFailAnswer(clientSocket);
  582. stringRemove(&user);
  583. return 0;
  584. }
  585. packageSendOkAnswer(clientSocket);
  586. stringRemove(&user);
  587. return 0;
  588. }
  589. int package(int client, int clientSocket, Stream* in)
  590. {
  591. if(streamHasData(in))
  592. {
  593. String s;
  594. stringInit(&s);
  595. stringReadStreamLine(&s, in);
  596. int r = 0;
  597. if(stringCompare(&s, "SEND"))
  598. {
  599. r = packageSend(client, clientSocket, in);
  600. }
  601. else if(stringCompare(&s, "LIST"))
  602. {
  603. r = packageList(client, clientSocket, in);
  604. }
  605. else if(stringCompare(&s, "READ"))
  606. {
  607. r = packageRead(client, clientSocket, in);
  608. }
  609. else if(stringCompare(&s, "DEL"))
  610. {
  611. r = packageDelete(client, clientSocket, in);
  612. }
  613. else if(stringCompare(&s, "LOGIN"))
  614. {
  615. r = packageLogin(client, clientSocket, in);
  616. }
  617. else
  618. {
  619. printf("Invalid package from %d\n", client);
  620. r = 1;
  621. }
  622. stringRemove(&s);
  623. return r;
  624. }
  625. return 0;
  626. }
  627. int main(int argc, char** argv)
  628. {
  629. if(argc < 3)
  630. {
  631. printf("Usage: %s directory port\n", argv[0]);
  632. return EXIT_FAILURE;
  633. }
  634. int port = atoi(argv[2]);
  635. if(port <= 0 || port >= 65536)
  636. {
  637. printf("invalid port");
  638. return EXIT_FAILURE;
  639. }
  640. serverInitDefaults(&server);
  641. signal(SIGINT, interruptHandler);
  642. signal(SIGKILL, interruptHandler);
  643. if(serverInit(&server, 3, port, argv[1]) == -1)
  644. {
  645. return EXIT_FAILURE;
  646. }
  647. serverRegisterHandler(&server, package);
  648. serverWaitForConnection(&server);
  649. serverRemove(&server);
  650. return EXIT_SUCCESS;
  651. }