PageRenderTime 69ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/src/elog.c

https://bitbucket.org/jeonghanlee/elog-with-tinymce-or-updated-ckeditor
C | 1256 lines | 915 code | 205 blank | 136 comment | 369 complexity | 6063f22d5caf2f787c89bfc008ab4306 MD5 | raw file
Possible License(s): GPL-2.0
  1. /********************************************************************\
  2. Name: elog.c
  3. Created by: Stefan Ritt
  4. Contents: Electronic logbook utility
  5. $Id$
  6. \********************************************************************/
  7. #include "elog-version.h"
  8. char svn_revision[] = "$Id$";
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <fcntl.h>
  12. #include <stdarg.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <time.h>
  16. #include <ctype.h>
  17. #ifdef _MSC_VER
  18. #include <windows.h>
  19. #include <io.h>
  20. #else
  21. #include <netdb.h>
  22. #include <netinet/in.h>
  23. #include <sys/socket.h>
  24. #include <sys/time.h>
  25. #include <unistd.h>
  26. #include <signal.h>
  27. #define closesocket(s) close(s)
  28. #ifndef O_BINARY
  29. #define O_BINARY 0
  30. #endif
  31. #endif
  32. /* SSL includes */
  33. #ifdef HAVE_SSL
  34. #include <openssl/ssl.h>
  35. #endif
  36. typedef int INT;
  37. #define MAX_ATTACHMENTS 50
  38. #define NAME_LENGTH 500
  39. #define MAX_N_ATTR 50
  40. #define TEXT_SIZE 100000
  41. int verbose;
  42. char text[TEXT_SIZE], old_text[TEXT_SIZE], new_text[TEXT_SIZE];
  43. /*------------------------------------------------------------------*/
  44. char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  45. void base64_encode(unsigned char *s, unsigned char *d, int size)
  46. {
  47. unsigned int t, pad;
  48. unsigned char *p;
  49. pad = 3 - strlen((char *) s) % 3;
  50. if (pad == 3)
  51. pad = 0;
  52. p = d;
  53. while (*s) {
  54. t = (*s++) << 16;
  55. if (*s)
  56. t |= (*s++) << 8;
  57. if (*s)
  58. t |= (*s++) << 0;
  59. *(d + 3) = map[t & 63];
  60. t >>= 6;
  61. *(d + 2) = map[t & 63];
  62. t >>= 6;
  63. *(d + 1) = map[t & 63];
  64. t >>= 6;
  65. *(d + 0) = map[t & 63];
  66. d += 4;
  67. if (d - p >= size - 3)
  68. return;
  69. }
  70. *d = 0;
  71. while (pad--)
  72. *(--d) = '=';
  73. }
  74. /*---- string comparison -------------------------------------------*/
  75. int equal_ustring(char *str1, char *str2)
  76. {
  77. if (str1 == NULL && str2 != NULL)
  78. return 0;
  79. if (str1 != NULL && str2 == NULL)
  80. return 0;
  81. if (str1 == NULL && str2 == NULL)
  82. return 1;
  83. while (*str1)
  84. if (toupper(*str1++) != toupper(*str2++))
  85. return 0;
  86. if (*str2)
  87. return 0;
  88. return 1;
  89. }
  90. /*---- strlcpy and strlcat to avoid buffer overflow ----------------*/
  91. #ifndef STRLCPY_DEFINED
  92. /*
  93. * Copy src to string dst of size siz. At most siz-1 characters
  94. * will be copied. Always NUL terminates (unless size == 0).
  95. * Returns strlen(src); if retval >= siz, truncation occurred.
  96. */
  97. size_t strlcpy(char *dst, const char *src, size_t size)
  98. {
  99. char *d = dst;
  100. const char *s = src;
  101. size_t n = size;
  102. /* Copy as many bytes as will fit */
  103. if (n != 0 && --n != 0) {
  104. do {
  105. if ((*d++ = *s++) == 0)
  106. break;
  107. } while (--n != 0);
  108. }
  109. /* Not enough room in dst, add NUL and traverse rest of src */
  110. if (n == 0) {
  111. if (size != 0)
  112. *d = '\0'; /* NUL-terminate dst */
  113. while (*s++);
  114. }
  115. return (s - src - 1); /* count does not include NUL */
  116. }
  117. /*
  118. * Appends src to string dst of size siz (unlike strncat, siz is the
  119. * full size of dst, not space left). At most siz-1 characters
  120. * will be copied. Always NUL terminates (unless size <= strlen(dst)).
  121. * Returns strlen(src) + MIN(size, strlen(initial dst)).
  122. * If retval >= size, truncation occurred.
  123. */
  124. size_t strlcat(char *dst, const char *src, size_t size)
  125. {
  126. char *d = dst;
  127. const char *s = src;
  128. size_t n = size;
  129. size_t dlen;
  130. /* Find the end of dst and adjust bytes left but don't go past end */
  131. while (n-- != 0 && *d != '\0')
  132. d++;
  133. dlen = d - dst;
  134. n = size - dlen;
  135. if (n == 0)
  136. return (dlen + strlen(s));
  137. while (*s != '\0') {
  138. if (n != 1) {
  139. *d++ = *s;
  140. n--;
  141. }
  142. s++;
  143. }
  144. *d = '\0';
  145. return (dlen + (s - src)); /* count does not include NUL */
  146. }
  147. #endif // STRLCPY_DEFINED
  148. char *sha256_crypt(const char *key, const char *salt);
  149. void do_crypt(char *s, char *d, int size)
  150. {
  151. strlcpy(d, sha256_crypt(s, "$5$") + 4, size);
  152. }
  153. /*-------------------------------------------------------------------*/
  154. void stou(char *str)
  155. /* convert all special characters to underscores in a string */
  156. {
  157. int i;
  158. for (i = 0; i < (int) strlen(str); i++)
  159. if (str[i] == ' ' || str[i] == '.' || str[i] == '/' ||
  160. str[i] == '\\' || str[i] == '-' || str[i] == '(' || str[i] == ')')
  161. str[i] = '_';
  162. }
  163. /*------------------------------------------------------------------*/
  164. void url_encode(char *ps, int size)
  165. /********************************************************************\
  166. Encode the given string in-place by adding %XX escapes
  167. \********************************************************************/
  168. {
  169. unsigned char *pd, *p;
  170. unsigned char str[NAME_LENGTH];
  171. pd = (unsigned char *) str;
  172. p = (unsigned char *) ps;
  173. while (*p && pd < str + 250) {
  174. if (strchr("%&=#?+", *p) || *p > 127) {
  175. sprintf((char *) pd, "%%%02X", *p);
  176. pd += 3;
  177. p++;
  178. } else if (*p == ' ') {
  179. *pd++ = '+';
  180. p++;
  181. } else {
  182. *pd++ = *p++;
  183. }
  184. }
  185. *pd = '\0';
  186. strlcpy(ps, (char *) str, size);
  187. }
  188. /*------------------------------------------------------------------*/
  189. void sgets(char *string, int size)
  190. {
  191. char *p;
  192. do {
  193. p = fgets(string, size, stdin);
  194. } while (p == NULL);
  195. if (strlen(p) > 0 && p[strlen(p) - 1] == '\n')
  196. p[strlen(p) - 1] = 0;
  197. }
  198. /*------------------------------------------------------------------*/
  199. void add_crlf(char *buffer, int bufsize)
  200. {
  201. char *p;
  202. char *tmpbuf;
  203. tmpbuf = malloc(bufsize);
  204. /* convert \n -> \r\n */
  205. p = buffer;
  206. while ((p = strstr(p, "\n")) != NULL) {
  207. if (p > buffer && *(p - 1) == '\r') {
  208. p++;
  209. continue;
  210. }
  211. if ((int) strlen(buffer) + 2 >= bufsize) {
  212. free(tmpbuf);
  213. return;
  214. }
  215. strlcpy(tmpbuf, p, bufsize);
  216. *(p++) = '\r';
  217. strlcpy(p, tmpbuf, bufsize - (p - buffer));
  218. p++;
  219. }
  220. free(tmpbuf);
  221. }
  222. /*------------------------------------------------------------------*/
  223. void convert_crlf(char *buffer, int bufsize)
  224. {
  225. char *p;
  226. /* convert '\n' -> \r\n */
  227. p = buffer;
  228. while ((p = strstr(p, "\\n")) != NULL) {
  229. if (p - buffer < bufsize - 2) {
  230. *(p++) = '\r';
  231. *(p++) = '\n';
  232. }
  233. }
  234. }
  235. /*------------------------------------------------------------------*/
  236. int elog_connect(char *host, int port)
  237. {
  238. int status, sock;
  239. struct hostent *phe;
  240. struct sockaddr_in bind_addr;
  241. /* create socket */
  242. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  243. perror("cannot create socket");
  244. return -1;
  245. }
  246. /* compose remote address */
  247. memset(&bind_addr, 0, sizeof(bind_addr));
  248. bind_addr.sin_family = AF_INET;
  249. bind_addr.sin_addr.s_addr = 0;
  250. bind_addr.sin_port = htons((unsigned short) port);
  251. phe = gethostbyname(host);
  252. if (phe == NULL) {
  253. perror("cannot get host name");
  254. return -1;
  255. }
  256. memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
  257. /* connect to server */
  258. status = connect(sock, (void *) &bind_addr, sizeof(bind_addr));
  259. if (status != 0) {
  260. printf("Cannot connect to host %s, port %d\n", host, port);
  261. return -1;
  262. }
  263. if (verbose)
  264. printf("Successfully connected to host %s, port %d\n", host, port);
  265. return sock;
  266. }
  267. /*------------------------------------------------------------------*/
  268. #ifdef HAVE_SSL
  269. int ssl_connect(int sock, SSL ** ssl_con)
  270. {
  271. SSL_METHOD *meth;
  272. SSL_CTX *ctx;
  273. SSL_library_init();
  274. SSL_load_error_strings();
  275. meth = (SSL_METHOD *) SSLv23_method();
  276. ctx = SSL_CTX_new(meth);
  277. *ssl_con = SSL_new(ctx);
  278. SSL_set_fd(*ssl_con, sock);
  279. if (SSL_connect(*ssl_con) <= 0)
  280. return -1;
  281. return 0;
  282. }
  283. #endif
  284. /*------------------------------------------------------------------*/
  285. char request[100000], response[100000], *content;
  286. INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
  287. char *uname, char *upwd, int message_id,
  288. char attrib_name[MAX_N_ATTR][NAME_LENGTH], char attrib[MAX_N_ATTR][NAME_LENGTH], char *text)
  289. /********************************************************************\
  290. Routine: retrive_elog
  291. Purpose: Retrive an ELog entry for edit/reply
  292. Input:
  293. char *host Host name where ELog server runs
  294. int port ELog server port number
  295. char *subdir Subdirectoy to elog server
  296. int ssl Flag for using SSL layer
  297. char *uname User name
  298. char *upwd User password
  299. int message_id Message to retrieve
  300. char *attrib_name Attribute names
  301. char *attrib Attribute values
  302. char *text Message text
  303. Function value:
  304. EL_SUCCESS Successful completion
  305. \********************************************************************/
  306. {
  307. int i, n, first, index, sock;
  308. char str[256], encrypted_passwd[256], *ph, *ps;
  309. #ifdef HAVE_SSL
  310. SSL *ssl_con;
  311. ssl_con = NULL;
  312. #endif
  313. if (ssl) /* avoid compiler warning */
  314. sock = 0;
  315. sock = elog_connect(host, port);
  316. if (sock < 0)
  317. return sock;
  318. #ifdef HAVE_SSL
  319. if (ssl)
  320. if (ssl_connect(sock, &ssl_con) < 0) {
  321. printf("elogd server does not run SSL protocol\n");
  322. return -1;
  323. }
  324. #endif
  325. /* compose request */
  326. strcpy(request, "GET /");
  327. strlcpy(str, experiment, sizeof(str));
  328. url_encode(str, sizeof(str));
  329. if (subdir[0] && experiment[0])
  330. sprintf(request + strlen(request), "%s/%s/%d?cmd=download", subdir, str, message_id);
  331. else if (subdir[0])
  332. sprintf(request + strlen(request), "%s/%d?cmd=download", subdir, message_id);
  333. else if (experiment[0])
  334. sprintf(request + strlen(request), "%s/%d?cmd=download", str, message_id);
  335. strcat(request, " HTTP/1.0\r\n");
  336. sprintf(request + strlen(request), "User-Agent: ELOG\r\n");
  337. first = 1;
  338. if (uname[0]) {
  339. if (first)
  340. sprintf(request + strlen(request), "Cookie: ");
  341. first = 0;
  342. sprintf(request + strlen(request), "unm=%s;", uname);
  343. }
  344. if (upwd[0]) {
  345. if (first)
  346. sprintf(request + strlen(request), "Cookie: ");
  347. first = 0;
  348. do_crypt(upwd, encrypted_passwd, sizeof(encrypted_passwd));
  349. sprintf(request + strlen(request), "upwd=%s;", encrypted_passwd);
  350. }
  351. /* finish cookie line */
  352. if (!first)
  353. strcat(request, "\r\n");
  354. strcat(request, "\r\n");
  355. /* send request */
  356. #ifdef HAVE_SSL
  357. if (ssl)
  358. SSL_write(ssl_con, request, strlen(request));
  359. else
  360. #endif
  361. send(sock, request, strlen(request), 0);
  362. if (verbose) {
  363. printf("Request sent to host:\n");
  364. puts(request);
  365. }
  366. /* receive response */
  367. memset(response, 0, sizeof(response));
  368. #ifdef HAVE_SSL
  369. if (ssl)
  370. i = SSL_read(ssl_con, response, sizeof(response) - 1);
  371. else
  372. #endif
  373. i = recv(sock, response, sizeof(response) - 1, 0);
  374. if (i < 0) {
  375. perror("Cannot receive response");
  376. return -1;
  377. }
  378. n = i;
  379. while (i > 0) {
  380. #ifdef HAVE_SSL
  381. if (ssl)
  382. i = SSL_read(ssl_con, response + n, sizeof(response) - 1 - n);
  383. else
  384. #endif
  385. i = recv(sock, response + n, sizeof(response) - 1 - n, 0);
  386. if (i > 0)
  387. n += i;
  388. }
  389. response[n] = 0;
  390. #ifdef HAVE_SSL
  391. if (ssl) {
  392. SSL_shutdown(ssl_con);
  393. SSL_free(ssl_con);
  394. }
  395. #endif
  396. closesocket(sock);
  397. if (verbose) {
  398. printf("Response received:\n");
  399. puts(response);
  400. }
  401. /* check response status */
  402. if (strstr(response, "$@MID@$:")) {
  403. /* separate attributes and message */
  404. ph = strstr(response, "========================================\n");
  405. /* skip first line */
  406. ps = strstr(response, "$@MID@$:");
  407. while (*ps && *ps != '\n')
  408. ps++;
  409. while (*ps && (*ps == '\n' || *ps == '\r'))
  410. ps++;
  411. for (index = 0; index < MAX_N_ATTR; index++) {
  412. if (ps >= ph)
  413. break;
  414. strlcpy(attrib_name[index], ps, NAME_LENGTH);
  415. if (strchr(attrib_name[index], ':'))
  416. *(strchr(attrib_name[index], ':')) = 0;
  417. ps += strlen(attrib_name[index]) + 2;
  418. strlcpy(attrib[index], ps, NAME_LENGTH);
  419. for (i = 0; i < NAME_LENGTH; i++) {
  420. if (attrib[index][i] == '\r' || attrib[index][i] == '\n')
  421. attrib[index][i] = 0;
  422. if (attrib[index][i] == 0)
  423. break;
  424. }
  425. ps += strlen(attrib[index]);
  426. while (*ps && (*ps == '\n' || *ps == '\r'))
  427. ps++;
  428. }
  429. attrib_name[index][0] = 0;
  430. attrib[index][0] = 0;
  431. ph = strchr(ph, '\n') + 1;
  432. if (*ph == '\r')
  433. ph++;
  434. strlcpy(text, ph, TEXT_SIZE);
  435. return 1;
  436. }
  437. if (strstr(response, "302 Found")) {
  438. if (strstr(response, "Location:")) {
  439. if (strstr(response, "fail"))
  440. printf("Error: Invalid user name or password\n");
  441. else {
  442. strncpy(str, strstr(response, "Location:") + 10, sizeof(str));
  443. if (strchr(str, '?'))
  444. *strchr(str, '?') = 0;
  445. if (strchr(str, '\n'))
  446. *strchr(str, '\n') = 0;
  447. if (strchr(str, '\r'))
  448. *strchr(str, '\r') = 0;
  449. if (strrchr(str, '/'))
  450. printf("Message successfully transmitted, ID=%s\n", strrchr(str, '/') + 1);
  451. else
  452. printf("Message successfully transmitted, ID=%s\n", str);
  453. }
  454. }
  455. } else if (strstr(response, "Logbook Selection"))
  456. printf("Error: No logbook specified\n");
  457. else if (strstr(response, "enter password"))
  458. printf("Error: Missing or invalid password\n");
  459. else if (strstr(response, "form name=form1"))
  460. printf("Error: Missing or invalid user name/password\n");
  461. else
  462. printf("Error transmitting message\n");
  463. return 0;
  464. }
  465. /*------------------------------------------------------------------*/
  466. INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
  467. char *uname, char *upwd,
  468. int reply,
  469. int quote_on_reply,
  470. int edit,
  471. int download,
  472. int suppress,
  473. int encoding,
  474. char attrib_name[MAX_N_ATTR][NAME_LENGTH],
  475. char attrib[MAX_N_ATTR][NAME_LENGTH],
  476. int n_attr,
  477. char *text, char afilename[MAX_ATTACHMENTS][256],
  478. char *buffer[MAX_ATTACHMENTS], INT buffer_size[MAX_ATTACHMENTS])
  479. /********************************************************************\
  480. Routine: submit_elog
  481. Purpose: Submit an ELog entry
  482. Input:
  483. char *host Host name where ELog server runs
  484. in port ELog server port number
  485. int ssl SSL flag
  486. char *subdir Subdirectoy to elog server
  487. char *uname User name
  488. char *upwd User password
  489. int reply Reply to existing message
  490. int edit Edit existing message
  491. int download Download existing message
  492. int suppress Suppress Email notification
  493. int encoding 0:ELCode,1:plain,2:HTML,3:TinyMCE
  494. char *attrib_name Attribute names
  495. char *attrib Attribute values
  496. char *text Message text
  497. char afilename[] File names of attachments
  498. char *buffer[] Attachment contents
  499. INT buffer_size[] Size of buffer in bytes
  500. Function value:
  501. EL_SUCCESS Successful completion
  502. \********************************************************************/
  503. {
  504. int status, sock, i, n, header_length, content_length, index;
  505. char host_name[256], boundary[80], str[80], encrypted_passwd[256], *p, *old_encoding;
  506. char old_attrib_name[MAX_N_ATTR][NAME_LENGTH], old_attrib[MAX_N_ATTR][NAME_LENGTH];
  507. struct hostent *phe;
  508. #ifdef HAVE_SSL
  509. SSL *ssl_con;
  510. ssl_con = NULL;
  511. #endif
  512. /* get local host name */
  513. gethostname(host_name, sizeof(host_name));
  514. phe = gethostbyname(host_name);
  515. if (phe == NULL) {
  516. perror("Cannot retrieve host name");
  517. return -1;
  518. }
  519. phe = gethostbyaddr(phe->h_addr, sizeof(int), AF_INET);
  520. if (phe == NULL) {
  521. perror("Cannot retrieve host name");
  522. return -1;
  523. }
  524. /* if domain name is not in host name, hope to get it from phe */
  525. if (strchr(host_name, '.') == NULL)
  526. strcpy(host_name, phe->h_name);
  527. if (edit || download) {
  528. if (edit)
  529. status = retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, edit,
  530. old_attrib_name, old_attrib, old_text);
  531. else
  532. status = retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, download,
  533. old_attrib_name, old_attrib, old_text);
  534. if (status != 1)
  535. return status;
  536. /* update attributes */
  537. for (index = 0; index < n_attr; index++) {
  538. for (i = 0; i < MAX_N_ATTR && old_attrib_name[i][0]; i++)
  539. if (equal_ustring(attrib_name[index], old_attrib_name[i]))
  540. break;
  541. if (old_attrib_name[i][0])
  542. strlcpy(old_attrib[i], attrib[index], NAME_LENGTH);
  543. }
  544. /* copy attributes */
  545. for (i = 0; i < MAX_N_ATTR && old_attrib_name[i][0]; i++) {
  546. strlcpy(attrib_name[i], old_attrib_name[i], NAME_LENGTH);
  547. strlcpy(attrib[i], old_attrib[i], NAME_LENGTH);
  548. }
  549. n_attr = i;
  550. if (text[0] == 0)
  551. strlcpy(text, old_text, TEXT_SIZE);
  552. }
  553. if (download) {
  554. if (strstr(response, "$@MID@$:"))
  555. printf("%s", strstr(response, "$@MID@$:"));
  556. else
  557. printf("%s", response);
  558. return 1;
  559. }
  560. if (reply) {
  561. status =
  562. retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, reply,
  563. old_attrib_name, old_attrib, old_text);
  564. if (status != 1)
  565. return status;
  566. /* update attributes */
  567. for (index = 0; index < n_attr; index++) {
  568. for (i = 0; i < MAX_N_ATTR && old_attrib_name[i][0]; i++)
  569. if (equal_ustring(attrib_name[index], old_attrib_name[i]))
  570. break;
  571. if (old_attrib_name[i][0])
  572. strlcpy(old_attrib[i], attrib[index], NAME_LENGTH);
  573. }
  574. /* copy attributes */
  575. for (i = 0; i < MAX_N_ATTR && old_attrib_name[i][0]; i++) {
  576. if (equal_ustring(old_attrib_name[i], "Reply to") || equal_ustring(old_attrib_name[i], "Date")) {
  577. attrib_name[i][0] = 0;
  578. attrib[i][0] = 0;
  579. } else {
  580. strlcpy(attrib_name[i], old_attrib_name[i], NAME_LENGTH);
  581. strlcpy(attrib[i], old_attrib[i], NAME_LENGTH);
  582. }
  583. }
  584. n_attr = i;
  585. /* check encoding */
  586. old_encoding = "plain";
  587. for (i = 0; i < n_attr; i++)
  588. if (equal_ustring(attrib_name[i], "encoding"))
  589. break;
  590. if (i < n_attr)
  591. old_encoding = attrib[i];
  592. if (quote_on_reply) {
  593. strlcpy(new_text, text, sizeof(new_text));
  594. /* precede old text with "> " */
  595. text[0] = 0;
  596. p = old_text;
  597. do {
  598. if (strchr(p, '\n')) {
  599. *strchr(p, '\n') = 0;
  600. if (old_encoding[0] == 'H') {
  601. strlcat(text, "> ", TEXT_SIZE);
  602. strlcat(text, p, TEXT_SIZE);
  603. strlcat(text, "<br>\n", TEXT_SIZE);
  604. } else {
  605. strlcat(text, "> ", TEXT_SIZE);
  606. strlcat(text, p, TEXT_SIZE);
  607. strlcat(text, "\n", TEXT_SIZE);
  608. }
  609. p += strlen(p) + 1;
  610. if (*p == '\n')
  611. p++;
  612. } else {
  613. if (old_encoding[0] == 'H') {
  614. strlcat(text, "> ", TEXT_SIZE);
  615. strlcat(text, p, TEXT_SIZE);
  616. strlcat(text, "<p>\n", TEXT_SIZE);
  617. } else {
  618. strlcat(text, "> ", TEXT_SIZE);
  619. strlcat(text, p, TEXT_SIZE);
  620. strlcat(text, "\n\n", TEXT_SIZE);
  621. }
  622. break;
  623. }
  624. } while (1);
  625. strlcat(text, new_text, TEXT_SIZE);
  626. }
  627. }
  628. sock = elog_connect(host, port);
  629. if (sock < 0)
  630. return sock;
  631. #ifdef HAVE_SSL
  632. if (ssl)
  633. if (ssl_connect(sock, &ssl_con) < 0) {
  634. printf("elogd server does not run SSL protocol\n");
  635. return -1;
  636. }
  637. #endif
  638. content_length = 100000;
  639. for (i = 0; i < MAX_ATTACHMENTS; i++)
  640. if (afilename[i][0])
  641. content_length += buffer_size[i];
  642. content = malloc(content_length);
  643. if (content == NULL) {
  644. printf("Not enough memory\n");
  645. return -1;
  646. }
  647. /* compose content */
  648. srand((unsigned) time(NULL));
  649. sprintf(boundary, "---------------------------%04X%04X%04X", rand(), rand(), rand());
  650. strcpy(content, boundary);
  651. strcat(content, "\r\nContent-Disposition: form-data; name=\"cmd\"\r\n\r\nSubmit\r\n");
  652. if (uname[0])
  653. sprintf(content + strlen(content),
  654. "%s\r\nContent-Disposition: form-data; name=\"unm\"\r\n\r\n%s\r\n", boundary, uname);
  655. if (upwd[0]) {
  656. do_crypt(upwd, encrypted_passwd, sizeof(encrypted_passwd));
  657. sprintf(content + strlen(content),
  658. "%s\r\nContent-Disposition: form-data; name=\"upwd\"\r\n\r\n%s\r\n", boundary,
  659. encrypted_passwd);
  660. }
  661. if (experiment[0])
  662. sprintf(content + strlen(content),
  663. "%s\r\nContent-Disposition: form-data; name=\"exp\"\r\n\r\n%s\r\n", boundary, experiment);
  664. if (reply)
  665. sprintf(content + strlen(content),
  666. "%s\r\nContent-Disposition: form-data; name=\"reply_to\"\r\n\r\n%d\r\n", boundary, reply);
  667. if (edit) {
  668. sprintf(content + strlen(content),
  669. "%s\r\nContent-Disposition: form-data; name=\"edit_id\"\r\n\r\n%d\r\n", boundary, edit);
  670. sprintf(content + strlen(content),
  671. "%s\r\nContent-Disposition: form-data; name=\"skiplock\"\r\n\r\n1\r\n", boundary);
  672. }
  673. if (suppress)
  674. sprintf(content + strlen(content),
  675. "%s\r\nContent-Disposition: form-data; name=\"suppress\"\r\n\r\n1\r\n", boundary);
  676. if (encoding == 0)
  677. sprintf(content + strlen(content),
  678. "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nELCode\r\n", boundary);
  679. else if (encoding == 1)
  680. sprintf(content + strlen(content),
  681. "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nplain\r\n", boundary);
  682. else if (encoding == 2)
  683. sprintf(content + strlen(content),
  684. "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nHTML\r\n", boundary);
  685. else if (encoding == 3)
  686. sprintf(content + strlen(content),
  687. "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nTinyMCE\r\n", boundary);
  688. for (i = 0; i < n_attr; i++) {
  689. strcpy(str, attrib_name[i]);
  690. if (str[0]) {
  691. stou(str);
  692. sprintf(content + strlen(content),
  693. "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", boundary, str, attrib[i]);
  694. }
  695. }
  696. sprintf(content + strlen(content),
  697. "%s\r\nContent-Disposition: form-data; name=\"Text\"\r\n\r\n%s\r\n%s\r\n",
  698. boundary, text, boundary);
  699. content_length = strlen(content);
  700. p = content + content_length;
  701. for (i = 0; i < MAX_ATTACHMENTS; i++)
  702. if (afilename[i][0]) {
  703. sprintf(p,
  704. "Content-Disposition: form-data; name=\"attfile%d\"; filename=\"%s\"\r\n\r\n",
  705. i + 1, afilename[i]);
  706. content_length += strlen(p);
  707. p += strlen(p);
  708. memcpy(p, buffer[i], buffer_size[i]);
  709. p += buffer_size[i];
  710. strcpy(p, boundary);
  711. strcat(p, "\r\n");
  712. content_length += buffer_size[i] + strlen(p);
  713. p += strlen(p);
  714. }
  715. /* compose request */
  716. strcpy(request, "POST /");
  717. if (subdir[0])
  718. sprintf(request + strlen(request), "%s/", subdir);
  719. if (experiment[0]) {
  720. strcpy(str, experiment);
  721. url_encode(str, sizeof(str));
  722. sprintf(request + strlen(request), "%s/", str);
  723. }
  724. strcat(request, " HTTP/1.0\r\n");
  725. sprintf(request + strlen(request), "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
  726. if (port != 80)
  727. sprintf(str, "%s:%d", host, port);
  728. else
  729. sprintf(str, "%s", host);
  730. sprintf(request + strlen(request), "Host: %s\r\n", str);
  731. sprintf(request + strlen(request), "User-Agent: ELOG\r\n");
  732. sprintf(request + strlen(request), "Content-Length: %d\r\n", content_length);
  733. strcat(request, "\r\n");
  734. header_length = strlen(request);
  735. /*
  736. {
  737. FILE *f;
  738. f = fopen("elog.log", "w");
  739. fwrite(request, header_length+content_length, 1, f);
  740. fclose(f);
  741. }
  742. */
  743. /* send request */
  744. #ifdef HAVE_SSL
  745. if (ssl)
  746. SSL_write(ssl_con, request, header_length);
  747. else
  748. #endif
  749. send(sock, request, header_length, 0);
  750. if (verbose) {
  751. printf("Request sent to host:\n");
  752. puts(request);
  753. }
  754. /* send content */
  755. #ifdef HAVE_SSL
  756. if (ssl)
  757. SSL_write(ssl_con, content, content_length);
  758. else
  759. #endif
  760. send(sock, content, content_length, 0);
  761. if (verbose) {
  762. printf("Content sent to host:\n");
  763. puts(content);
  764. }
  765. /* receive response */
  766. memset(response, 0, sizeof(response));
  767. #ifdef HAVE_SSL
  768. if (ssl)
  769. i = SSL_read(ssl_con, response, sizeof(response) - 1);
  770. else
  771. #endif
  772. i = recv(sock, response, sizeof(response) - 1, 0);
  773. if (i < 0) {
  774. perror("Cannot receive response");
  775. return -1;
  776. }
  777. /* discard remainder of response */
  778. n = i;
  779. while (i > 0) {
  780. #ifdef HAVE_SSL
  781. if (ssl)
  782. i = SSL_read(ssl_con, response + n, sizeof(response) - 1 - n);
  783. else
  784. #endif
  785. i = recv(sock, response + n, sizeof(response) - 1 - n, 0);
  786. if (i > 0)
  787. n += i;
  788. }
  789. response[n] = 0;
  790. #ifdef HAVE_SSL
  791. if (ssl) {
  792. SSL_shutdown(ssl_con);
  793. SSL_free(ssl_con);
  794. }
  795. #endif
  796. closesocket(sock);
  797. if (verbose) {
  798. printf("Response received:\n");
  799. puts(response);
  800. }
  801. /* check response status */
  802. if (strstr(response, "302 Found")) {
  803. if (strstr(response, "Location:")) {
  804. if (strstr(response, "has moved"))
  805. printf("Error: elogd server has moved to another location\n");
  806. else if (strstr(response, "fail"))
  807. printf("Error: Invalid user name or password\n");
  808. else {
  809. strncpy(str, strstr(response, "Location:") + 10, sizeof(str));
  810. if (strchr(str, '?'))
  811. *strchr(str, '?') = 0;
  812. if (strchr(str, '\n'))
  813. *strchr(str, '\n') = 0;
  814. if (strchr(str, '\r'))
  815. *strchr(str, '\r') = 0;
  816. if (strrchr(str, '/'))
  817. printf("Message successfully transmitted, ID=%s\n", strrchr(str, '/') + 1);
  818. else
  819. printf("Message successfully transmitted, ID=%s\n", str);
  820. }
  821. } else
  822. printf("Message successfully transmitted\n");
  823. } else if (strstr(response, "Logbook Selection"))
  824. printf("Error: No logbook specified\n");
  825. else if (strstr(response, "enter password"))
  826. printf("Error: Missing or invalid password\n");
  827. else if (strstr(response, "form name=form1"))
  828. printf("Error: Missing or invalid user name/password\n");
  829. else if (strstr(response, "Error: Attribute")) {
  830. if (strstr(response, "not existing")) {
  831. strncpy(str, strstr(response, "Error: Attribute") + 27, sizeof(str));
  832. if (strchr(str, '<'))
  833. *strchr(str, '<') = 0;
  834. printf("Error: Non existing attribute option \"%s\"\n", str);
  835. } else {
  836. strncpy(str, strstr(response, "Error: Attribute") + 20, sizeof(str));
  837. if (strchr(str, '<'))
  838. *strchr(str, '<') = 0;
  839. printf("Error: Missing required attribute \"%s\"\n", str);
  840. }
  841. } else
  842. printf("Error transmitting message\n");
  843. return 1;
  844. }
  845. /*------------------------------------------------------------------*/
  846. int main(int argc, char *argv[])
  847. {
  848. char str[1000], uname[80], upwd[80];
  849. char host_name[256], logbook[32], textfile[256], subdir[256];
  850. char *buffer[MAX_ATTACHMENTS], attachment[MAX_ATTACHMENTS][256];
  851. INT att_size[MAX_ATTACHMENTS];
  852. INT i, n, fh, n_att, n_attr, port, reply, quote_on_reply, edit, download, encoding, suppress, size, ssl;
  853. char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH];
  854. text[0] = textfile[0] = uname[0] = upwd[0] = suppress = quote_on_reply = 0;
  855. host_name[0] = logbook[0] = subdir[0] = 0;
  856. n_att = n_attr = reply = edit = download = encoding = 0;
  857. port = 80;
  858. ssl = 0;
  859. for (i = 0; i < MAX_ATTACHMENTS; i++) {
  860. attachment[i][0] = 0;
  861. buffer[i] = NULL;
  862. att_size[i] = 0;
  863. }
  864. /* parse command line parameters */
  865. for (i = 1; i < argc; i++) {
  866. if (argv[i][0] == '-' && argv[i][1] == 'v')
  867. verbose = 1;
  868. else if (argv[i][0] == '-' && argv[i][1] == 's')
  869. ssl = 1;
  870. else if (argv[i][0] == '-' && argv[i][1] == 'q')
  871. quote_on_reply = 1;
  872. else if (argv[i][0] == '-' && argv[i][1] == 'x')
  873. suppress = 1;
  874. else {
  875. if (argv[i][0] == '-') {
  876. if (i + 1 >= argc || argv[i + 1][0] == '-')
  877. goto usage;
  878. if (argv[i][1] == 'h')
  879. strcpy(host_name, argv[++i]);
  880. else if (argv[i][1] == 'p')
  881. port = atoi(argv[++i]);
  882. else if (argv[i][1] == 'l')
  883. strcpy(logbook, argv[++i]);
  884. else if (argv[i][1] == 'd')
  885. strcpy(subdir, argv[++i]);
  886. else if (argv[i][1] == 'u') {
  887. strcpy(uname, argv[++i]);
  888. strcpy(upwd, argv[++i]);
  889. } else if (argv[i][1] == 'a') {
  890. strcpy(str, argv[++i]);
  891. if (strchr(str, '=')) {
  892. strcpy(attrib[n_attr], strchr(str, '=') + 1);
  893. *strchr(str, '=') = 0;
  894. strcpy(attr_name[n_attr], str);
  895. n_attr++;
  896. } else {
  897. printf("Error: Attributes must be supplied in the form \"-a <attribute>=<value>\".\n");
  898. return 1;
  899. }
  900. } else if (argv[i][1] == 'f')
  901. strcpy(attachment[n_att++], argv[++i]);
  902. else if (argv[i][1] == 'r')
  903. reply = atoi(argv[++i]);
  904. else if (argv[i][1] == 'e')
  905. edit = atoi(argv[++i]);
  906. else if (argv[i][1] == 'w') {
  907. if (argv[i+1][0] == 'l')
  908. download = -1;
  909. else
  910. download = atoi(argv[++i]);
  911. } else if (argv[i][1] == 'n')
  912. encoding = atoi(argv[++i]);
  913. else if (argv[i][1] == 'm')
  914. strcpy(textfile, argv[++i]);
  915. else {
  916. usage:
  917. printf("%s ", ELOGID);
  918. strcpy(str, svn_revision + 13);
  919. if (strchr(str, ' '))
  920. *strchr(str, ' ') = 0;
  921. printf("revision %s\n", str);
  922. printf("\nusage: elog\n");
  923. printf("elog -h <hostname> [-p port] [-d subdir]\n");
  924. printf(" Location where elogd is running\n");
  925. printf(" -l logbook/experiment Name of logbook or experiment\n");
  926. printf(" -s Use SSL for communication\n");
  927. printf(" [-v] For verbose output\n");
  928. printf(" [-u username password] Wser name and password\n");
  929. printf(" [-f <attachment>] (up to %d attachments)\n", MAX_ATTACHMENTS);
  930. printf(" -a <attribute>=<value> (up to %d attributes)\n", MAX_N_ATTR);
  931. printf(" [-r <id>] Reply to existing message\n");
  932. printf(" [-q] Quote original text on reply\n");
  933. printf(" [-e <id>] Edit existing message\n");
  934. printf(" [-w <id>|last] Download existing message (last message)\n");
  935. printf(" [-x] Suppress email notification\n");
  936. printf(" [-n 0|1|2] Encoding: 0:ELcode,1:plain,2:HTML,3:TinyMCE\n");
  937. printf(" -m <textfile>] | <text>\n");
  938. printf("\nArguments with blanks must be enclosed in quotes\n");
  939. printf("The elog message can either be submitted on the command line, piped in like\n");
  940. printf("\"cat text | elog -h ... -l ... -a ...\" or in a file with the -m flag.\n");
  941. printf("Multiple attributes and attachments can be supplied\n");
  942. return 1;
  943. }
  944. } else {
  945. strcpy(text, argv[i]);
  946. convert_crlf(text, sizeof(text));
  947. }
  948. }
  949. }
  950. #ifndef HAVE_SSL
  951. if (ssl) {
  952. printf("SLL support not compiled into this program\n");
  953. return 1;
  954. }
  955. #endif
  956. #if defined( _MSC_VER )
  957. {
  958. WSADATA WSAData;
  959. /* Start windows sockets */
  960. if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
  961. return -1;
  962. }
  963. #endif
  964. if (host_name[0] == 0) {
  965. printf("Please specify hostname.\n");
  966. return 1;
  967. }
  968. if (logbook[0] == 0) {
  969. printf("Please specify logbook with the \"-l\" flag.\n");
  970. return 1;
  971. }
  972. if (n_attr == 0 && !edit && !reply && !download) {
  973. printf("Please specify attribute(s) with the \"-a\" flag.\n");
  974. return 1;
  975. }
  976. fh = -1;
  977. if (textfile[0]) {
  978. fh = open(textfile, O_RDONLY | O_BINARY);
  979. if (fh < 0) {
  980. printf("Message file \"%s\" does not exist.\n", textfile);
  981. return 1;
  982. }
  983. size = (INT) lseek(fh, 0, SEEK_END);
  984. lseek(fh, 0, SEEK_SET);
  985. if (size > (INT) (sizeof(text) - 1)) {
  986. printf("Message file \"%s\" is too long (%zd bytes max).\n", textfile, sizeof(text));
  987. return 1;
  988. }
  989. i = read(fh, text, size);
  990. if (i < size) {
  991. printf("Cannot fully read message from file %s.\n", textfile);
  992. return 1;
  993. }
  994. close(fh);
  995. }
  996. if (text[0] == 0 && textfile[0] == 0 && !edit && !download) {
  997. /* read from stdin */
  998. n = 0;
  999. do {
  1000. i = getchar();
  1001. text[n++] = i;
  1002. } while (i != EOF);
  1003. if (n > 0)
  1004. text[n - 1] = 0;
  1005. }
  1006. /* change CR -> CRLF for unix text files */
  1007. add_crlf(text, sizeof(text));
  1008. /*---- open attachment file ----*/
  1009. for (i = 0; i < MAX_ATTACHMENTS; i++) {
  1010. if (!attachment[i][0])
  1011. break;
  1012. fh = open(attachment[i], O_RDONLY | O_BINARY);
  1013. if (fh < 0) {
  1014. printf("Attachment file \"%s\" does not exist.\n", attachment[i]);
  1015. return 1;
  1016. }
  1017. att_size[i] = lseek(fh, 0, SEEK_END);
  1018. lseek(fh, 0, SEEK_SET);
  1019. buffer[i] = malloc(att_size[i] + 1);
  1020. n = read(fh, buffer[i], att_size[i]);
  1021. if (n < att_size[i]) {
  1022. printf("Cannot fully read attachment file \"%s\".\n", attachment[i]);
  1023. return 1;
  1024. }
  1025. buffer[i][n] = 0;
  1026. close(fh);
  1027. }
  1028. /* now submit message */
  1029. submit_elog(host_name, port, ssl, subdir, logbook,
  1030. uname, upwd, reply, quote_on_reply, edit, download, suppress, encoding, attr_name, attrib, n_attr, text,
  1031. attachment, buffer, att_size);
  1032. for (i = 0; i < MAX_ATTACHMENTS; i++)
  1033. if (buffer[i])
  1034. free(buffer[i]);
  1035. return 0;
  1036. }