Jpp  15.0.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
62 typedef 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 
70 int verbose;
71 
73 
74 /*------------------------------------------------------------------*/
75 
76 
77 const 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 
87 const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
88 
89 void 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 
125 int 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 
144 char *sha256_crypt(const char *key, const char *salt);
145 
146 void do_crypt(char *s, char *d, int size)
147 {
148  strlcpy(d, sha256_crypt(s, "$5$") + 4, size);
149 }
150 
151 /*-------------------------------------------------------------------*/
152 
153 void 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 
166 void url_encode(char *ps, int size)
167 /********************************************************************\
168 Encode 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 
194 void 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 
208 void 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 
240 void 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 
257 int 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
298 int 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 
330 char request[100000], response[100000], *content;
331 
332 INT 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 
552 INT 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],
564  char *buffer[MAX_ATTACHMENTS], INT buffer_size[MAX_ATTACHMENTS])
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)
653  strlcpy(text, old_text, TEXT_SIZE);
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);
718  strlcat(text, p, TEXT_SIZE);
719  strlcat(text, "<br>\n", TEXT_SIZE);
720  } else {
721  strlcat(text, "> ", TEXT_SIZE);
722  strlcat(text, p, 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);
732  strlcat(text, p, TEXT_SIZE);
733  strlcat(text, "<p>\n", TEXT_SIZE);
734  } else {
735  strlcat(text, "> ", TEXT_SIZE);
736  strlcat(text, p, TEXT_SIZE);
737  strlcat(text, "\n\n", TEXT_SIZE);
738  }
739 
740  break;
741  }
742 
743  } while (1);
744 
745  strlcat(text, new_text, TEXT_SIZE);
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 
999 int 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 }
void url_encode(char *ps, int size)
Definition: elog.cc:166
char * sha256_crypt(const char *key, const char *salt)
Definition: crypt.cc:573
int main(int argc, char *argv[])
Definition: Main.cc:15
void do_crypt(char *s, char *d, int size)
Definition: elog.cc:146
std::istream & read(std::istream &in, JTestSummary &summary, const char delimiter= ' ')
Read test summary.
char text[TEXT_SIZE]
Definition: elog.cc:72
#define TEXT_SIZE
Definition: elog.cc:68
#define MAX_ATTACHMENTS
Definition: elog.cc:64
void add_crlf(char *buffer, int bufsize)
Definition: elog.cc:208
#define MAX_N_ATTR
Definition: elog.cc:66
T * open(const std::string &file_name)
Open file.
Definition: JeepToolkit.hh:306
void base64_encode(unsigned char *s, unsigned char *d, int size)
Definition: elog.cc:89
then echo The file $DIR KM3NeT_00000001_00000000 root already please rename or remove it first
const int n
Definition: JPolint.hh:660
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: strlcpy.cc:39
const char * git_revision()
Definition: elog.cc:77
int verbose
Definition: elog.cc:70
void convert_crlf(char *buffer, int bufsize)
Definition: elog.cc:240
void close(std::istream *pf)
Close file.
Definition: JeepToolkit.hh:346
int equal_ustring(const char *str1, const char *str2)
Definition: elog.cc:125
const char * _git_revision
Definition: elog.cc:27
static const size_t buffer_size
char * content
Definition: elog.cc:330
#define GIT_REVISION
Definition: git-revision.h:1
char old_text[TEXT_SIZE]
Definition: elog.cc:72
* usage
#define NAME_LENGTH
Definition: elog.cc:65
char new_text[TEXT_SIZE]
Definition: elog.cc:72
then JMuonMCEvt f $INPUT_FILE o $INTERMEDIATE_FILE d
Definition: JMuonPath.sh:47
int elog_connect(char *host, int port)
Definition: elog.cc:257
void sgets(char *string, int size)
Definition: elog.cc:194
char response[100000]
Definition: elog.cc:330
void stou(char *str)
Definition: elog.cc:153
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
const char * map
Definition: elog.cc:87
char request[100000]
Definition: elog.cc:330
int INT
Definition: elog.cc:62
size_t strlcat(char *dst, const char *src, size_t size)
Definition: strlcpy.cc:72
#define O_BINARY
Definition: elog.cc:51
static const char ELOGID[]
Definition: elog-version.h:30
#define closesocket(s)
Definition: elog.cc:49
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