31 #include <sys/types.h> 
   44 #include <netinet/in.h> 
   45 #include <sys/socket.h> 
   49 #define closesocket(s) close(s) 
   57 #include <openssl/ssl.h> 
   64 #define MAX_ATTACHMENTS  50 
   65 #define NAME_LENGTH     500 
   68 #define TEXT_SIZE    100000 
   81       p = strrchr(p, 
'-')+2;
 
   87 const char *
map = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
   94    pad = 3 - strlen((
char *) s) % 3;
 
  105       *(d + 3) = 
map[t & 63];
 
  107       *(d + 2) = 
map[t & 63];
 
  109       *(d + 1) = 
map[t & 63];
 
  111       *(d + 0) = 
map[t & 63];
 
  114       if (d - p >= size - 3)
 
  127    if (str1 == NULL && str2 != NULL)
 
  129    if (str1 != NULL && str2 == NULL)
 
  131    if (str1 == NULL && str2 == NULL)
 
  135       if (toupper(*str1++) != toupper(*str2++))
 
  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] == 
')')
 
  171    unsigned char *pd, *p;
 
  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);
 
  181       } 
else if (*p == 
' ') {
 
  189    strlcpy(ps, (
char *) str, size);
 
  199       p = fgets(
string, size, stdin);
 
  202    if (strlen(p) > 0 && p[strlen(p) - 1] == 
'\n')
 
  203       p[strlen(p) - 1] = 0;
 
  213    tmpbuf = (
char *)malloc(bufsize);
 
  217    while ((p = strstr(p, 
"\n")) != NULL) {
 
  219       if (p > buffer && *(p - 1) == 
'\r') {
 
  224       if ((
int) strlen(buffer) + 2 >= bufsize) {
 
  231       strlcpy(p, tmpbuf, bufsize - (p - buffer));
 
  246    while ((p = strstr(p, 
"\\n")) != NULL) {
 
  248       if (p - buffer < bufsize - 2) {
 
  261    struct sockaddr_in bind_addr;
 
  264    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
 
  265       perror(
"cannot create socket");
 
  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);
 
  275    phe = gethostbyname(host);
 
  277       perror(
"cannot get host name");
 
  280    memcpy((
char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
 
  283    status = connect(sock, (
const sockaddr*) (&bind_addr), 
sizeof(bind_addr));
 
  285       printf(
"Cannot connect to host %s, port %d\n", host, port);
 
  290       printf(
"Successfully connected to host %s, port %d\n", host, port);
 
  298 int ssl_connect(
int sock, SSL ** ssl_con)
 
  306    SSL_load_error_strings();
 
  308    meth = (SSL_METHOD *) TLSv1_2_method();
 
  309    ctx = SSL_CTX_new(meth);
 
  311    *ssl_con = SSL_new(ctx);
 
  312    SSL_set_fd(*ssl_con, sock);
 
  313    if (SSL_connect(*ssl_con) <= 0)
 
  316    cert = SSL_get_peer_certificate(*ssl_con);
 
  320    i = SSL_get_verify_result(*ssl_con);
 
  322       printf(
"Possibly invalid certificate, continue on your own risk!\n");
 
  333                   char *uname, 
char *upwd, 
int message_id,
 
  358    int i, 
n, first, index, sock;
 
  359    char str[256], encrypted_passwd[256], *ph, *ps;
 
  373       if (ssl_connect(sock, &ssl_con) < 0) {
 
  374          printf(
"elogd server does not run SSL protocol\n");
 
  381    strlcpy(str, experiment, 
sizeof(str));
 
  383    if (subdir[0] && experiment[0])
 
  384       sprintf(
request + strlen(
request), 
"%s/%s/%d?cmd=download", subdir, str, message_id);
 
  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");
 
  408       do_crypt(upwd, encrypted_passwd, 
sizeof(encrypted_passwd));
 
  426       printf(
"Request sent to host:\n");
 
  439       perror(
"Cannot receive response");
 
  458       SSL_shutdown(ssl_con);
 
  466       printf(
"Response received:\n");
 
  474       ph = strstr(
response, 
"========================================\n");
 
  478       while (*ps && *ps != 
'\n')
 
  480       while (*ps && (*ps == 
'\n' || *ps == 
'\r'))
 
  483       for (index = 0; index < 
MAX_N_ATTR; index++) {
 
  488          if (strchr(attrib_name[index], 
':'))
 
  489             *(strchr(attrib_name[index], 
':')) = 0;
 
  491          ps += strlen(attrib_name[index]) + 2;
 
  495             if (attrib[index][i] == 
'\r' || attrib[index][i] == 
'\n')
 
  496                attrib[index][i] = 0;
 
  498             if (attrib[index][i] == 0)
 
  502          ps += strlen(attrib[index]);
 
  503          while (*ps && (*ps == 
'\n' || *ps == 
'\r'))
 
  507       attrib_name[index][0] = 0;
 
  508       attrib[index][0] = 0;
 
  510       ph = strchr(ph, 
'\n') + 1;
 
  519    if (strstr(
response, 
"302 Found")) {
 
  520       if (strstr(
response, 
"Location:")) {
 
  522             printf(
"Error: Invalid user name or password\n");
 
  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;
 
  532             if (strrchr(str, 
'/'))
 
  533                printf(
"Message successfully transmitted, ID=%s\n", strrchr(str, 
'/') + 1);
 
  535                printf(
"Message successfully transmitted, ID=%s\n", str);
 
  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");
 
  545       printf(
"Error transmitting message\n");
 
  553                 char *uname, 
char *upwd,
 
  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;
 
  606    gethostname(host_name, 
sizeof(host_name));
 
  608    phe = gethostbyname(host_name);
 
  610       perror(
"Cannot retrieve host name");
 
  613    phe = gethostbyaddr(phe->h_addr, 
sizeof(
int), AF_INET);
 
  615       perror(
"Cannot retrieve host name");
 
  620    if (strchr(host_name, 
'.') == NULL)
 
  621       strcpy(host_name, phe->h_name);
 
  623    if (edit || download) {
 
  625          status = 
retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, edit,
 
  626                                 old_attrib_name, old_attrib, 
old_text);
 
  628          status = 
retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, download,
 
  629                                 old_attrib_name, old_attrib, 
old_text);
 
  635       for (index = 0; index < n_attr; index++) {
 
  636          for (i = 0; i < 
MAX_N_ATTR && old_attrib_name[i][0]; i++)
 
  640          if (old_attrib_name[i][0])
 
  645       for (i = 0; i < 
MAX_N_ATTR && old_attrib_name[i][0]; i++) {
 
  658          printf(
"%s", strstr(
response, 
"$@MID@$:"));
 
  666           retrieve_elog(host, port, subdir, ssl, experiment, uname, upwd, reply,
 
  667                         old_attrib_name, old_attrib, 
old_text);
 
  673       for (index = 0; index < n_attr; index++) {
 
  674          for (i = 0; i < 
MAX_N_ATTR && old_attrib_name[i][0]; i++)
 
  678          if (old_attrib_name[i][0])
 
  683       for (i = 0; i < 
MAX_N_ATTR && old_attrib_name[i][0]; i++) {
 
  685             attrib_name[i][0] = 0;
 
  696       old_encoding = 
"plain";
 
  698       for (i = 0; i < n_attr; i++)
 
  703          old_encoding = attrib[i];
 
  705       if (quote_on_reply) {
 
  713             if (strchr(p, 
'\n')) {
 
  714                *strchr(p, 
'\n') = 0;
 
  716                if (old_encoding[0] == 
'H') {
 
  730                if (old_encoding[0] == 
'H') {
 
  755       if (ssl_connect(sock, &ssl_con) < 0) {
 
  756          printf(
"elogd server does not run SSL protocol\n");
 
  761    content_length = 100000;
 
  765    content = (
char *)malloc(content_length);
 
  767       printf(
"Not enough memory\n");
 
  772    srand((
unsigned) time(NULL));
 
  773    sprintf(boundary, 
"---------------------------%04X%04X%04X", rand(), rand(), rand());
 
  775    strcat(
content, 
"\r\nContent-Disposition: form-data; name=\"cmd\"\r\n\r\nSubmit\r\n");
 
  779               "%s\r\nContent-Disposition: form-data; name=\"unm\"\r\n\r\n%s\r\n", boundary, uname);
 
  782       do_crypt(upwd, encrypted_passwd, 
sizeof(encrypted_passwd));
 
  784               "%s\r\nContent-Disposition: form-data; name=\"upwd\"\r\n\r\n%s\r\n", boundary,
 
  790               "%s\r\nContent-Disposition: form-data; name=\"exp\"\r\n\r\n%s\r\n", boundary, experiment);
 
  794               "%s\r\nContent-Disposition: form-data; name=\"reply_to\"\r\n\r\n%d\r\n", boundary, reply);
 
  798               "%s\r\nContent-Disposition: form-data; name=\"edit_id\"\r\n\r\n%d\r\n", boundary, edit);
 
  800               "%s\r\nContent-Disposition: form-data; name=\"skiplock\"\r\n\r\n1\r\n", boundary);
 
  805               "%s\r\nContent-Disposition: form-data; name=\"suppress\"\r\n\r\n1\r\n", boundary);
 
  809               "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nELCode\r\n", boundary);
 
  810    else if (encoding == 1)
 
  812               "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nplain\r\n", boundary);
 
  813    else if (encoding == 2)
 
  815               "%s\r\nContent-Disposition: form-data; name=\"encoding\"\r\n\r\nHTML\r\n", boundary);
 
  817    for (i = 0; i < n_attr; i++) {
 
  818       strcpy(str, attrib_name[i]);
 
  822                  "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", boundary, str, attrib[i]);
 
  828               "%s\r\nContent-Disposition: form-data; name=\"Text\"\r\n\r\n%s\r\n%s\r\n",
 
  829               boundary, 
text, boundary);
 
  831    content_length = strlen(
content);
 
  835       if (afilename[i][0]) {
 
  837                  "Content-Disposition: form-data; name=\"attfile%d\"; filename=\"%s\"\r\n\r\n",
 
  838                  i + 1, afilename[i]);
 
  840          content_length += strlen(p);
 
  856       strcpy(str, experiment);
 
  860    strcat(
request, 
" HTTP/1.0\r\n");
 
  862    sprintf(
request + strlen(
request), 
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
 
  864       sprintf(str, 
"%s:%d", host, port);
 
  866       sprintf(str, 
"%s", host);
 
  869    sprintf(
request + strlen(
request), 
"Content-Length: %d\r\n", content_length);
 
  873    header_length = strlen(
request);
 
  887       SSL_write(ssl_con, 
request, header_length);
 
  890       send(sock, 
request, header_length, 0);
 
  892       printf(
"Request sent to host:\n");
 
  899       SSL_write(ssl_con, 
content, content_length);
 
  902       send(sock, 
content, content_length, 0);
 
  904       printf(
"Content sent to host:\n");
 
  917       perror(
"Cannot receive response");
 
  937       SSL_shutdown(ssl_con);
 
  945       printf(
"Response received:\n");
 
  950    if (strstr(
response, 
"302 Found")) {
 
  951       if (strstr(
response, 
"Location:")) {
 
  953             printf(
"Error: elogd server has moved to another location\n");
 
  955             printf(
"Error: Invalid user name or password\n");
 
  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;
 
  965             if (strrchr(str, 
'/'))
 
  966                printf(
"Message successfully transmitted, ID=%s\n", strrchr(str, 
'/') + 1);
 
  968                printf(
"Message successfully transmitted, ID=%s\n", str);
 
  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);
 
  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);
 
  989    else if (strstr(
response, 
"form name=form1"))
 
  990       printf(
"Error: Missing or invalid user name/password\n");
 
  992       printf(
"Error transmitting message\n");
 
  999 int main(
int argc, 
char *argv[])
 
 1001    char str[1000], uname[80], upwd[80];
 
 1002    char host_name[256], logbook[32], textfile[256], subdir[256];
 
 1005    INT i, 
n, fh, n_att, n_attr, port, reply, quote_on_reply, edit, download, encoding, suppress, size, ssl,
 
 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;
 
 1017       attachment[i][0] = 0;
 
 1023    for (i = 1; i < argc; i++) {
 
 1024       if (argv[i][0] == 
'-' && argv[i][1] == 
'v')
 
 1026       else if (argv[i][0] == 
'-' && argv[i][1] == 
's')
 
 1028       else if (argv[i][0] == 
'-' && argv[i][1] == 
'q')
 
 1030       else if (argv[i][0] == 
'-' && argv[i][1] == 
'x')
 
 1033          if (argv[i][0] == 
'-') {
 
 1034             if (i + 1 >= argc || argv[i + 1][0] == 
'-')
 
 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);
 
 1055                   printf(
"Error: Attributes must be supplied in the form \"-a <attribute>=<value>\".\n");
 
 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')
 
 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]);
 
 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");
 
 1101             strcpy(
text, argv[i]);
 
 1110       printf(
"SLL support not compiled into this program\n");
 
 1115 #if defined( _MSC_VER ) 
 1120       if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
 
 1125    if (host_name[0] == 0) {
 
 1126       printf(
"Please specify hostname.\n");
 
 1130    if (logbook[0] == 0) {
 
 1131       printf(
"Please specify logbook with the \"-l\" flag.\n");
 
 1135    if (n_attr == 0 && !edit && !reply && !download) {
 
 1136       printf(
"Please specify attribute(s) with the \"-a\" flag.\n");
 
 1145          printf(
"Message file \"%s\" does not exist.\n", textfile);
 
 1149       size = (
INT) lseek(fh, 0, SEEK_END);
 
 1150       lseek(fh, 0, SEEK_SET);
 
 1152       if (size > (
INT) (
sizeof(
text) - 1)) {
 
 1153          printf(
"Message file \"%s\" is too long (%zd bytes max).\n", textfile, 
sizeof(
text));
 
 1160          printf(
"Cannot fully read message from file %s.\n", textfile);
 
 1167    if (text_flag == 0 && !edit && !download) {
 
 1189       if (!attachment[i][0])
 
 1194          printf(
"Attachment file \"%s\" does not exist.\n", attachment[i]);
 
 1198       att_size[i] = lseek(fh, 0, SEEK_END);
 
 1199       lseek(fh, 0, SEEK_SET);
 
 1201       buffer[i] = (
char *)malloc(att_size[i] + 1);
 
 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]);
 
 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);
 
static const size_t buffer_size
 
static const char ELOGID[]
 
void url_encode(char *ps, int size)
 
void sgets(char *string, int size)
 
int main(int argc, char *argv[])
 
void convert_crlf(char *buffer, int bufsize)
 
const char * git_revision()
 
const char * _git_revision
 
void base64_encode(unsigned char *s, unsigned char *d, int size)
 
char * sha256_crypt(const char *key, const char *salt)
 
void add_crlf(char *buffer, int bufsize)
 
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)
 
void do_crypt(char *s, char *d, int size)
 
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])
 
int elog_connect(char *host, int port)
 
int equal_ustring(const char *str1, const char *str2)
 
std::istream & read(std::istream &in, JTestSummary &summary, const char delimiter=' ')
Read test summary.
 
void close(std::istream *pf)
Close file.
 
T * open(const std::string &file_name)
Open file.
 
size_t strlcat(char *dst, const char *src, size_t size)
 
size_t strlcpy(char *dst, const char *src, size_t size)