diff --git a/src/elog.c b/src/elog.c index a8a557f0..7c8a98c1 100755 --- a/src/elog.c +++ b/src/elog.c @@ -6,6 +6,9 @@ Contents: Electronic logbook utility $Log$ + Revision 1.7 2003/07/15 11:19:45 midas + Added -e flag, reply now quotes original text + Revision 1.6 2003/06/25 15:25:13 midas Fixed bug with 'reply_to' @@ -77,14 +80,16 @@ typedef int INT; -#define MAX_ATTACHMENTS 10 -#define NAME_LENGTH 100 -#define MAX_N_ATTR 20 +#define MAX_ATTACHMENTS 50 +#define NAME_LENGTH 500 +#define MAX_N_ATTR 50 #define TEXT_SIZE 100000 int verbose; +char text[TEXT_SIZE], old_text[TEXT_SIZE], new_text[TEXT_SIZE]; + /*------------------------------------------------------------------*/ char *map= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -119,6 +124,95 @@ unsigned int t, pad; *(--d) = '='; } +/*---- string comparison -------------------------------------------*/ + +BOOL equal_ustring(char *str1, char *str2) +{ + if (str1 == NULL && str2 != NULL) + return FALSE; + if (str1 != NULL && str2 == NULL) + return FALSE; + if (str1 == NULL && str2 == NULL) + return TRUE; + + while (*str1) + if (toupper(*str1++) != toupper(*str2++)) + return FALSE; + + if (*str2) + return FALSE; + + return TRUE; +} + +/*---- strlcpy and strlcat to avoid buffer overflow ----------------*/ + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless size == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t strlcpy(char *dst, const char *src, size_t size) +{ +char *d = dst; +const char *s = src; +size_t n = size; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) + { + do + { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) + { + if (size != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++); + } + + return (s - src - 1); /* count does not include NUL */ +} + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless size <= strlen(dst)). + * Returns strlen(src) + MIN(size, strlen(initial dst)). + * If retval >= size, truncation occurred. + */ +size_t strlcat(char *dst, const char *src, size_t size) +{ +char *d = dst; +const char *s = src; +size_t n = size; +size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = size - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + /*------------------------------------------------------------------*/ void sgets(char *string, int size) @@ -138,10 +232,277 @@ char *p; char request[100000], response[100000], *content; +INT retrieve_elog(char *host, int port, char *subdir, char *experiment, + char *passwd, char *uname, char *upwd, int message_id, + char attrib_name[MAX_N_ATTR][NAME_LENGTH], + char attrib[MAX_N_ATTR][NAME_LENGTH], + char *text) +/********************************************************************\ + + Routine: retrive_elog + + Purpose: Retrive an ELog entry for edit/reply + + Input: + char *host Host name where ELog server runs + in port ELog server port number + char *subdir Subdirectoy to elog server + char *passwd Write password + char *uname User name + char *upwd User password + int message_id Message to retrieve + char *attrib_name Attribute names + char *attrib Attribute values + char *text Message text + + Function value: + EL_SUCCESS Successful completion + +\********************************************************************/ +{ +int status, sock, i, n, first, index; +struct hostent *phe; +struct sockaddr_in bind_addr; +char host_name[256], str[80], *ph, *ps; + +#if defined( _MSC_VER ) + { + WSADATA WSAData; + + /* Start windows sockets */ + if ( WSAStartup(MAKEWORD(1,1), &WSAData) != 0) + return -1; + } +#endif + + /* get local host name */ + gethostname(host_name, sizeof(host_name)); + + phe = gethostbyname(host_name); + if (phe == NULL) + { + perror("Cannot retrieve host name"); + return -1; + } + phe = gethostbyaddr(phe->h_addr, sizeof(int), AF_INET); + if (phe == NULL) + { + perror("Cannot retrieve host name"); + return -1; + } + + /* if domain name is not in host name, hope to get it from phe */ + if (strchr(host_name, '.') == NULL) + strcpy(host_name, phe->h_name); + + /* create socket */ + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + perror("cannot create socket"); + return -1; + } + + /* compose remote address */ + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_addr.s_addr = 0; + bind_addr.sin_port = htons((unsigned short)port); + + phe = gethostbyname(host); + if (phe == NULL) + { + perror("cannot get host name"); + return -1; + } + memcpy((char *)&(bind_addr.sin_addr), phe->h_addr, phe->h_length); + + /* connect to server */ + status = connect(sock, (void *) &bind_addr, sizeof(bind_addr)); + if (status != 0) + { + printf("Cannot connect to host %s, port %d\n", host, port); + return -1; + } + + if (verbose) + printf("Successfully connected to host %s, port %d\n", host, port); + + /* compose request */ + strcpy(request, "GET /"); + if (subdir[0]) + sprintf(request+strlen(request), "%s/%d?cmd=download", subdir, message_id); + if (experiment[0]) + sprintf(request+strlen(request), "%s/%d?cmd=download", experiment, message_id); + strcat(request, " HTTP/1.0\r\n"); + + sprintf(request+strlen(request), "Host: %s\r\n", host_name); + sprintf(request+strlen(request), "User-Agent: ELOG\r\n"); + + first = TRUE; + if (passwd[0]) + { + if (first) + sprintf(request+strlen(request), "Cookie: "); + first = FALSE; + + base64_encode(passwd, str); + sprintf(request+strlen(request), "wpwd=%s;", str); + } + + if (uname[0]) + { + if (first) + sprintf(request+strlen(request), "Cookie: "); + first = FALSE; + + sprintf(request+strlen(request), "unm=%s;", uname); + } + + if (upwd[0]) + { + if (first) + sprintf(request+strlen(request), "Cookie: "); + first = FALSE; + + base64_encode(upwd, str); + sprintf(request+strlen(request), "upwd=%s;", str); + } + + /* finish cookie line */ + if (!first) + strcat(request, "\r\n"); + + strcat(request, "\r\n"); + + /* send request */ + send(sock, request, strlen(request), 0); + if (verbose) + { + printf("Request sent to host:\n"); + puts(request); + } + + /* receive response */ + i = recv(sock, response, sizeof(response), 0); + if (i < 0) + { + perror("Cannot receive response"); + return -1; + } + + n = i; + while (i > 0) + { + i = recv(sock, response+n, sizeof(response)-n, 0); + if (i > 0) + n += i; + } + response[n] = 0; + + closesocket(sock); + + if (verbose) + { + printf("Response received:\n"); + puts(response); + } + + /* check response status */ + if (strstr(response, "$@MID@$:")) + { + /* separate attributes and message */ + + ph = strstr(response, "========================================\n"); + + /* skip first line */ + ps = strstr(response, "$@MID@$:"); + while (*ps && *ps != '\n') + ps++; + while (*ps && (*ps == '\n' || *ps == '\r')) + ps++; + + for (index = 0; index= ph) + break; + + strlcpy(attrib_name[index], ps, NAME_LENGTH); + if (strchr(attrib_name[index], ':')) + *(strchr(attrib_name[index], ':')) = 0; + + ps += strlen(attrib_name[index])+2; + strlcpy(attrib[index], ps, NAME_LENGTH); + + for (i=0 ; i " */ + text[0] = 0; + p = old_text; + + do + { + if (strchr(p, '\n')) + { + *strchr(p, '\n') = 0; + + if (encoding[0] == 'H') + { + strlcat(text, "> ", TEXT_SIZE); + strlcat(text, p, TEXT_SIZE); + strlcat(text, "
\n", TEXT_SIZE); + } + else + { + strlcat(text, "> ", TEXT_SIZE); + strlcat(text, p, TEXT_SIZE); + strlcat(text, "\n", TEXT_SIZE); + } + + p += strlen(p)+1; + if (*p == '\n') + p++; + } + else + { + if (encoding[0] == 'H') + { + strlcat(text, "> ", TEXT_SIZE); + strlcat(text, p, TEXT_SIZE); + strlcat(text, "

\n", TEXT_SIZE); + } + else + { + strlcat(text, "> ", TEXT_SIZE); + strlcat(text, p, TEXT_SIZE); + strlcat(text, "\n\n", TEXT_SIZE); + } + + break; + } + + } while (TRUE); + + strlcat(text, new_text, TEXT_SIZE); + } + /* get local host name */ gethostname(host_name, sizeof(host_name)); @@ -279,6 +764,10 @@ char host_name[256], boundary[80], str[80], *p; sprintf(content+strlen(content), "%s\r\nContent-Disposition: form-data; name=\"reply_to\"\r\n\r\n%d\r\n", boundary, reply); + if (edit) + sprintf(content+strlen(content), + "%s\r\nContent-Disposition: form-data; name=\"edit_id\"\r\n\r\n%d\r\n", boundary, edit); + for (i=0 ; i] (up to %d times)\n", MAX_ATTACHMENTS); printf(" -a = (up to %d times)\n", MAX_N_ATTR); printf(" [-r ] Reply to existing message\n"); + printf(" [-e ] Edit existing message\n"); printf(" -m ] | \n"); printf("\nArguments with blanks must be enclosed in quotes\n"); printf("The elog message can either be submitted on the command line, piped in like\n"); @@ -532,7 +1024,7 @@ char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; return 1; } - if (n_attr == 0) + if (n_attr == 0 && !edit && !reply) { printf("Please specify attribute(s) with the \"-a\" flag.\n"); return 1; @@ -540,13 +1032,6 @@ char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; fh = -1; - if (text[0] == 0 && textfile[0] == 0) - { - /* use stdin */ - fh = 0; - size = sizeof(text); - } - if (textfile[0]) { fh = open(textfile, O_RDONLY | O_BINARY); @@ -576,7 +1061,7 @@ char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; close(fh); } - if (text[0] == 0 && textfile[0] == 0) + if (text[0] == 0 && textfile[0] == 0 && !edit) { /* read from stdin */ @@ -626,7 +1111,7 @@ char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; /* now submit message */ submit_elog(host_name, port, subdir, logbook, password, - uname, upwd, reply, + uname, upwd, reply, edit, attr_name, attrib, n_attr, text, attachment, buffer, att_size);