From 448c1e07d41b5fc919d7af960f0769950ae0e35a Mon Sep 17 00:00:00 2001 From: Stefan Ritt Date: Wed, 29 May 2002 10:22:46 +0000 Subject: [PATCH] Initial revision SVN revision: 60 --- elconv.c | 1050 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1050 insertions(+) create mode 100644 elconv.c diff --git a/elconv.c b/elconv.c new file mode 100644 index 00000000..70a6be1d --- /dev/null +++ b/elconv.c @@ -0,0 +1,1050 @@ +/********************************************************************\ + + Name: elogd.c + Created by: Stefan Ritt + + Contents: Conversion program for ELOG messages + + $Log$ + Revision 1.1 2002/05/29 10:22:46 midas + Initial revision + + +\********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define OS_WINNT + +#define DIR_SEPARATOR '\\' +#define DIR_SEPARATOR_STR "\\" + +#define snprintf _snprintf + +#include +#include +#include +#include +#else + +#define OS_UNIX + +#define TRUE 1 +#define FALSE 0 + +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" + +#define __USE_XOPEN /* needed for crypt() */ + +typedef int BOOL; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#endif + +typedef int INT; + +#define TELL(fh) lseek(fh, 0, SEEK_CUR) + +#define NAME_LENGTH 256 +#define SUCCESS 1 +#define MAX_PATH_LENGTH 256 + +#define EL_SUCCESS 1 +#define EL_FIRST_MSG 2 +#define EL_LAST_MSG 3 +#define EL_NO_MSG 4 +#define EL_FILE_ERROR 5 + +#define MAX_GROUPS 32 +#define MAX_PARAM 100 +#define MAX_ATTACHMENTS 10 +#define MAX_N_LIST 100 +#define MAX_N_ATTR 50 +#define VALUE_SIZE 256 +#define PARAM_LENGTH 256 +#define TEXT_SIZE 50000 +#define MAX_PATH_LENGTH 256 + +char attr_list[MAX_N_ATTR][NAME_LENGTH]; +char data_dir[256]; +int verbose; + +/*---- Funcions from the MIDAS library -----------------------------*/ + +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; +} + +/*------------------------------------------------------------------*/ + +void el_decode(char *message, char *key, char *result) +{ +char *pc; + + if (result == NULL) + return; + + *result = 0; + + if (strstr(message, key)) + { + for (pc=strstr(message, key)+strlen(key) ; *pc != '\n' && *pc != '\r' ; ) + *result++ = *pc++; + *result = 0; + } +} + +/*------------------------------------------------------------------*/ + +/* Simplified copy of fnmatch() for Cygwin where fnmatch is not defined */ + +#define EOS '\0' + +int fnmatch1(const char *pattern, const char *string) +{ +const char *stringstart; +char c, test; + + for (stringstart = string;;) + switch (c = *pattern++) { + case EOS: + return (*string == EOS ? 0 : 1); + case '?': + if (*string == EOS) + return (1); + ++string; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) + return (0); + + /* General case, use recursion. */ + while ((test = *string) != EOS) + { + if (!fnmatch1(pattern, string)) + return (0); + ++string; + } + return (1); + /* FALLTHROUGH */ + default: + if (c != *string) + return (1); + string++; + break; + } +} + +/*------------------------------------------------------------------*/ + +INT ss_file_find(char * path, char * pattern, char **plist) +/********************************************************************\ + + Routine: ss_file_find + + Purpose: Return list of files matching 'pattern' from the 'path' location + + Input: + char *path Name of a file in file system to check + char *pattern pattern string (wildcard allowed) + + Output: + char **plist pointer to the lfile list + + Function value: + int Number of files matching request + +\********************************************************************/ +{ + int i; + +#ifdef OS_UNIX + DIR *dir_pointer; + struct dirent *dp; + + if ((dir_pointer = opendir(path)) == NULL) + return 0; + *plist = (char *) malloc(MAX_PATH_LENGTH); + i = 0; + for (dp = readdir(dir_pointer); dp != NULL; dp = readdir(dir_pointer)) + { + if (fnmatch1(pattern, dp->d_name) == 0) + { + *plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH); + strncpy(*plist+(i*MAX_PATH_LENGTH), dp->d_name, strlen(dp->d_name)); + *(*plist+(i*MAX_PATH_LENGTH)+strlen(dp->d_name)) = '\0'; + i++; + seekdir(dir_pointer, telldir(dir_pointer)); + } + } + closedir(dir_pointer); +#endif + +#ifdef OS_WINNT + HANDLE pffile; + LPWIN32_FIND_DATA lpfdata; + char str[255]; + int first; + + strcpy(str,path); + strcat(str,"\\"); + strcat(str,pattern); + first = 1; + i = 0; + lpfdata = malloc(sizeof(WIN32_FIND_DATA)); + *plist = (char *) malloc(MAX_PATH_LENGTH); + pffile = FindFirstFile(str, lpfdata); + if (pffile == INVALID_HANDLE_VALUE) + return 0; + first = 0; + *plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH); + strncpy(*plist+(i*MAX_PATH_LENGTH), lpfdata->cFileName, strlen(lpfdata->cFileName)); + *(*plist+(i*MAX_PATH_LENGTH)+strlen(lpfdata->cFileName)) = '\0'; + i++; + while (FindNextFile(pffile, lpfdata)) + { + *plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH); + strncpy(*plist+(i*MAX_PATH_LENGTH), lpfdata->cFileName, strlen(lpfdata->cFileName)); + *(*plist+(i*MAX_PATH_LENGTH)+strlen(lpfdata->cFileName)) = '\0'; + i++; + } + free(lpfdata); +#endif + return i; +} + +/*------------------------------------------------------------------*/ + +INT el_search_message(char *tag, int *fh, BOOL walk, BOOL first) +{ +int lfh, i, n, d, min, max, size, offset, direction, last, status, did_walk; +struct tm *tms, ltms; +time_t lt, ltime, lact; +char str[256], file_name[256], dir[256]; +char *file_list; + + did_walk = 0; + ltime = lfh = 0; + + /* get data directory */ + strcpy(dir, data_dir); + + /* check tag for direction */ + direction = 0; + if (strpbrk(tag, "+-")) + { + direction = atoi(strpbrk(tag, "+-")); + *strpbrk(tag, "+-") = 0; + } + + /* if tag is given, open file directly */ + if (tag[0]) + { + /* extract time structure from tag */ + tms = <ms; + memset(tms, 0, sizeof(struct tm)); + tms->tm_year = (tag[0]-'0')*10 + (tag[1]-'0'); + tms->tm_mon = (tag[2]-'0')*10 + (tag[3]-'0') -1; + tms->tm_mday = (tag[4]-'0')*10 + (tag[5]-'0'); + tms->tm_hour = 12; + + if (tms->tm_year < 90) + tms->tm_year += 100; + ltime = lt = mktime(tms); + + if (ltime < 0) + return -1; + + strcpy(str, tag); + if (strchr(str, '.')) + { + offset = atoi(strchr(str, '.')+1); + *strchr(str, '.') = 0; + } + else + return -1; + + do + { + tms = localtime(<ime); + + sprintf(file_name, "%s%02d%02d%02d.log", dir, + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday); + lfh = open(file_name, O_RDWR | O_BINARY, 0644); + + if (lfh < 0) + { + if (!walk) + return EL_FILE_ERROR; + + did_walk = 1; + + if (direction == -1) + ltime -= 3600*24; /* one day back */ + else + ltime += 3600*24; /* go forward one day */ + + /* set new tag */ + tms = localtime(<ime); + sprintf(tag, "%02d%02d%02d.0", tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday); + } + + /* in forward direction, stop today */ + if (direction != -1 && ltime > (time_t)(time(NULL)+3600*24)) + break; + + /* in backward direction, go back 10 years */ + if (direction == -1 && abs((int)(lt-ltime)) > 3600*24*365*10) + break; + + } while (lfh < 0); + + if (lfh < 0) + return EL_FILE_ERROR; + + if (direction == -1 && did_walk) + lseek(lfh, 0, SEEK_END); + else + lseek(lfh, offset, SEEK_SET); + } + + /* open most recent file if no tag given */ + if (tag[0] == 0) + { + if (first) + { + /* go through whole directory, find first file */ + + file_list = NULL; + n = ss_file_find(dir, "??????.log", &file_list); + if (n == 0) + { + if (file_list) + free(file_list); + return EL_FILE_ERROR; + } + + for (i=0,min=9999999 ; i max) + max = d; + } + free(file_list); + sprintf(file_name, "%s%06d.log", dir, max % 1000000); + lfh = open(file_name, O_RDWR | O_BINARY, 0644); + if (lfh < 0) + return EL_FILE_ERROR; + + lseek(lfh, 0, SEEK_END); + + /* remember tag */ + sprintf(tag, "%06d.%d", (int) (max % 1000000), (int) (TELL(lfh))); + } + } + + if (direction == -1) + { + /* seek previous message */ + + if (TELL(lfh) == 0) + { + /* go back one day */ + close(lfh); + + lt = ltime; + do + { + lt -= 3600*24; + tms = localtime(<); + sprintf(str, "%02d%02d%02d.0", + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday); + + status = el_search_message(str, &lfh, FALSE, FALSE); + + } while (status != SUCCESS && + (INT)ltime-(INT)lt < 3600*24*365); + + if (status != EL_SUCCESS) + { + if (fh) + *fh = lfh; + else + close(lfh); + return EL_FIRST_MSG; + } + + /* adjust tag */ + strcpy(tag, str); + + /* go to end of current file */ + lseek(lfh, 0, SEEK_END); + } + + /* read previous message size */ + lseek(lfh, -17, SEEK_CUR); + i = read(lfh, str, 17); + if (i <= 0) + { + close(lfh); + return EL_FILE_ERROR; + } + + if (strncmp(str, "$End$: ", 7) == 0) + { + size = atoi(str+7); + lseek(lfh, -size, SEEK_CUR); + } + else + { + close(lfh); + return EL_FILE_ERROR; + } + + /* adjust tag */ + sprintf(strchr(tag, '.')+1, "%d", (int) (TELL(lfh))); + } + + if (direction == 1) + { + /* seek next message */ + + /* read current message size */ + last = TELL(lfh); + + i = read(lfh, str, 15); + if (i <= 0) + { + close(lfh); + return EL_FILE_ERROR; + } + lseek(lfh, -15, SEEK_CUR); + + if (strncmp(str, "$Start$: ", 9) == 0) + { + size = atoi(str+9); + lseek(lfh, size, SEEK_CUR); + } + else + { + close(lfh); + return EL_FILE_ERROR; + } + + /* if EOF, goto next day */ + i = read(lfh, str, 15); + if (i < 15) + { + close(lfh); + time(&lact); + + lt = ltime; + do + { + lt += 3600*24; + tms = localtime(<); + sprintf(str, "%02d%02d%02d.0", + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday); + + status = el_search_message(str, &lfh, FALSE, FALSE); + + } while (status != EL_SUCCESS && + (INT)lt-(INT)lact < 3600*24); + + if (status != EL_SUCCESS) + { + if (fh) + *fh = lfh; + else + close(lfh); + return EL_LAST_MSG; + } + + /* adjust tag */ + strcpy(tag, str); + + /* go to beginning of current file */ + lseek(lfh, 0, SEEK_SET); + } + else + lseek(lfh, -15, SEEK_CUR); + + /* adjust tag */ + sprintf(strchr(tag, '.')+1, "%d", (int) (TELL(lfh))); + } + + if (fh) + *fh = lfh; + else + close(lfh); + + return EL_SUCCESS; +} + +/*------------------------------------------------------------------*/ + +INT el_submit(char attr_name[MAX_N_ATTR][NAME_LENGTH], + char attr_value[MAX_N_ATTR][NAME_LENGTH], + int n_attr, char *text, char *reply_to, char *encoding, + char afilename[MAX_ATTACHMENTS][256], + char *buffer[MAX_ATTACHMENTS], + INT buffer_size[MAX_ATTACHMENTS], + char *tag, INT tag_size) +/********************************************************************\ + + Routine: el_submit + + Purpose: Submit an ELog entry + + Input: + char attr_name[][] Name of attributes + char attr_value[][] Value of attributes + int n_attr Number of attributes + + char *text Message text + char *reply_to In reply to this message + char *encoding Text encoding, either HTML or plain + + char *afilename[] File name of attachments + char *buffer[] Attachment contents + INT *buffer_size[] Size of attachment in bytes + char *tag If given, edit existing message + INT *tag_size Maximum size of tag + + Output: + char *tag Message tag in the form YYMMDD.offset + INT *tag_size Size of returned tag + + Function value: + EL_SUCCESS Successful completion + +\********************************************************************/ +{ +INT n, i, size, fh, status, index, offset, tail_size; +struct tm *tms; +char file_name[256], afile_name[MAX_ATTACHMENTS][256], dir[256], str[256], + start_str[80], end_str[80], last[80], date[80], thread[80], attachment_all[64*MAX_ATTACHMENTS]; +time_t now; +char message[TEXT_SIZE+100], *p; +BOOL bedit; + + bedit = (tag[0] != 0); + + for (index = 0 ; index < MAX_ATTACHMENTS ; index++) + { + /* generate filename for attachment */ + afile_name[index][0] = file_name[0] = 0; + + if (afilename[index][0] && buffer_size[index] == 0) + { + /* resubmission of existing attachment */ + strcpy(afile_name[index], afilename[index]); + } + else + { + if (afilename[index][0]) + { + /* strip directory, add date and time to filename */ + + strcpy(file_name, afilename[index]); + p = file_name; + while (strchr(p, ':')) + p = strchr(p, ':')+1; + while (strchr(p, '\\')) + p = strchr(p, '\\')+1; /* NT */ + while (strchr(p, '/')) + p = strchr(p, '/')+1; /* Unix */ + + /* assemble ELog filename */ + if (p[0]) + { + strcpy(dir, data_dir); + + time(&now); + tms = localtime(&now); + + strcpy(str, p); + sprintf(afile_name[index], "%02d%02d%02d_%02d%02d%02d_%s", + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday, + tms->tm_hour, tms->tm_min, tms->tm_sec, str); + sprintf(file_name, "%s%02d%02d%02d_%02d%02d%02d_%s", dir, + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday, + tms->tm_hour, tms->tm_min, tms->tm_sec, str); + + /* save attachment */ + fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644); + if (fh < 0) + { + printf("Cannot write attachment file \"%s\"", file_name); + } + else + { + write(fh, buffer[index], buffer_size[index]); + close(fh); + } + } + } + } + } + + /* generate new file name YYMMDD.log in data directory */ + strcpy(dir, data_dir); + + if (bedit) + { + /* edit existing message */ + strcpy(str, tag); + if (strchr(str, '.')) + { + offset = atoi(strchr(str, '.')+1); + *strchr(str, '.') = 0; + } + sprintf(file_name, "%s%s.log", dir, str); + fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644); + if (fh < 0) + return -1; + + lseek(fh, offset, SEEK_SET); + read(fh, str, 16); + size = atoi(str+9); + read(fh, message, size); + + el_decode(message, "Date: ", date); + el_decode(message, "Thread: ", thread); + el_decode(message, "Attachment: ", attachment_all); + + /* buffer tail of logfile */ + lseek(fh, 0, SEEK_END); + tail_size = TELL(fh) - (offset+size); + + if (tail_size > 0) + { + buffer = malloc(tail_size); + if (buffer == NULL) + { + close(fh); + return -1; + } + + lseek(fh, offset+size, SEEK_SET); + n = read(fh, buffer, tail_size); + } + lseek(fh, offset, SEEK_SET); + } + else + { + /* create new message */ + time(&now); + tms = localtime(&now); + + sprintf(file_name, "%s%02d%02d%02d.log", dir, + tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday); + + fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644); + if (fh < 0) + return -1; + + strcpy(date, ctime(&now)); + date[24] = 0; + + if (reply_to[0]) + sprintf(thread, "%16s %16s", reply_to, "0"); + else + sprintf(thread, "%16s %16s", "0", "0"); + + lseek(fh, 0, SEEK_END); + } + + /* compose message */ + + sprintf(message, "Date: %s\n", date); + sprintf(message+strlen(message), "Thread: %s\n", thread); + + for (i=0 ; itm_year % 100, tms->tm_mon+1, tms->tm_mday, (int) (TELL(fh))); + + sprintf(start_str, "$Start$: %6d\n", size); + sprintf(end_str, "$End$: %6d\n\f", size); + + write(fh, start_str, strlen(start_str)); + write(fh, message, strlen(message)); + write(fh, end_str, strlen(end_str)); + + if (bedit) + { + if (tail_size > 0) + { + n = write(fh, buffer, tail_size); + free(buffer); + } + + /* truncate file here */ +#ifdef _MSC_VER + chsize(fh, TELL(fh)); +#else + ftruncate(fh, TELL(fh)); +#endif + } + + close(fh); + + /* if reply, mark original message */ + if (reply_to[0] && !bedit) + { + strcpy(last, reply_to); + do + { + status = el_search_message(last, &fh, FALSE, FALSE); + if (status == EL_SUCCESS) + { + /* position to next thread location */ + lseek(fh, 72, SEEK_CUR); + memset(str, 0, sizeof(str)); + read(fh, str, 16); + lseek(fh, -16, SEEK_CUR); + + /* if no reply yet, set it */ + if (atoi(str) == 0) + { + sprintf(str, "%16s", tag); + write(fh, str, 16); + close(fh); + break; + } + else + { + /* if reply set, find last one in chain */ + strcpy(last, strtok(str, " ")); + close(fh); + } + } + else + /* stop on error */ + break; + + } while (TRUE); + } + + return EL_SUCCESS; +} + +/*------------------------------------------------------------------*/ + +INT el_get_v1(char *tag, char *message, int *bufsize) +/********************************************************************\ + + Routine: el_get_v1 + + Purpose: Retrieve in ELog entry in format 1 + + Input: + char *tag tag in the form YYMMDD.offset + int size Size of message buffer + + Output: + char *tag tag of retrieved message + char *message Message attributes and body + + Function value: + EL_SUCCESS Successful completion + EL_NO_MSG No message in log + EL_LAST_MSG Last message in log + EL_FILE_ERROR Internal error + +\********************************************************************/ +{ +int i, size, fh, offset, search_status; +char str[256]; + + if (tag[0]) + { + search_status = el_search_message(tag, &fh, TRUE, FALSE); + if (search_status != EL_SUCCESS) + return search_status; + } + else + { + /* open most recent message */ + strcpy(tag, "-1"); + search_status = el_search_message(tag, &fh, TRUE, FALSE); + if (search_status != EL_SUCCESS) + return search_status; + } + + /* extract message size */ + offset = TELL(fh); + i = read(fh, str, 16); + if (i <= 0) + { + close(fh); + return EL_FILE_ERROR; + } + + if (strncmp(str, "$Start$: ", 9) == 0) + size = atoi(str+9); + else + { + close(fh); + return EL_FILE_ERROR; + } + + /* read message */ + memset(message, 0, sizeof(message)); + read(fh, message, size); + close(fh); + + *bufsize = size; + + return EL_SUCCESS; +} + + +/*------------------------------------------------------------------*/ + +void scan_message() +{ +int size, status, fh, message_id; +char file_name[256], tag[256], str[256]; +char message[TEXT_SIZE+1000]; + + tag[0] = 0; + message_id = 1; + + /* search first message */ + status = el_search_message(tag, NULL, TRUE, TRUE); + + if (status == EL_FILE_ERROR) + { + printf("Cannot find any ??????.log file in this directory.\n"); + return; + } + + do + { + size = sizeof(message); + status = el_get_v1(tag, message, &size); + + if (status == EL_LAST_MSG) + break; + + if (verbose) + printf("Converting %s\n", tag); + + strcpy(str, tag); + str[6] = 0; + sprintf(file_name, "%s%sa.log", data_dir, str); + + fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644); + if (fh < 0) + { + printf("Error: Cannot open file %s for writing.\n", file_name); + return; + } + + lseek(fh, 0, SEEK_END); + + /* write new message header */ + sprintf(str, "$@MID@$: %d\n", message_id); + write(fh, str, strlen(str)); + + /* strip $end$ */ + if (strstr(message, "$End$")) + *strstr(message, "$End$") = 0; + + if (message[strlen(message)-1] != '\n') + strcat(message, "\n"); + write(fh, message, strlen(message)); + + close(fh); + + message_id++; + strcat(tag, "+1"); + + } while (1); + +} + +/*------------------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ +int i; + + /* parse command line parameters */ + for (i=1 ; i= argc || argv[i+1][0] == '-') + goto usage; + else + { +usage: + printf("usage: %s ", argv[0]); + printf(" -v debugging output\n"); + return 0; + } + } + } + + /* use current directory as working directory */ + getcwd(data_dir, sizeof(data_dir)); + strcat(data_dir, DIR_SEPARATOR_STR); + + scan_message(); + + return 0; +}