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