/********************************************************************\ Name: elogd.c Created by: Stefan Ritt Contents: Web server program for Electronic Logbook ELOG $Log$ Revision 1.31 2002/06/03 09:55:08 midas Added 'start page=' option Revision 1.30 2002/06/03 09:37:47 midas Fixed bug with MOptions in Email notification Revision 1.29 2002/06/03 08:30:44 midas Add
for replies in HTML format Revision 1.28 2002/06/03 08:12:24 midas Reversed setuid() and creation of elogd.pid Revision 1.27 2002/06/03 08:07:47 midas elogd.pid is now created from child Revision 1.26 2002/06/03 07:32:27 midas Added 'Title image URL' in theme file Revision 1.25 2002/05/31 14:20:50 midas Added 'user' and 'group' statements in configuration file Revision 1.24 2002/05/31 13:24:18 midas Use Referer for mail notification URL Revision 1.23 2002/05/31 12:51:58 midas First version with truely relative paths Revision 1.22 2002/05/13 20:50:53 midas Fixed problem with daylight savings time Revision 1.21 2002/05/03 07:39:16 midas Fixed bug with "Content-Length" Revision 1.20 2002/05/02 15:42:06 midas Removed lingering and do a REUSEADDR by default Revision 1.19 2002/05/02 14:45:10 midas Evaluage 'HEAD' request (for wget) Revision 1.18 2002/04/30 13:40:33 midas Version 1.3.5 Revision 1.17 2002/04/29 08:11:38 midas Added icons via IOptions configuration Revision 1.16 2002/04/22 10:32:35 midas Version 1.3.4 Revision 1.15 2002/04/22 10:31:58 midas Added "logfile", fixed hightlighting problems, thanks to Heiko.Schleit@mpi-hd.mpg.de Revision 1.14 2002/03/14 11:48:43 midas Added .jpeg file extension Revision 1.13 2002/02/25 16:12:26 midas Added BGImage and BDTImage in themes Revision 1.12 2002/02/25 15:31:04 midas Made "move to", "copy to" and "submit" (from elog) work in other languages Revision 1.11 2002/02/12 16:06:10 midas Fixed small bug Revision 1.10 2002/01/31 00:51:41 midas Small patch to make elogd run under Mac OS X (Darwin), thanks to Dominik Westner Revision 1.9 2002/01/30 04:26:05 midas Added flag 'restrict edit = 0/1' Revision 1.8 2002/01/29 10:06:23 midas Fixed various bugs with fixed attributes Revision 1.7 2002/01/23 08:41:42 midas Added "Search all logbooks" flag Revision 1.6 2002/01/15 10:23:59 midas - Remove "back" button from error display (NS4.7 does not support it) - Fixed wrong URL in email notification - Submission of new messages possible even if cookie expired during editing Revision 1.5 2002/01/14 13:05:41 midas - Check for JavaScript in error display - Improved decoding of POST message (needed for lynx) Revision 1.4 2001/12/21 16:03:23 midas Moved themes directories under "themes/" Revision 1.3 2001/12/21 15:28:51 midas Initial version as separate package, corresponds to V1.3.2 \********************************************************************/ /* Version of ELOG */ #define VERSION "1.3.6" #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 #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 #include #include #define closesocket(s) close(s) #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 EL_SUCCESS 1 #define EL_FIRST_MSG 2 #define EL_LAST_MSG 3 #define EL_NO_MSG 4 #define EL_FILE_ERROR 5 #define WEB_BUFFER_SIZE 2000000 char return_buffer[WEB_BUFFER_SIZE]; int strlen_retbuf; int keep_alive; char header_buffer[1000]; int return_length; char host_name[256]; char referer[256]; char logbook[256]; char logbook_enc[256]; char data_dir[256]; char cfg_file[256]; char cfg_dir[256]; char tcp_hostname[256]; int tcp_port = 80; #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 _param[MAX_PARAM][PARAM_LENGTH]; char _value[MAX_PARAM][VALUE_SIZE]; char _text[TEXT_SIZE]; char *_attachment_buffer[MAX_ATTACHMENTS]; INT _attachment_size[MAX_ATTACHMENTS]; struct in_addr rem_addr; INT _sock; BOOL verbose, use_keepalive; char *mname[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; char type_list[MAX_N_LIST][NAME_LENGTH] = { "Routine", "Other" }; char category_list[MAX_N_LIST][NAME_LENGTH] = { "General", "Other", }; char author_list[MAX_N_LIST][NAME_LENGTH] = { "" }; /* attribute flags */ #define AF_REQUIRED (1<<0) #define AF_LOCKED (1<<1) #define AF_MULTI (1<<2) #define AF_FIXED (1<<3) #define AF_ICON (1<<4) char attr_list[MAX_N_ATTR][NAME_LENGTH]; char attr_options[MAX_N_ATTR][MAX_N_LIST][NAME_LENGTH]; int attr_flags[MAX_N_ATTR]; char attr_list_default[][NAME_LENGTH] = { "Author", "Type", "Category", "Subject", "" }; char attr_options_default[][MAX_N_LIST][NAME_LENGTH] = { { "" }, { "Routine", "Other" }, { "General", "Other" }, { "" } }; int attr_flags_default[] = { AF_REQUIRED, 0, 0, 0 }; struct { char ext[32]; char type[32]; } filetype[] = { { ".JPG", "image/jpeg" }, { ".JPEG", "image/jpeg" }, { ".GIF", "image/gif" }, { ".PNG", "image/png" }, { ".PS", "application/postscript" }, { ".EPS", "application/postscript" }, { ".HTML", "text/html" }, { ".HTM", "text/html" }, { ".XLS", "application/x-msexcel" }, { ".DOC", "application/msword" }, { ".PDF", "application/pdf" }, { ".TXT", "text/plain" }, { ".ASC", "text/plain" }, { ".ZIP", "application/x-zip-compressed" }, { "" }, }; int scan_attributes(char *logbook); void show_error(char *error); /*---- 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 strsubst(char *string, char name[][NAME_LENGTH], char value[][NAME_LENGTH], int n) /* subsitute "$name" with value corresponding to name */ { int i, j; char tmp[1000], str[256], uattr[256], *ps, *pt, *p; pt = tmp; ps = string; for (p = strchr(ps, '$') ; p != NULL ; p = strchr(ps, '$')) { /* copy leading characters */ j = (int)(p-ps); memcpy(pt, ps, j); pt += j; p++; /* extract name */ strcpy(str, p); for (j=0 ; j<(int)strlen(str) ; j++) str[j] = toupper(str[j]); /* search name */ for (i=0 ; i 0) { FD_ZERO(&readfds); FD_SET(sock, &readfds); timeout.tv_sec = millisec / 1000; timeout.tv_usec = (millisec % 1000) * 1000; select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout); if (!FD_ISSET(sock, &readfds)) break; } i = recv(sock, buffer+n, 1, 0); if (i<=0) break; n++; if (n >= buffer_size) break; } while (buffer[n-1] && buffer[n-1] != 10); return n-1; } INT sendmail(char *smtp_host, char *from, char *to, char *subject, char *text) { struct sockaddr_in bind_addr; struct hostent *phe; int s, offset; char buf[80]; char str[10000]; time_t now; struct tm *ts; if (verbose) printf("\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host); /* create a new socket for connecting to remote server */ s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) return -1; /* connect to remote node port 25 */ memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_port = htons((short) 25); phe = gethostbyname(smtp_host); if (phe == NULL) return -1; memcpy((char *)&(bind_addr.sin_addr), phe->h_addr, phe->h_length); if (connect(s, (void *) &bind_addr, sizeof(bind_addr)) < 0) { closesocket(s); return -1; } recv_string(s, str, sizeof(str), 10000); if (verbose) puts(str); /* drain server messages */ do { str[0] = 0; recv_string(s, str, sizeof(str), 300); if (verbose) puts(str); } while (str[0]); snprintf(str, sizeof(str) - 1, "HELO %s\r\n", host_name); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "MAIL FROM: <%s>\r\n", from); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "RCPT TO: <%s>\r\n", to); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "DATA\r\n"); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject); send(s, str, strlen(str), 0); if (verbose) puts(str); time(&now); ts = localtime(&now); strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S", ts); offset = (-(int)timezone); if (daylight) offset += 3600; snprintf(str, sizeof(str) - 1, "Date: %s %+03d%02d\r\n\r\n", buf, (int) (offset/3600), (int) ((abs((int)offset)/60) % 60)); send(s, str, strlen(str), 0); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "%s\r\n.\r\n", text); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); snprintf(str, sizeof(str) - 1, "QUIT\r\n"); send(s, str, strlen(str), 0); if (verbose) puts(str); recv_string(s, str, sizeof(str), 3000); if (verbose) puts(str); closesocket(s); return 1; } /*-------------------------------------------------------------------*/ INT ss_daemon_init() { #ifdef OS_UNIX /* only implemented for UNIX */ int i, fd, pid; if ( (pid = fork()) < 0) return 0; else if (pid != 0) exit(0); /* parent finished */ /* child continues here */ /* try and use up stdin, stdout and stderr, so other routines writing to stdout etc won't cause havoc. Copied from smbd */ for (i=0 ; i<3 ; i++) { close(i); fd = open("/dev/null", O_RDWR, 0); if (fd < 0) fd = open("/dev/null", O_WRONLY, 0); if (fd < 0) { printf("Can't open /dev/null"); return 0; } if (fd != i) { printf("Did not get file descriptor"); return 0; } } setsid(); /* become session leader */ chdir("/"); /* change working direcotry (not on NFS!) */ umask(0); /* clear our file mode creation mask */ #endif return SUCCESS; } /*------------------------------------------------------------------*/ /* Parameter extraction from configuration file similar to win.ini */ char *cfgbuffer; int getcfg(char *group, char *param, char *value) { char str[10000], *p, *pstr; int length; int fh; value[0] = 0; /* read configuration file on init */ if (!cfgbuffer) { fh = open(cfg_file, O_RDONLY | O_BINARY); if (fh < 0) return 0; length = lseek(fh, 0, SEEK_END); lseek(fh, 0, SEEK_SET); cfgbuffer = malloc(length+1); if (cfgbuffer == NULL) { close(fh); return 0; } read(fh, cfgbuffer, length); cfgbuffer[length] = 0; close(fh); } /* search group */ p = cfgbuffer; do { if (*p == '[') { p++; pstr = str; while (*p && *p != ']' && *p != '\n') *pstr++ = *p++; *pstr = 0; if (equal_ustring(str, group)) { /* search parameter */ p = strchr(p, '\n'); if (p) p++; while (p && *p && *p != '[') { pstr = str; while (*p && *p != '=' && *p != '\n') *pstr++ = *p++; *pstr-- = 0; while (pstr > str && (*pstr == ' ' || *pstr == '=' || *pstr == '\t')) *pstr-- = 0; if (equal_ustring(str, param)) { if (*p == '=') { p++; while (*p == ' ' || *p == '\t') p++; pstr = str; while (*p && *p != '\n' && *p != '\r') *pstr++ = *p++; *pstr-- = 0; while (*pstr == ' ' || *pstr == '\t') *pstr-- = 0; strcpy(value, str); return 1; } } if (p) p = strchr(p, '\n'); if (p) p++; } } } if (p) p = strchr(p, '\n'); if (p) p++; } while (p); /* if parameter not found in logbook, look in [global] section */ if (!equal_ustring(group, "global")) return getcfg("global", param, value); return 0; } /*------------------------------------------------------------------*/ int enumcfg(char *group, char *param, char *value, int index) { char str[10000], *p, *pstr; int i; /* open configuration file */ if (!cfgbuffer) getcfg("dummy", "dummy", str); if (!cfgbuffer) return 0; /* search group */ p = cfgbuffer; do { if (*p == '[') { p++; pstr = str; while (*p && *p != ']' && *p != '\n' && *p != '\r') *pstr++ = *p++; *pstr = 0; if (equal_ustring(str, group)) { /* enumerate parameters */ i = 0; p = strchr(p, '\n'); if (p) p++; while (p && *p && *p != '[') { pstr = str; while (*p && *p != '=' && *p != '\n' && *p != '\r') *pstr++ = *p++; *pstr-- = 0; while (pstr > str && (*pstr == ' ' || *pstr == '=')) *pstr-- = 0; if (i == index) { strcpy(param, str); if (*p == '=') { p++; while (*p == ' ') p++; pstr = str; while (*p && *p != '\n' && *p != '\r') *pstr++ = *p++; *pstr-- = 0; while (*pstr == ' ') *pstr-- = 0; if (value) strcpy(value, str); } return 1; } if (p) p = strchr(p, '\n'); if (p) p++; i++; } } } if (p) p = strchr(p, '\n'); if (p) p++; } while (p); return 0; } /*------------------------------------------------------------------*/ int enumgrp(int index, char *group) { char str[10000], *p, *pstr; int i; /* open configuration file */ if (!cfgbuffer) getcfg("dummy", "dummy", str); if (!cfgbuffer) return 0; /* search group */ p = cfgbuffer; i = 0; do { if (*p == '[') { p++; pstr = str; while (*p && *p != ']' && *p != '\n' && *p != '\r') *pstr++ = *p++; *pstr = 0; if (i == index) { strcpy(group, str); return 1; } i++; } while (*p && *p != '\r' && *p != '\n') p++; while (*p && (*p == '\r' || *p == '\n')) p++; } while (*p); return 0; } /*-------------------------------------------------------------------*/ char *locbuffer = NULL; char **porig, **ptrans; /* localization support */ char *loc(char *orig) { char language[256], file_name[256], *p; int fh, length, n; static char old_language[256]; getcfg("global", "Language", language); if (!equal_ustring(language, old_language)) { if (equal_ustring(language, "english") || language[0] == 0) { if (locbuffer) { free(locbuffer); locbuffer = NULL; } } else { strcpy(file_name, cfg_dir); strcat(file_name, "eloglang."); strcat(file_name, language); fh = open(file_name, O_RDONLY | O_BINARY); if (fh < 0) return orig; length = lseek(fh, 0, SEEK_END); lseek(fh, 0, SEEK_SET); locbuffer = malloc(length+1); if (locbuffer == NULL) { close(fh); return orig; } read(fh, locbuffer, length); locbuffer[length] = 0; close(fh); /* scan lines, setup orig-translated pointers */ p = locbuffer; n = 0; do { while (*p && (*p == '\r' || *p == '\n')) p++; if (*p && (*p == ';' || *p == '#' || *p == ' ' || *p == '\t')) { while (*p && *p != '\n' && *p != '\r') p++; continue; } if (n == 0) { porig = malloc(sizeof(char *) * 2); ptrans = malloc(sizeof(char *) * 2); } else { porig = realloc(porig, sizeof(char *) * (n + 2)); ptrans = realloc(ptrans, sizeof(char *) * (n + 2)); } porig[n] = p; while (*p && (*p != '=' && *p != '\r' && *p != '\n')) p++; if (*p && *p != '=') continue; ptrans[n] = p + 1; while (*ptrans[n] == ' ') ptrans[n] ++; /* remove '=' and surrounding blanks */ while (*p == '=' || *p == ' ') *p-- = 0; p = ptrans[n]; while (*p && *p != '\n' && *p != '\r') p++; if (p) *p++ = 0; n++; } while (p && *p); porig[n] = NULL; } strcpy(old_language, language); } if (!locbuffer) return orig; /* search string and return translation */ for (n = 0; porig[n] ; n++) if (strcmp(orig, porig[n]) == 0) { if (*ptrans[n]) return ptrans[n]; return orig; } return orig; } /*------------------------------------------------------------------*/ /* Parameter extraction from themes file */ typedef struct { char name[32]; char value[256]; } THEME; THEME default_theme [] = { { "Table width", "100%" }, { "Frame color", "#486090" }, { "Cell BGColor", "#E6E6E6" }, { "Border width", "0" }, { "Title BGColor", "#486090" }, { "Title Fontcolor", "#FFFFFF" }, { "Title Cellpadding", "0" }, { "Title Image", "" }, { "Title Image URL", "" }, { "Merge menus", "1" }, { "Use buttons", "0" }, { "Menu1 BGColor", "#E0E0E0" }, { "Menu1 Align", "left" }, { "Menu1 Cellpadding", "0" }, { "Menu2 BGColor", "#FFFFB0" }, { "Menu2 Align", "center" }, { "Menu2 Cellpadding", "0" }, { "Menu2 use images", "0" }, { "Categories cellpadding", "3" }, { "Categories border", "0" }, { "Categories BGColor1", "#CCCCFF" }, { "Categories BGColor2", "#DDEEBB" }, { "Text BGColor", "#FFFFFF" }, { "List bgcolor1", "#DDEEBB" }, { "List bgcolor2", "#FFFFB0" }, { "BGImage", "" }, { "BGTImage", "" }, { "" } }; THEME *theme = NULL; char theme_name[80]; /*------------------------------------------------------------------*/ void loadtheme(char *tn) { FILE *f; char *p, line[256], item[256], value[256], file_name[256]; int i; if (theme == NULL) theme = malloc(sizeof(default_theme)); /* copy default theme */ memcpy(theme, default_theme, sizeof(default_theme)); /* use default if no name is given */ if (tn == NULL) return; memset(file_name, 0, sizeof(file_name)); strcpy(file_name, cfg_dir); strcat(file_name, "themes"); strcat(file_name, DIR_SEPARATOR_STR); strcat(file_name, tn); strcat(file_name, DIR_SEPARATOR_STR); strcat(file_name, "theme.cfg"); f = fopen(file_name, "r"); if (f == NULL) return; strcpy(theme_name, tn); do { line[0] = 0; fgets(line, sizeof(line), f); /* ignore comments */ if (line[0] == ';' || line[0] == '#') continue; if (strchr(line, '=')) { /* split line into item and value, strop blanks */ strcpy(item, line); p = strchr(item, '='); while ((*p == '=' || *p == ' ') && p > item) *p-- = 0; p = strchr(line, '='); while (*p && (*p == '=' || *p == ' ')) p++; strcpy(value, p); if (strlen(value) > 0) { p = value+strlen(value)-1; while (p >= value && (*p == ' ' || *p == '\r' || *p == '\n')) *(p--) = 0; } /* find field in _theme and set it */ for (i=0 ; theme[i].name[0] ; i++) if (equal_ustring(item, theme[i].name)) { strcpy(theme[i].value, value); break; } } } while (!feof(f)); fclose(f); return; } /*------------------------------------------------------------------*/ /* get a certain theme attribute from currently loaded file */ char *gt(char *name) { int i; if (theme == NULL) loadtheme(NULL); for (i=0 ; theme[i].name[0] ; i++) if (equal_ustring(theme[i].name, name)) return theme[i].value; return ""; } /*------------------------------------------------------------------*/ 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 (equal_ustring(afilename[index], loc(""))) { strcpy(afile_name[index], loc("")); } else 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 ; i")))) { /* delete old attachment */ strcpy(str, data_dir); strcat(str, p); remove(str); } if (afile_name[i][0] && !equal_ustring(afile_name[i], loc(""))) { if (n == 0) { sprintf(message+strlen(message), "Attachment: %s", afile_name[i]); n++; } else sprintf(message+strlen(message), ",%s", afile_name[i]); } else if (p && !equal_ustring(afile_name[i], loc(""))) { if (n == 0) { sprintf(message+strlen(message), "Attachment: %s", p); n++; } else sprintf(message+strlen(message), ",%s", p); } } } else { sprintf(message+strlen(message), "Attachment: %s", afile_name[0]); for (i=1 ; 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_retrieve(char *tag, char *date, char attr_list[MAX_N_ATTR][NAME_LENGTH], char attrib[MAX_N_ATTR][NAME_LENGTH], int n_attr, char *text, int *textsize, char *orig_tag, char *reply_tag, char attachment[MAX_ATTACHMENTS][256], char *encoding) /********************************************************************\ Routine: el_retrieve Purpose: Retrieve an ELog entry by its message tab Input: char *tag tag in the form YYMMDD.offset int *size Size of text buffer Output: char *tag tag of retrieved message char *date Date/time of message recording char attr_list Names of attributes char attrib Values of attributes int n_attr Number of attributes char *text Message text char *orig_tag Original message if this one is a reply char *reply_tag Reply for current message char *attachment[] File attachments char *encoding Encoding of message int *size Actual message text size 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], *p; char message[TEXT_SIZE+1000], thread[256], attachment_all[64*MAX_ATTACHMENTS]; 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); /* decode message */ el_decode(message, "Date: ", date); el_decode(message, "Thread: ", thread); for (i=0 ; i \r conversion (e.g. zipping/unzipping) */ if (p == NULL) p = strstr(message, "========================================\r"); if (text != NULL) { if (p != NULL) { p += 41; if ((int) strlen(p) >= *textsize) { strncpy(text, p, *textsize-1); text[*textsize-1] = 0; show_error("Message too long to display. Please increase TEXT_SIZE and recompile elogd."); return EL_FILE_ERROR; } else { strcpy(text, p); /* strip end tag */ if (strstr(text, "$End$")) *strstr(text, "$End$") = 0; *textsize = strlen(text); } } else { text[0] = 0; *textsize = 0; } } if (search_status == EL_LAST_MSG) return EL_LAST_MSG; return EL_SUCCESS; } /*------------------------------------------------------------------*/ INT el_delete_message(char *tag) /********************************************************************\ Routine: el_delete_message Purpose: Delete an ELog entry including attachments Input: char *tag Message tage Output: Function value: EL_SUCCESS Successful completion \********************************************************************/ { INT i, n, size, fh, offset, tail_size, status, n_attr; char dir[256], str[256], file_name[256]; char *buffer, attrib[MAX_N_ATTR][NAME_LENGTH]; char date[80], text[TEXT_SIZE], orig_tag[80], reply_tag[80], attachment[MAX_ATTACHMENTS][256], encoding[80]; n_attr = scan_attributes(logbook); /* get attachments */ size = sizeof(text); status = el_retrieve(tag, date, attr_list, attrib, n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); if (status != SUCCESS) return EL_FILE_ERROR; for (i=0 ; i 0) { buffer = malloc(tail_size); if (buffer == NULL) { close(fh); return EL_FILE_ERROR; } lseek(fh, offset+size, SEEK_SET); n = read(fh, buffer, tail_size); } lseek(fh, offset, SEEK_SET); if (tail_size > 0) { n = write(fh, buffer, tail_size); free(buffer); } /* truncate file here */ #ifdef OS_WINNT chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif /* if file length gets zero, delete file */ tail_size = lseek(fh, 0, SEEK_END); close(fh); if (tail_size == 0) remove(file_name); return EL_SUCCESS; } /*------------------------------------------------------------------*/ INT el_delete_message_only(char *tag, char afilename[MAX_ATTACHMENTS][256]) /********************************************************************\ Routine: el_delete_message_only Purpose: Delete an ELog entry, but keeping (and returning) attachments Input: char *tag Message tage Output: Function value: EL_SUCCESS Successful completion \********************************************************************/ { INT i, n, size, fh, offset, tail_size, status, n_attr; char dir[256], str[256], file_name[256]; char *buffer, attrib[MAX_N_ATTR][NAME_LENGTH]; char date[80], text[TEXT_SIZE], orig_tag[80], reply_tag[80], attachment[MAX_ATTACHMENTS][256], encoding[80]; n_attr = scan_attributes(logbook); /* get attachments */ size = sizeof(text); status = el_retrieve(tag, date, attr_list, attrib, n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); if (status != SUCCESS) return EL_FILE_ERROR; for (i=0 ; i 0) { buffer = malloc(tail_size); if (buffer == NULL) { close(fh); return EL_FILE_ERROR; } lseek(fh, offset+size, SEEK_SET); n = read(fh, buffer, tail_size); } lseek(fh, offset, SEEK_SET); if (tail_size > 0) { n = write(fh, buffer, tail_size); free(buffer); } /* truncate file here */ #ifdef OS_WINNT chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif /* if file length gets zero, delete file */ tail_size = lseek(fh, 0, SEEK_END); close(fh); if (tail_size == 0) remove(file_name); return EL_SUCCESS; } /*------------------------------------------------------------------*/ void logf(const char *format, ...) { char fname[2000]; va_list argptr; char str[10000]; FILE* f; time_t now; char buf[256]; if (!getcfg("global", "logfile", fname)) return; va_start(argptr, format); vsprintf(str, (char *) format, argptr); va_end(argptr); f=fopen(fname,"a"); if (!f) return; now=time(0); strftime(buf, sizeof(buf), "%d-%b-%Y %H:%M:%S", localtime(&now)); fprintf(f,"%s: %s",buf,str); if (str[strlen(str)-1] != '\n') fprintf(f,"\n"); fclose(f); } /*------------------------------------------------------------------*/ void rsputs(const char *str) { if (strlen_retbuf + strlen(str) > sizeof(return_buffer)) strcpy(return_buffer, "

Error: return buffer too small

"); else strcpy(return_buffer+strlen_retbuf, str); strlen_retbuf += strlen(str); } /*------------------------------------------------------------------*/ void rsputs2(const char *str) { int i, j, k; char *p, link[256]; if (strlen_retbuf + strlen(str) > sizeof(return_buffer)) strcpy(return_buffer, "

Error: return buffer too small

"); else { j = strlen_retbuf; for (i=0 ; i<(int)strlen(str) ; i++) { if (strncmp(str+i, "http://", 7) == 0) { p = (char *) (str+i+7); i += 7; for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++) link[k] = *p++; link[k] = 0; i--; sprintf(return_buffer+j, "http://%s", link, link); j += strlen(return_buffer+j); } else if (strncmp(str+i, "https://", 8) == 0) { p = (char *) (str+i+8); i += 8; for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++) link[k] = *p++; link[k] = 0; i--; sprintf(return_buffer+j, "https://%s", link, link); j += strlen(return_buffer+j); } else if (strncmp(str+i, "ftp://", 6) == 0) { p = (char *) (str+i+6); i += 6; for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++) link[k] = *p++; link[k] = 0; i--; sprintf(return_buffer+j, "ftp://%s", link, link); j += strlen(return_buffer+j); } else if (strncmp(str+i, "mailto:", 7) == 0) { p = (char *) (str+i+7); i += 7; for (k=0 ; *p && *p != '>' && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++) link[k] = *p++; link[k] = 0; i--; sprintf(return_buffer+j, "%s", link, link); j += strlen(return_buffer+j); } else switch (str[i]) { case '<': strcat(return_buffer, "<"); j+=4; break; case '>': strcat(return_buffer, ">"); j+=4; break; /* the translation for the search highliting */ case '\001' : strcat(return_buffer, "<"); j++; break; case '\002' : strcat(return_buffer, ">"); j++; break; case '\003' : strcat(return_buffer, "\""); j++; break; case '\004' : strcat(return_buffer, " "); j++; break; default: return_buffer[j++] = str[i]; } } return_buffer[j] = 0; strlen_retbuf = j; } } /*------------------------------------------------------------------*/ void rsprintf(const char *format, ...) { va_list argptr; char str[10000]; va_start(argptr, format); vsprintf(str, (char *) format, argptr); va_end(argptr); if (strlen_retbuf + strlen(str) > sizeof(return_buffer)) strcpy(return_buffer, "

Error: return buffer too small

"); else strcpy(return_buffer+strlen_retbuf, str); strlen_retbuf += strlen(str); } /*------------------------------------------------------------------*/ /* Parameter handling functions similar to setenv/getenv */ void initparam() { memset(_param, 0, sizeof(_param)); memset(_value, 0, sizeof(_value)); _text[0] = 0; } int setparam(char *param, char *value) { int i; char str[256]; if (equal_ustring(param, "text")) { if (strlen(value) >= TEXT_SIZE) { sprintf(str, "Error: Message text too big (%d bytes). Please increase TEXT_SIZE and recompile elogd\n", strlen(value)); show_error(str); return 0; } strncpy(_text, value, TEXT_SIZE); _text[TEXT_SIZE-1] = 0; return 1; } for (i=0 ; i= VALUE_SIZE) { show_error("Error: Parameter value too big. Please increase VALUE_SIZE and recompile elogd\n"); return 0; } strncpy(_value[i], value, VALUE_SIZE); _value[i][VALUE_SIZE-1] = 0; } else { printf("Error: parameter array too small\n"); } return 1; } char *getparam(char *param) { int i; if (equal_ustring(param, "text")) return _text; for (i=0 ; iredir\r\n", path); } void redirect2(char *path) { redirect(path); send(_sock, return_buffer, strlen(return_buffer)+1, 0); closesocket(_sock); return_length = -1; } void redirect3(char *path) { /* redirect */ rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } rsprintf("Location: %s\r\n\r\nredir\r\n", path); } /*------------------------------------------------------------------*/ int strbreak(char *str, char list[][NAME_LENGTH], int size) /* break comma-separated list into char array, stripping leading and trailing blanks */ { int i; char *p; memset(list, 0, size*NAME_LENGTH); p = strtok(str, ","); if (!p) return 0; while (*p == ' ') p++; for (i=0 ; p && i\n"); rsprintf("ELOG Electronic Logbook Upgrade Information\n"); rsprintf("\n\n"); rsprintf("\n"); rsprintf("", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); rsprintf("\n", gt("Title bgcolor"), gt("Title fontcolor")); rsprintf("\n"); rsprintf("
ELog Electronic Logbook Upgrade Information

\n"); rsprintf("You probably use an elogd.cfg configuration file for a ELOG version\n"); rsprintf("1.1.x, since it contains a \"Types = ...\" entry. From version\n"); rsprintf("1.2.0 on, the fixed attributes Type and Category have been\n"); rsprintf("replaced by arbitrary attributes. Please replace these two lines with the\n"); rsprintf("following entries:

\n"); rsprintf("

\n");
  rsprintf("Attributes = Author, Type, Category, Subject\n");
  rsprintf("Required Attributes = Author\n");
  getcfg(logbook, "Types", str);
  rsprintf("Options Type = %s\n", str);
  getcfg(logbook, "Categories", str);
  rsprintf("Options Category = %s\n", str);
  rsprintf("Page title = $subject\n");
  rsprintf("
\n"); rsprintf("

\n"); rsprintf("It is of course possible to change the attributes or add new ones. The new\n"); rsprintf("options in the configuration file are described under http://midas.psi.ch/elog/config.html\n"); rsprintf(".\n"); rsprintf("

\n\n"); rsprintf("
\n"); rsprintf("
\n"); rsprintf("S. Ritt, 18 October 2001"); rsprintf("
"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_standard_header(char *title, char *path) { rsprintf("HTTP/1.1 200 Document follows\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); rsprintf("Content-Type: text/html\r\n"); rsprintf("Pragma: no-cache\r\n"); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } rsprintf("Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n\r\n"); rsprintf("%s\n", title); if (*gt("BGImage")) rsprintf("\n", gt("BGImage")); else rsprintf("\n"); if (path) rsprintf("
\n\n", path); else rsprintf("\n\n"); } /*------------------------------------------------------------------*/ void show_standard_title(char *logbook, char *text, int printable) { char str[256], ref[256]; int i; /* overall table, containing title, menu and message body */ if (printable) rsprintf("\n\n", gt("Border width"), gt("Frame color")); else rsprintf("
\n\n", gt("Table width"), gt("Border width"), gt("Frame color")); /*---- logbook selection row ----*/ if (!printable && getcfg("global", "logbook tabs", str) && atoi(str) == 1) { if (!getcfg("global", "tab cellpadding", str)) strcpy(str, "5"); rsprintf("\n\n"); } /*---- title row ----*/ rsprintf("\n\n"); } /*------------------------------------------------------------------*/ void show_error(char *error) { /* header */ show_standard_header("ELOG error", ""); rsprintf("

\n", str); if (getcfg("global", "main tab", str)) { rsprintf("\n", str); rsprintf("\n"); } for (i=0 ; ; i++) { if (!enumgrp(i, str)) break; if (equal_ustring(str, "global")) continue; strcpy(ref, str); url_encode(ref); if (equal_ustring(str, logbook)) rsprintf("\n", gt("Title BGColor"), gt("Title fontcolor"), str); else rsprintf("\n", ref, str); rsprintf("\n"); } rsprintf("\n"); rsprintf("
%s %s%s  
\n", gt("Title cellpadding")); /* left cell */ rsprintf("\n"); /* middle cell */ if (*getparam("full_name")) { rsprintf("\n", gt("Title fontcolor"), loc("Logged in as"), getparam("full_name")); } /* right cell */ rsprintf("\n"); rsprintf("
", gt("Title BGColor")); /* use comment as title if available, else logbook name */ if (!getcfg(logbook, "Comment", str)) strcpy(str, logbook); rsprintf("  %s%s\n", gt("Title fontcolor"), str, text); rsprintf(" ", gt("Title BGColor")); rsprintf("  %s \"%s\"", gt("Title BGColor")); if (*gt("Title image URL")) rsprintf("\n", gt("Title image URL")); if (*gt("Title image")) rsprintf("", gt("Title image")); else rsprintf("ELOG V%s  ", gt("Title fontcolor"), VERSION); if (*gt("Title image URL")) rsprintf("\n"); rsprintf("
", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); rsprintf("\n", error); rsprintf("\n
"); rsprintf("%s
", gt("Cell BGColor")); /* rsprintf("\n"); rsprintf("\n"); */ rsprintf("
\n"); rsprintf("\n"); } /*------------------------------------------------------------------*/ void send_file(char *file_name) { int fh, i, length; char str[256]; time_t now; struct tm *gmt; fh = open(file_name, O_RDONLY | O_BINARY); if (fh > 0) { lseek(fh, 0, SEEK_END); length = TELL(fh); lseek(fh, 0, SEEK_SET); rsprintf("HTTP/1.1 200 Document follows\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); rsprintf("Accept-Ranges: bytes\r\n"); time(&now); now += (int) (3600*3); gmt = gmtime(&now); strftime(str, sizeof(str), "%A, %d-%b-%y %H:%M:%S GMT", gmt); rsprintf("Expires: %s\r\n", str); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* return proper header for file type */ for (i=0 ; i<(int)strlen(file_name) ; i++) str[i] = toupper(file_name[i]); str[i] = 0; for (i=0 ; filetype[i].ext[0] ; i++) if (strstr(str, filetype[i].ext)) break; if (filetype[i].ext[0]) rsprintf("Content-Type: %s\r\n", filetype[i].type); else if (strchr(str, '.') == NULL) rsprintf("Content-Type: text/plain\r\n"); else rsprintf("Content-Type: application/octet-stream\r\n"); rsprintf("Content-Length: %d\r\n\r\n", length); /* return if file too big */ if (length > (int) (sizeof(return_buffer) - strlen(return_buffer))) { printf("return buffer too small\n"); close(fh); return; } return_length = strlen(return_buffer)+length; read(fh, return_buffer+strlen(return_buffer), length); close(fh); } else { rsprintf("HTTP/1.1 404 Not Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); rsprintf("Connection: close\r\n"); rsprintf("Content-Type: text/html\r\n\r\n"); rsprintf("404 Not Found\r\n"); rsprintf("

Not Found

\r\n"); rsprintf("The requested file %s was not found on this server

\r\n", file_name); rsprintf("


ELOG version %s
\r\n\r\n", VERSION); return_length = strlen_retbuf; keep_alive = 0; } } /*------------------------------------------------------------------*/ void strencode(char *text) { int i; for (i=0 ; i<(int) strlen(text) ; i++) { switch (text[i]) { case '\n': rsprintf("
\n"); break; case '<': rsprintf("<"); break; case '>': rsprintf(">"); break; case '&': rsprintf("&"); break; case '\"': rsprintf("""); break; case ' ': rsprintf(" "); break; /* the translation for the search highliting */ case '\001': rsprintf("<"); break; case '\002': rsprintf(">"); break; case '\003': rsprintf("\""); break; case '\004': rsprintf(" "); break; default: rsprintf("%c", text[i]); } } } /*------------------------------------------------------------------*/ void strencode2(char *b, char *text) { int i; for (i=0 ; i<(int) strlen(text) ; b++,i++) { switch (text[i]) { case '\n': sprintf(b, "
\n"); break; case '<': sprintf(b, "<"); break; case '>': sprintf(b, ">"); break; case '&': sprintf(b, "&"); break; case '\"': sprintf(b, """); break; default: sprintf(b, "%c", text[i]); } } *b = 0; } /*------------------------------------------------------------------*/ int build_subst_list(char list[][NAME_LENGTH], char value[][NAME_LENGTH], char attrib[][NAME_LENGTH]) { int i; char str[256], format[256]; time_t now; struct tm *ts; struct hostent *phe; /* copy attribute list */ for (i=0 ; ih_name); else strcpy(str, (char *)inet_ntoa(rem_addr)); strcpy(value[i++], str); /* add local host */ strcpy(list[i], "host"); strcpy(value[i++], host_name); /* add user names */ strcpy(list[i], "short_name"); strcpy(value[i++], getparam("unm")); strcpy(list[i], "long_name"); strcpy(value[i++], getparam("full_name")); /* add logbook */ strcpy(list[i], "logbook"); strcpy(value[i++], logbook); /* add date */ strcpy(list[i], "date"); time(&now); ts = localtime(&now); if (getcfg(logbook, "Date format", format)) strftime(str, sizeof(str), format, ts); else strcpy(str, ctime(&now)); strcpy(value[i++], str); return i; } /*------------------------------------------------------------------*/ void show_change_pwd_page() { char str[256], file_name[256], line[256], *p, *pl, old_pwd[32], new_pwd[32]; char *buf; FILE *f; int i, wrong_pwd, size; double exp; time_t now; struct tm *gmt; do_crypt(getparam("oldpwd"), old_pwd); do_crypt(getparam("newpwd"), new_pwd); getcfg(logbook, "Password file", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } wrong_pwd = FALSE; if (old_pwd[0] || new_pwd[0]) { f = fopen(file_name, "r+b"); if (f != NULL) { fseek(f, 0, SEEK_END); size = TELL(fileno(f)); fseek(f, 0, SEEK_SET); buf = malloc(size+1); fread(buf, 1, size, f); buf[size] = 0; pl = buf; while (pl < buf+size) { for (i=0 ; pl[i] && pl[i] != '\r' && pl[i] != '\n' ; i++) line[i] = pl[i]; line[i] = 0; if (line[0] == ';' || line[0] == '#' || line[0] == 0) { pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; continue; } strcpy(str, line); if (strchr(str, ':')) *strchr(str, ':') = 0; if (strcmp(str, getparam("unm")) == 0) break; pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; } /* if user found, check old password */ if (*getparam("unm") && (strcmp(str, getparam("unm")) == 0)) { p = line+strlen(str); if (*p) p++; strcpy(str, p); if (strchr(str, ':')) *strchr(str, ':') = 0; if (strcmp(old_pwd, str) != 0) wrong_pwd = TRUE; } /* replace password */ if (!wrong_pwd) { fseek(f, 0, SEEK_SET); fwrite(buf, 1, pl-buf, f); fprintf(f, "%s:%s:%s\n", getparam("unm"), new_pwd, getparam("full_name")); pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; fwrite(pl, 1, strlen(pl), f); #ifdef _MSC_VER chsize(fileno(f), TELL(fileno(f))); #else ftruncate(fileno(f), TELL(fileno(f))); #endif } free(buf); fclose(f); if (!wrong_pwd) { rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* get optional expriation from configuration file */ exp = 0; if (getcfg(logbook, "Login expiration", str)) exp = atof(str); if (exp == 0) { if (getcfg("global", "Password file", str)) rsprintf("Set-Cookie: upwd=%s; path=/\r\n", new_pwd); else rsprintf("Set-Cookie: upwd=%s\r\n", new_pwd); } else { time(&now); now += (int) (3600*exp); gmt = gmtime(&now); strftime(str, sizeof(str), "%A, %d-%b-%Y %H:%M:%S GMT", gmt); if (getcfg("global", "Password file", str)) rsprintf("Set-Cookie: upwd=%s; path=/; expires=%s\r\n", new_pwd, str); else rsprintf("Set-Cookie: upwd=%s; expires=%s\r\n", new_pwd, str); } rsprintf("Location: .\r\n\r\nredir\r\n"); return; } } } show_standard_header(loc("ELOG change password"), NULL); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); if (wrong_pwd) rsprintf("\n", loc("Wrong password")); rsprintf("\n", gt("Title fontcolor"), loc("Change password for user"), getparam("full_name")); rsprintf("\n", gt("Cell BGColor"), loc("Old Password")); rsprintf("\n", gt("Cell BGColor"), loc("New Password")); rsprintf("", gt("Cell BGColor"), loc("Submit")); rsprintf("
%s!
\n", gt("Title bgcolor")); rsprintf("%s \"%s\"
%s:     
%s:     
\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ BOOL allow_user(char *command) { char str[1000], users[2000]; char list[MAX_N_LIST][NAME_LENGTH]; int i, n; /* check for user level access */ if (!getcfg(logbook, "Password file", str)) return TRUE; /* allow by default */ sprintf(str, "Allow %s", command); if (!getcfg(logbook, str, users)) return TRUE; /* check if current user in list */ n = strbreak(users, list, MAX_N_LIST); for (i=0 ; i%s\" is not allowed for user \"%s\""), command, getparam("full_name")); show_error(str); return FALSE; } /*------------------------------------------------------------------*/ int get_last_index(int index) { int i, n_attr; char str[80], date[80], attrib[MAX_N_ATTR][NAME_LENGTH], orig_tag[80], reply_tag[80], att[MAX_ATTACHMENTS][256], encoding[80]; str[0] = 0; n_attr = scan_attributes(logbook); el_retrieve(str, date, attr_list, attrib, n_attr, NULL, 0, orig_tag, reply_tag, att, encoding); strcpy(str, attrib[index]); /* look for first digit, return value */ for (i=0 ; i<(int)strlen(str) ; i++) if (isdigit(str[i])) break; return atoi(str+i); } /*------------------------------------------------------------------*/ void show_elog_new(char *path, BOOL bedit) { int i, n, n_attr, index, size, width, fh, length; char str[1000], preset[1000], *p, star[80], comment[10000]; char list[MAX_N_ATTR][NAME_LENGTH], file_name[256], *buffer, format[256]; char date[80], attrib[MAX_N_ATTR][NAME_LENGTH], text[TEXT_SIZE], orig_tag[80], reply_tag[80], att[MAX_ATTACHMENTS][256], encoding[80], slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; time_t now; n_attr = scan_attributes(logbook); for (i=0 ; i%s can edit this entry"), attrib[i]); show_error(str); return; } } if (strstr(preset, "$long_name")) { if (strstr(attrib[i], getparam("full_name")) == NULL) { sprintf(str, loc("Only user %s can edit this entry"), attrib[i]); show_error(str); return; } } } } } /* remove attributes for replies */ if (path && !bedit) { getcfg(logbook, "Remove on reply", str); strbreak(str, list, MAX_N_ATTR); for (i=0 ; iELOG\n"); rsprintf("\n"); /*---- title row ----*/ show_standard_title(logbook, "", 0); /*---- menu buttons ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", loc("Submit")); rsprintf("\n", loc("Back")); rsprintf("
\n\n"); /*---- entry form ----*/ /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); /* print required message if one of the attributes has it set */ for (i= 0 ; i < n_attr ; i++) { if (attr_flags[i] & AF_REQUIRED) { rsprintf("\n", gt("Categories bgcolor1"), loc("Fields marked with"), loc("are required")); break; } } time(&now); if (bedit) { if (getcfg(logbook, "Date format", format)) { struct tm ts; memset(&ts, 0, sizeof(ts)); for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; ts.tm_mon = i; ts.tm_mday = atoi(date+8); ts.tm_hour = atoi(date+11); ts.tm_min = atoi(date+14); ts.tm_sec = atoi(date+17); ts.tm_year = atoi(date+20)-1900; mktime(&ts); strftime(str, sizeof(str), format, &ts); } else strcpy(str, date); rsprintf("\n\n", gt("Categories bgcolor1"), loc("Entry date"), gt("Categories bgcolor2"), str); } else { if (getcfg(logbook, "Date format", format)) strftime(str, sizeof(str), format, localtime(&now)); else strcpy(str, ctime(&now)); rsprintf("\n\n", gt("Categories bgcolor1"), loc("Entry date"), gt("Categories bgcolor2"), str); } /* display attributes */ for (index = 0 ; index < n_attr ; index++) { strcpy(star, (attr_flags[index] & AF_REQUIRED) ? "*" : ""); /* check for preset string */ sprintf(str, "Preset %s", attr_list[index]); if (getcfg(logbook, str, preset)) { if (!bedit || (attr_flags[index] & AF_FIXED) == 0) { i = build_subst_list(slist, svalue, NULL); strsubst(preset, slist, svalue, i); /* check for index substitution */ if (!bedit && strchr(preset, '%')) { /* get index */ i = get_last_index(index); strcpy(str, preset); sprintf(preset, str, i+1); } if (!strchr(preset, '%')) strcpy(attrib[index], preset); } } /* display text box */ rsprintf("", gt("Categories bgcolor1"), attr_list[index], star); /* if attribute cannot be changed, just display text */ if ((attr_flags[index] & AF_LOCKED) || (bedit && (attr_flags[index] & AF_FIXED))) { rsprintf("\n", attr_list[index], attrib[index]); } else { if (attr_options[index][0][0] == 0) { rsprintf("\n", gt("Categories bgcolor2"), NAME_LENGTH, attr_list[index], attrib[index]); } else { if (equal_ustring(attr_options[index][0], "boolean")) { /* display checkbox */ rsprintf("\n"); } else if (attr_flags[index] & AF_ICON) { /* display icons */ rsprintf("\n"); } else { /* display drop-down box */ rsprintf("\n"); } } } } } if (path) { /* hidden text for original message */ rsprintf("\n", path); if (bedit) rsprintf("\n"); } rsprintf("\n"); /* set textarea width */ width = 76; if (getcfg(logbook, "Message width", str)) width = atoi(str); /* increased wrapping width for replies (leave space for '> ' */ if (path && !bedit) width += 2; rsprintf("\n"); if (getcfg(logbook, "Number attachments", str)) n = atoi(str); else n = 5; if (n > MAX_ATTACHMENTS) n = MAX_ATTACHMENTS; if (n > 0) { if (bedit) { rsprintf("\n", loc("To delete an old attachment, enter <delete> in the new attachment field")); for (i=0 ; i", gt("Categories bgcolor1"), loc("Original attachment"), i+1, loc("New attachment"), i+1); rsprintf("\n", i+1); } else rsprintf("\n", gt("Categories bgcolor1"), loc("Attachment"), i+1, gt("Categories bgcolor2"), i+1); } } else { /* attachment */ for (i=0 ; i\n", gt("Categories bgcolor1"), loc("Attachment"), i+1, gt("Categories bgcolor2"), i+1); } } rsprintf("
%s * %s
%s:%s
%s:%s
%s%s:%s\n", gt("Categories bgcolor2"), attrib[index]); if (attr_flags[index] & AF_MULTI) { for (i=0 ; i\n", str, attr_options[index][i]); } } else if (attr_flags[index] & AF_ICON) { for (i=0 ; i\n", str, attr_options[index][i]); } } else rsprintf("
\n", gt("Categories bgcolor2"), attr_list[index]); } else { if (attr_flags[index] & AF_MULTI) { /* display multiple check boxes */ rsprintf("\n", gt("Categories bgcolor2")); for (i=0 ; i%s \n", str, attr_options[index][i], attr_options[index][i]); else rsprintf("%s \n", str, attr_options[index][i], attr_options[index][i]); } rsprintf("
\n", gt("Categories bgcolor2")); for (i=0 ; i", attr_list[index], attr_options[index][i]); else rsprintf("", attr_list[index], attr_options[index][i]); rsprintf(" \n", attr_options[index][i]); } rsprintf("
\n"); if (getcfg(logbook, "Message comment", comment) && !bedit && !path) { rsputs(comment); rsputs("
\n"); } if (!getcfg(logbook, "Show text", str) || atoi(str) == 1) { rsprintf("
\n"); /* HTML check box */ if (path) { if (encoding[0] == 'H') rsprintf("%s\n", loc("Submit as HTML text")); else rsprintf("%s\n", loc("Submit as HTML text")); } else { if (getcfg(logbook, "HTML default", str)) { if (atoi(str) == 0) { rsprintf("%s\n", loc("Submit as HTML text")); } else if (atoi(str) == 1) { rsprintf("%s\n", loc("Submit as HTML text")); } } else rsprintf("%s\n", loc("Submit as HTML text")); } } /* Suppress check box */ if (getcfg(logbook, "Suppress default", str)) { if (atoi(str) == 0) { rsprintf("        \n"); rsprintf("%s>\n", loc("Suppress Email notification")); } else if (atoi(str) == 1) { rsprintf("        \n"); rsprintf("%s\n", loc("Suppress Email notification")); } } else { rsprintf("        \n"); rsprintf("%s\n", loc("Suppress Email notification")); } if (bedit) { /* Resubmit check box */ if (getcfg(logbook, "Resubmit default", str)) { if (atoi(str) == 0) { rsprintf("        \n"); rsprintf("%s\n", loc("Resubmit as new entry")); } else if (atoi(str) == 1) { rsprintf("        \n"); rsprintf("%s\n", loc("Resubmit as new entry")); } } else { rsprintf("        \n"); rsprintf("%s\n", loc("Resubmit as new entry")); } } rsprintf("
%s.
\n", gt("Categories bgcolor1"), loc("If no attachments are resubmitted, the original ones are kept")); rsprintf("%s.
%s %d:
%s %d:
%s
", gt("Categories bgcolor2"), att[i]+14); rsprintf("
%s %d:
%s %d:
\n"); /*---- menu buttons again ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", loc("Submit")); rsprintf("\n", loc("Back")); rsprintf("
\n\n"); rsprintf("\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_elog_find() { int i, j, n_attr; char str[256]; n_attr = scan_attributes(logbook); /*---- header ----*/ show_standard_header(loc("ELOG find"), NULL); /*---- title ----*/ show_standard_title(logbook, "", 0); /*---- menu buttons ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", loc("Search")); rsprintf("\n", loc("Reset Form")); rsprintf("\n", loc("Back")); rsprintf("
\n\n"); /*---- entry form ----*/ /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); if (!getcfg(logbook, "Show text", str) || atoi(str) == 1) { rsprintf("\n"); } rsprintf("\n", loc("Show attachments")); rsprintf("\n", loc("Printable output")); rsprintf("\n", loc("Sort in reverse order")); /* count logbooks */ for (i=0 ; ; i++) { if (!enumgrp(i, str)) break; if (equal_ustring(str, "global")) continue; } if (i > 2) { if (!getcfg(logbook, "Search all logbooks", str) || atoi(str) == 1) { rsprintf("\n", loc("Search all logbooks")); } } rsprintf("", gt("Categories bgcolor1"), loc("Start date")); rsprintf("\n"); rsprintf("", gt("Categories bgcolor1"), loc("End date")); rsprintf("\n"); rsprintf("\n"); for (i=0 ; i", gt("Categories bgcolor1"), attr_list[i]); rsprintf("\n"); } if (!getcfg(logbook, "Show text", str) || atoi(str) == 1) { rsprintf("", gt("Categories bgcolor1"), loc("Text")); rsprintf("\n", loc("(case insensitive substring)")); } rsprintf("
", gt("Categories bgcolor2")); if (getcfg(logbook, "Summary on default", str) && atoi(str) == 1) rsprintf("%s\n", loc("Summary only")); else rsprintf("%s\n", loc("Summary only")); rsprintf("
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); rsprintf("%s
%s:\n"); rsprintf("\n"); rsprintf(" %s: ", loc("Year")); rsprintf("
%s:\n"); rsprintf("\n"); rsprintf(" %s: ", loc("Year")); rsprintf("
%s:", gt("Categories bgcolor2")); if (attr_options[i][0][0] == 0) { rsprintf("\n", attr_list[i]); rsprintf("%s\n", loc("(case insensitive substring)")); } else { if (equal_ustring(attr_options[i][0], "boolean")) rsprintf("\n", attr_list[i]); /* display image for icon */ else if (attr_flags[i] & AF_ICON) { for (j=0 ; j", attr_list[i], attr_options[i][j]); rsprintf(" \n", attr_options[i][j]); } } else { rsprintf("\n"); } } rsprintf("
%s:\n", gt("Categories bgcolor2")); rsprintf("%s
\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_config_page() { int fh, length; char *buffer; /*---- header ----*/ rsprintf("HTTP/1.1 200 Document follows\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } rsprintf("Content-Type: text/html\r\n\r\n"); rsprintf("ELOG config\n"); rsprintf("\n"); /*---- title ----*/ show_standard_title(logbook, "", 0); /*---- menu buttons ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", loc("Save")); rsprintf("\n", loc("Cancel")); rsprintf("
\n\n"); /*---- entry form ----*/ /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); rsprintf("
", gt("Categories bgcolor2")); fh = open(cfg_file, O_RDONLY | O_BINARY); if (fh < 0) { rsprintf("Cannot read configuration file \"%s\"", cfg_file); rsprintf("
\n"); rsprintf("\r\n"); return; } length = lseek(fh, 0, SEEK_END); lseek(fh, 0, SEEK_SET); buffer = malloc(length+1); if (buffer == NULL) { close(fh); rsprintf("Error: out of memory

"); rsprintf("\n"); rsprintf("\r\n"); return; } read(fh, buffer, length); buffer[length] = 0; close(fh); rsprintf("
\n"); rsprintf("\n"); /*---- menu buttons ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", loc("Save")); rsprintf("\n", loc("Cancel")); rsprintf("
\n\n"); rsprintf("\n\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ int save_config() { int fh, i; char str[80]; fh = open(cfg_file, O_RDWR | O_BINARY | O_TRUNC, 644); if (fh < 0) { sprintf(str, "%s: %s", loc("Cannot open file %s"), cfg_file, strerror(errno)); show_error(str); return 0; } i = write(fh, _text, strlen(_text)); if (i < (int)strlen(_text)) { sprintf(str, "%s: %s", loc("Cannot write to %s"), cfg_file, strerror(errno)); show_error(str); close(fh); return 0; } close(fh); return 1; } /*------------------------------------------------------------------*/ void show_elog_delete(char *path) { int status; char str[256]; /* redirect if confirm = NO */ if (getparam("confirm") && *getparam("confirm") && strcmp(getparam("confirm"), loc("No")) == 0) { sprintf(str, "%s", path); redirect(str); return; } /* header */ sprintf(str, "%s", path); show_standard_header("Delete ELog entry", str); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); if (getparam("confirm") && *getparam("confirm")) { if (strcmp(getparam("confirm"), loc("Yes")) == 0) { /* delete message */ status = el_delete_message(path); rsprintf("\n", loc("Message successfully deleted")); else rsprintf("%s = %d\n", loc("Error deleting message: status"), status); rsprintf("\n", loc("Last")); rsprintf("\n", gt("Cell BGColor"), loc("Goto last message")); } } else { /* define hidden field for command */ rsprintf("\n", loc("Delete")); rsprintf("\n", gt("Title fontcolor"), loc("Are you sure to delete this message?")); rsprintf("\n", gt("Cell BGColor"), path); rsprintf("\n\n"); } rsprintf("
"); if (status == EL_SUCCESS) rsprintf("%s
", gt("Title bgcolor")); rsprintf("%s
%s
\n", gt("Cell BGColor"), loc("Yes")); rsprintf("\n", loc("No")); rsprintf("
\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_elog_submit_find(INT past_n, INT last_n) { int i, j, n, size, status, d1, m1, y1, d2, m2, y2, index, colspan, i_line, n_line, i_col; int current_year, current_month, current_day, printable, n_logbook, lindex, n_attr, reverse, n_attr_disp, n_found, search_all; char date[80], attrib[MAX_N_ATTR][NAME_LENGTH], disp_attr[MAX_N_ATTR][NAME_LENGTH], list[10000], text[TEXT_SIZE], text1[TEXT_SIZE], text2[TEXT_SIZE], orig_tag[80], reply_tag[80], attachment[MAX_ATTACHMENTS][256], encoding[80]; char str[256], tag[256], ref[256], file_name[256], col[80], old_data_dir[256]; char logbook_list[100][256], lb_enc[256], *nowrap, format[80]; char menu_str[1000], menu_item[MAX_N_LIST][NAME_LENGTH]; char *p , *pt, *pt1, *pt2; BOOL full, show_attachments; time_t ltime, ltime_start, ltime_end, ltime_current, now; struct tm tms, *ptms; FILE *f; n_attr = scan_attributes(logbook); printable = atoi(getparam("Printable")); if (*getparam("Reverse")) reverse = atoi(getparam("Reverse")); else { reverse = 0; if (getcfg(logbook, "Reverse sort", str)) reverse = atoi(str); } /*---- header ----*/ show_standard_header(loc("ELOG search result"), NULL); /*---- title ----*/ strcpy(str, ", "); if (past_n == 1) strcat(str, loc("Last day")); else if (past_n > 1) sprintf(str+strlen(str), loc("Last %d days"), past_n); else if (last_n) sprintf(str+strlen(str), loc("Last %d entries"), last_n); if (printable) show_standard_title(logbook, str, 1); else show_standard_title(logbook, str, 0); /* get mode */ if (past_n || last_n) { if (getcfg(logbook, "Summary on default", str)) full = !atoi(str); else full = TRUE; show_attachments = FALSE; } else { full = !(*getparam("mode")); show_attachments = (*getparam("attach") > 0); } time(&now); ptms = localtime(&now); current_year = ptms->tm_year+1900; current_month = ptms->tm_mon+1; current_day = ptms->tm_mday; /*---- menu buttons ----*/ if (!printable) { rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); if (getcfg(logbook, "Find menu commands", menu_str)) { n = strbreak(menu_str, menu_item, MAX_N_LIST); if (atoi(gt("Use buttons")) == 1) { for (i=0 ; i\n", str); } if (last_n) { sprintf(str, loc("Last %d entries"), last_n*2); rsprintf("\n", str); } } else rsprintf("\n", loc(menu_item[i])); } } else { rsprintf("\n"); for (i=0 ; i%s |\n", past_n*2, str); } if (last_n) { sprintf(str, loc("Last %d entries"), last_n*2); rsprintf(" %s |\n", last_n*2, str); } } else { strcpy(str, loc(menu_item[i])); url_encode(str); if (i < n-1) rsprintf(" %s |\n", str, loc(menu_item[i])); else rsprintf(" %s \n", str, loc(menu_item[i])); } } rsprintf("\n"); } } else { if (atoi(gt("Use buttons")) == 1) { if (past_n) { sprintf(str, loc("Last %d days"), past_n*2); rsprintf("\n", str); } if (last_n) { sprintf(str, loc("Last %d entries"), last_n*2); rsprintf("\n", str); } rsprintf("\n", loc("Find")); rsprintf("\n", loc("Back")); } else { rsprintf("\n"); if (past_n) { sprintf(str, loc("Last %d days"), past_n*2); rsprintf(" %s |\n", past_n*2, str); } if (last_n) { sprintf(str, loc("Last %d entries"), last_n*2); rsprintf(" %s |\n", last_n*2, str); } rsprintf(" %s |\n", loc("Find"), loc("Find")); rsprintf(" %s \n", loc("Back"), loc("Back")); rsprintf("\n"); } } rsprintf("
\n\n"); } /*---- convert end date to ltime ----*/ ltime_end = ltime_start = 0; if (!past_n && !last_n) { if (*getparam("m1") || *getparam("y1") || *getparam("d1")) { /* if year not given, use current year */ if (!*getparam("y1")) y1 = current_year; else y1 = atoi(getparam("y1")); if (y1 < 1990 || y1 > current_year) { rsprintf("\r\n"); rsprintf("

Error: year %s out of range

", getparam("y1")); rsprintf("\r\n"); return; } /* if month not given, use current month */ if (*getparam("m1")) { strcpy(str, getparam("m1")); for (m1=0 ; m1<12 ; m1++) if (equal_ustring(str, mname[m1])) break; if (m1 == 12) m1 = 0; m1++; } else m1 = current_month; /* if day not given, use 1 */ if (*getparam("d1")) d1 = atoi(getparam("d1")); else d1 = 1; memset(&tms, 0, sizeof(struct tm)); tms.tm_year = y1 % 100; tms.tm_mon = m1-1; tms.tm_mday = d1; tms.tm_hour = 0; if (tms.tm_year < 90) tms.tm_year += 100; ltime_start = mktime(&tms); } if (*getparam("m2") || *getparam("y2") || *getparam("d2")) { /* if year not give, use current year */ if (*getparam("y2")) y2 = atoi(getparam("y2")); else y2 = current_year; if (y2 < 1990 || y2 > current_year) { rsprintf("\r\n"); rsprintf("

Error: year %d out of range

", y2); rsprintf("\r\n"); return; } /* if month not given, use current month */ if (*getparam("m2")) { strcpy(str, getparam("m2")); for (m2=0 ; m2<12 ; m2++) if (equal_ustring(str, mname[m2])) break; if (m2 == 12) m2 = 0; m2++; } else m2 = current_month; /* if day not given, use last day of month */ if (*getparam("d2")) d2 = atoi(getparam("d2")); else { memset(&tms, 0, sizeof(struct tm)); tms.tm_year = y2 % 100; tms.tm_mon = m2-1+1; tms.tm_mday = 1; tms.tm_hour = 12; if (tms.tm_year < 90) tms.tm_year += 100; ltime = mktime(&tms); ltime -= 3600*24; memcpy(&tms, localtime(<ime), sizeof(struct tm)); d2 = tms.tm_mday; } memset(&tms, 0, sizeof(struct tm)); tms.tm_year = y2 % 100; tms.tm_mon = m2-1; tms.tm_mday = d2; tms.tm_hour = 0; tms.tm_min = 0; tms.tm_sec = 0; if (tms.tm_year < 90) tms.tm_year += 100; ltime_end = mktime(&tms); /* end time is first second of next day */ ltime_end += 3600*24; memcpy(&tms, localtime(<ime_end), sizeof(struct tm)); y2 = tms.tm_year + 1900; m2 = tms.tm_mon +1; d2 = tms.tm_mday; } } if (ltime_start && ltime_end && ltime_start > ltime_end) { rsprintf("\r\n"); rsprintf("

Error: start time after end time

", y2); rsprintf("\r\n"); return; } /*---- display filters ----*/ rsprintf("\n", printable ? "1" : gt("Border width"), gt("Categories cellpadding")); if (*getparam("m1") || *getparam("y1") || *getparam("d1")) rsprintf("", gt("Categories bgcolor1"), loc("Start date"), gt("Categories bgcolor2"), mname[m1-1], d1, y1); if (*getparam("m2") || *getparam("y2") || *getparam("d2")) { /* calculate previous day */ memset(&tms, 0, sizeof(struct tm)); tms.tm_year = y2 % 100; tms.tm_mon = m2-1; tms.tm_mday = d2; tms.tm_hour = 12; if (tms.tm_year < 90) tms.tm_year += 100; ltime = mktime(&tms); ltime -= 3600*24; memcpy(&tms, localtime(<ime), sizeof(struct tm)); rsprintf("", gt("Categories bgcolor1"), loc("End date"), gt("Categories bgcolor2"), mname[tms.tm_mon], tms.tm_mday, tms.tm_year + 1900); } for (i=0 ; i", gt("Categories bgcolor1"), attr_list[i], gt("Categories bgcolor2"), getparam(attr_list[i])); } if (*getparam("subtext")) { rsprintf("", gt("Categories bgcolor1"), loc("Text")); rsprintf("", gt("Categories bgcolor2"), getparam("subtext")); } rsprintf("
%s:%s %d, %d
%s:%s %d, %d
%s:%s
%s:%s
\n\n"); /* get number of summary lines */ n_line = 3; if (getcfg(logbook, "Summary lines", str)) n_line = atoi(str); /* check for search all */ search_all = atoi(getparam("all")); if (getcfg(logbook, "Search all logbooks", str) && atoi(str) == 0) search_all = 0; /*---- table titles ----*/ rsprintf("\n", printable ? "1" : gt("Border width"), gt("Categories cellpadding"), gt("Frame color")); strcpy(col, gt("Categories bgcolor1")); rsprintf("\n"); size = printable ? 2 : 3; rsprintf("", col, size); if (search_all) rsprintf("", col, size); rsprintf("", col, size); if (getcfg(logbook, "Display search", list)) n_attr_disp = strbreak(list, disp_attr, MAX_N_ATTR); else { n_attr_disp = n_attr; memcpy(disp_attr, attr_list, sizeof(attr_list)); } for (i=0 ; i%s", col, size, attr_list[i]); } if (!full && n_line > 0) rsprintf("", col, size); rsprintf("\n\n"); /*---- do find ----*/ i_col = 0; n_found = 0; old_data_dir[0] = 0; if (search_all) { /* count logbooks */ for (i=n_logbook=0 ; ; i++) { if (!enumgrp(i, str)) break; if (equal_ustring(str, "global")) continue; strcpy(logbook_list[n_logbook++], str); } strcpy(old_data_dir, data_dir); } else { strcpy(logbook_list[0], logbook); n_logbook = 1; } /* loop through all logbooks */ for (lindex=0 ; lindex 1) { /* set data_dir from logbook */ getcfg(logbook_list[lindex], "Data dir", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(data_dir, str); else { strcpy(data_dir, cfg_dir); strcat(data_dir, str); } if (data_dir[strlen(data_dir)-1] != DIR_SEPARATOR) strcat(data_dir, DIR_SEPARATOR_STR); } if (past_n) { if (reverse) { strcpy(tag, "-1"); el_search_message(tag, NULL, TRUE, FALSE); time(&now); ltime_start = now-3600*24*past_n; } else { time(&now); ltime_start = now-3600*24*past_n; ptms = localtime(<ime_start); sprintf(tag, "%02d%02d%02d.0", ptms->tm_year % 100, ptms->tm_mon+1, ptms->tm_mday); } } else if (last_n) { strcpy(tag, "-1"); el_search_message(tag, NULL, TRUE, FALSE); if (!reverse) for (i=1 ; i 0) if (ltime_current < ltime_start) break; /* check for end date */ if (ltime_end > 0) { if (ltime_current > ltime_end) continue; } } else { /* check for start date */ if (ltime_start > 0) if (ltime_current < ltime_start) continue; /* check for end date */ if (ltime_end > 0) { if (ltime_current > ltime_end) break; } } if (status == EL_SUCCESS) { /* do filtering */ for (i=0 ; i"); pt2 += strlen(pt2); /* copy origial search text */ memcpy(pt2, pt, strlen(str)); pt2 += strlen(str); pt += strlen(str); /* add coloring 2nd part */ if (equal_ustring(encoding, "plain") || !full) strcpy(pt2, "\001/B\002"); else strcpy(pt2, ""); pt2 += strlen(pt2); } } while (p != NULL); strcpy(pt2, pt); strcpy(text, text2); } /* filter passed: display line */ n_found++; strcpy(str, tag); if (strchr(str, '+')) *strchr(str, '+') = 0; if (strchr(str, '-')) *strchr(str, '-') = 0; strcpy(lb_enc, logbook_list[lindex]); url_encode(lb_enc); sprintf(ref, "../%s/%s", lb_enc, str); if (full) { strcpy(col, gt("List bgcolor1")); rsprintf(""); size = printable ? 2 : 3; nowrap = printable ? "" : "nowrap"; rsprintf("", col, size, ref, n_found); if (search_all) rsprintf("", nowrap, col, size, logbook_list[lindex]); if (getcfg(logbook, "Date format", format)) { struct tm ts; memset(&ts, 0, sizeof(ts)); for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; ts.tm_mon = i; ts.tm_mday = atoi(date+8); ts.tm_hour = atoi(date+11); ts.tm_min = atoi(date+14); ts.tm_sec = atoi(date+17); ts.tm_year = atoi(date+20)-1900; mktime(&ts); strftime(str, sizeof(str), format, &ts); } else strcpy(str, date); rsprintf("", nowrap, col, size, str); for (i=0 ; i\n", col); else rsprintf("\n", col); } else if (attr_flags[i] & AF_ICON) { rsprintf(""); } else { rsprintf(""); } } rsprintf("\n"); if (search_all) colspan = 3+n_attr_disp; else colspan = 2+n_attr_disp; if (!getcfg(logbook, "Show text", str) || atoi(str) == 1) { rsprintf("\n"); } if (!show_attachments && attachment[0][0]) { rsprintf("", colspan, ref); } else { rsprintf("\n"); } } } } if (!show_attachments && attachment[0][0]) rsprintf("\n"); } else /* if (full) */ { if (i_col % 2 == 0) strcpy(col, gt("List bgcolor1")); else strcpy(col, gt("List bgcolor2")); i_col++; rsprintf(""); size = printable ? 2 : 3; nowrap = printable ? "" : "nowrap"; rsprintf("", col, size, ref, n_found); if (search_all) rsprintf("", nowrap, col, logbook_list[lindex]); if (getcfg(logbook, "Date format", format)) { struct tm ts; memset(&ts, 0, sizeof(ts)); for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; ts.tm_mon = i; ts.tm_mday = atoi(date+8); ts.tm_hour = atoi(date+11); ts.tm_min = atoi(date+14); ts.tm_sec = atoi(date+17); ts.tm_year = atoi(date+20)-1900; mktime(&ts); strftime(str, sizeof(str), format, &ts); } else strcpy(str, date); rsprintf("", nowrap, col, size, str); for (i=0 ; i\n", col); else rsprintf("\n", col); } else if (attr_flags[i] & AF_ICON) { rsprintf(""); } else rsprintf("", col, size, attrib[i]); } if (n_line > 0) { rsprintf("\n"); } rsprintf("\n"); } } /* stop after all found (needed for reverse search) */ if (last_n && n_found >= last_n) break; } while (status == EL_SUCCESS); } /* for () */ rsprintf("
#LogbookDateText
  %d  %s%s", col); if (attrib[i][0]) rsprintf("", attrib[i]); rsprintf(" ", col, size); rsputs2(attrib[i]); rsprintf(" 
", colspan, size); if (equal_ustring(encoding, "plain")) { rsputs("
");
              rsputs2(text);
              rsputs("
"); } else rsputs(text); rsprintf("
", colspan, size); if (attachment[1][0]) rsprintf("%s: ", loc("Attachments")); else rsprintf("%s: ", loc("Attachment")); } for (index = 0 ; index < MAX_ATTACHMENTS ; index++) { if (attachment[index][0]) { strcpy(str, attachment[index]); str[13] = 0; sprintf(ref, "../%s/%s/%s", logbook_list[lindex], str, attachment[index]+14); for (i=0 ; i<(int)strlen(attachment[index]) ; i++) str[i] = toupper(attachment[index][i]); str[i] = 0; if (!show_attachments) { rsprintf("%s     ", ref, attachment[index]+14); } else { if (strstr(str, ".GIF") || strstr(str, ".JPG") || strstr(str, ".JPEG") || strstr(str, ".PNG")) { rsprintf("
%s %d: %s\n", colspan, gt("List bgcolor2"), loc("Attachment"), index+1, ref, attachment[index]+14); if (show_attachments) rsprintf("
%s %d: %s\n", colspan, gt("List bgcolor2"), loc("Attachment"), index+1, ref, attachment[index]+14); if ((strstr(str, ".TXT") || strstr(str, ".ASC") || strchr(str, '.') == NULL) && show_attachments) { /* display attachment */ rsprintf("
", size);

                    strcpy(file_name, data_dir);

                    strcat(file_name, attachment[index]);

                    f = fopen(file_name, "rt");
                    if (f != NULL)
                      {
                      while (!feof(f))
                        {
                        str[0] = 0;
                        fgets(str, sizeof(str), f);
                        rsputs2(str);
                        }
                      fclose(f);
                      }

                    rsprintf("
\n"); } rsprintf("
  %d  %s%s", col); if (attrib[i][0]) rsprintf("", attrib[i]); rsprintf(" %s ", col, size); for (i=i_line=0 ; i
\n"); if (n_found == 0) { rsprintf("\n", printable ? "1" : gt("Border width"), gt("Categories cellpadding"), gt("Frame color")); rsprintf("", loc("No entries found")); rsprintf("
%s
\n"); } rsprintf("\n"); if (getcfg(logbook, "bottom text", str)) { FILE *f; char file_name[256], *buf; strcpy(file_name, cfg_dir); strcat(file_name, str); f = fopen(file_name, "r"); if (f != NULL) { fseek(f, 0, SEEK_END); size = TELL(fileno(f)); fseek(f, 0, SEEK_SET); buf = malloc(size+1); fread(buf, 1, size, f); buf[size] = 0; fclose(f); rsputs(buf); } } else /* add little logo */ rsprintf("
ELOG V%s
", VERSION); rsprintf("\r\n"); /* restor old data_dir */ if (old_data_dir[0]) strcpy(data_dir, old_data_dir); } /*------------------------------------------------------------------*/ void submit_elog() { char str[256], mail_to[256], mail_from[256], file_name[256], error[1000], mail_text[10000], mail_list[MAX_N_LIST][NAME_LENGTH], list[10000], smtp_host[256], tag[80], subject[256], attrib[MAX_N_ATTR][NAME_LENGTH], subst_str[256]; char *buffer[MAX_ATTACHMENTS], mail_param[1000]; char att_file[MAX_ATTACHMENTS][256]; char slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; int i, j, n, missing, first, index, n_attr, n_mail, suppress, status; n_attr = scan_attributes(logbook); /* check for required attributs */ missing = 0; for (i=0 ; i"); sprintf(error+strlen(error), loc("Error: Attribute %s not supplied"), attr_list[i]); sprintf(error+strlen(error), ".

\n"); sprintf(error+strlen(error), loc("Please go back and enter the %s field"), attr_list[i]); strcat(error, ".\n"); show_error(error); return; } /* check for valid attachment files */ for (i=0 ; i"))) { sprintf(error, loc("Error: Attachment file %s invalid, please bo back and enter a proper file name"), getparam(str)); show_error(error); return; } } /* compile substitution list */ n = build_subst_list(slist, svalue, NULL); /* retrieve attributes */ for (i=0 ; i"); strcat(str, loc("Please check that it exists and elogd has write access")); show_error(str); return; } suppress = atoi(getparam("suppress")); /* check for mail submissions */ mail_param[0] = 0; n_mail = 0; if (suppress) { strcpy(mail_param, "?suppress=1"); } else { for (index=0 ; index <= n_attr ; index++) { if (index < n_attr) { strcpy(str, "Email "); if (strchr(attr_list[index], ' ')) sprintf(str+strlen(str), "\"%s\"", attr_list[index]); else strcat(str, attr_list[index]); strcat(str, " "); if (strchr(getparam(attr_list[index]), ' ')) sprintf(str+strlen(str), "\"%s\"", getparam(attr_list[index])); else strcat(str, getparam(attr_list[index])); } else sprintf(str, "Email ALL"); if (getcfg(logbook, str, list)) { n = strbreak(list, mail_list, MAX_N_LIST); if (verbose) printf("\n%s to %s\n\n", str, list); if (!getcfg("global", "SMTP host", smtp_host)) if (!getcfg("global", "SMTP host", smtp_host)) { show_error(loc("No SMTP host defined in [global] section of configuration file")); return; } for (i=0 ; iredir\r\n", tag, mail_param); } /*------------------------------------------------------------------*/ void copy_to(char *src_path, char *dst_logbook, int move) { int size, i, status, fh, n_attr; char str[256], file_name[256], attrib[MAX_N_ATTR][NAME_LENGTH]; char date[80], text[TEXT_SIZE], old_data_dir[256], tag[32], orig_tag[80], reply_tag[80], attachment[MAX_ATTACHMENTS][256], encoding[80]; n_attr = scan_attributes(logbook); /* get message */ size = sizeof(text); status = el_retrieve(src_path, date, attr_list, attrib, n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); if (status != EL_SUCCESS) { sprintf(str, loc("Message %s cannot be read from logbook \"%s\""), src_path, logbook); show_error(str); return; } /* read attachments */ for (i=0 ; i 0) { lseek(fh, 0, SEEK_END); _attachment_size[i] = TELL(fh); lseek(fh, 0, SEEK_SET); _attachment_buffer[i] = malloc(_attachment_size[i]); if (_attachment_buffer[i]) read(fh, _attachment_buffer[i], _attachment_size[i]); close(fh); } /* stip date/time from file name */ strcpy(str, attachment[i]); strcpy(attachment[i], str+14); } /* switch to destination logbook data directory */ strcpy(old_data_dir, data_dir); getcfg(dst_logbook, "Data dir", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(data_dir, str); else { strcpy(data_dir, cfg_dir); strcat(data_dir, str); } if (data_dir[strlen(data_dir)-1] != DIR_SEPARATOR) strcat(data_dir, DIR_SEPARATOR_STR); tag[0] = 0; status = el_submit(attr_list, attrib, n_attr, text, orig_tag, encoding, attachment, _attachment_buffer, _attachment_size, tag, sizeof(tag)); for (i=0 ; i"); strcat(str, loc("Please check that it exists and elogd has write access")); show_error(str); return; } /* delete original message for move */ if (move) { el_delete_message(src_path); /* check if this was the last message */ size = sizeof(text); status = el_retrieve(src_path, date, attr_list, attrib, n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); /* if yes, force display of new last message */ if (status != EL_SUCCESS) src_path[0] = 0; } /* display status message */ show_standard_header(loc("Copy ELog entry"), src_path); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); rsprintf("\n"); rsprintf("\n", gt("Cell BGColor"), loc("Go to"), logbook, src_path, logbook); rsprintf("\n", gt("Cell BGColor"), loc("Go to"), dst_logbook, dst_logbook); rsprintf("
"); if (move) rsprintf(loc("Message moved successfully from \"%s\" to \"%s\""), logbook, dst_logbook); else rsprintf(loc("Message copied successfully from \"%s\" to \"%s\""), logbook, dst_logbook); rsprintf("
%s %s
%s %s
\n"); rsprintf("\r\n"); return; } /*------------------------------------------------------------------*/ void show_elog_page(char *logbook, char *path) { int size, i, j, len, n, msg_status, status, fh, length, first_message, last_message, index, n_attr; char str[256], orig_path[256], command[80], ref[256], file_name[256], attrib[MAX_N_ATTR][NAME_LENGTH]; char date[80], text[TEXT_SIZE], menu_str[1000], other_str[1000], cmd[256], orig_tag[80], reply_tag[80], attachment[MAX_ATTACHMENTS][256], encoding[80], att[256], lattr[256]; char menu_item[MAX_N_LIST][NAME_LENGTH], format[80], slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; FILE *f; n_attr = scan_attributes(logbook); if (getcfg(logbook, "Types", str)) { show_upgrade_page(); return; } /*---- interprete commands ---------------------------------------*/ strcpy(command, getparam("cmd")); /* correct for image buttons */ if (*getparam("cmd_first.x")) strcpy(command, loc("First")); if (*getparam("cmd_previous.x")) strcpy(command, loc("Previous")); if (*getparam("cmd_next.x")) strcpy(command, loc("Next")); if (*getparam("cmd_last.x")) strcpy(command, loc("Last")); /* check if command allowed for current user */ if (!allow_user(command)) return; /* get menu command */ getcfg(logbook, "Menu commands", menu_str); if (menu_str[0] == 0) { strcpy(menu_str, loc("New")); strcat(menu_str, ", "); strcat(menu_str, loc("Edit")); strcat(menu_str, ", "); strcat(menu_str, loc("Delete")); strcat(menu_str, ", "); strcat(menu_str, loc("Reply")); strcat(menu_str, ", "); strcat(menu_str, loc("Find")); strcat(menu_str, ", "); strcat(menu_str, loc("Last day")); strcat(menu_str, ", "); strcat(menu_str, loc("Last 10")); strcat(menu_str, ", "); strcat(menu_str, loc("Config")); strcat(menu_str, ", "); if (getcfg(logbook, "Password file", str)) { strcat(menu_str, loc("Change Password")); strcat(menu_str, ", "); strcat(menu_str, loc("Logout")); strcat(menu_str, ", "); } strcat(menu_str, loc("Help")); } else { /* localize menu commands */ n = strbreak(menu_str, menu_item, MAX_N_LIST); menu_str[0] = 0; for (i=0 ; i%s\" not allowed"), command); show_error(str); return; } if (equal_ustring(command, loc("Help"))) { if (getcfg(logbook, "Help URL", str)) { /* if file is given, add '/' to make absolute path */ if (strchr(str, '/') == NULL) sprintf(ref, "/%s", str); else strcpy(ref, str); redirect3(ref); return; } /* send local help file */ strcpy(file_name, cfg_dir); strcat(file_name, "eloghelp_"); if (getcfg("global", "Language", str)) { str[2] = 0; strcat(file_name, str); } else strcat(file_name, "en"); strcat(file_name, ".html"); f = fopen(file_name, "r"); if (f == NULL) redirect3("http://midas.psi.ch/elog/eloghelp_en.html"); else { fclose(f); send_file(file_name); } return; } if (equal_ustring(command, loc("New"))) { show_elog_new(NULL, FALSE); return; } if (equal_ustring(command, loc("Edit"))) { if (path[0]) { show_elog_new(path, TRUE); return; } } if (equal_ustring(command, loc("Reply"))) { show_elog_new(path, FALSE); return; } if (equal_ustring(command, loc("Submit")) || equal_ustring(command, "Submit")) { submit_elog(); return; } if (equal_ustring(command, loc("Find"))) { show_elog_find(); return; } if (equal_ustring(command, loc("Search"))) { show_elog_submit_find(0, 0); return; } if (equal_ustring(command, loc("Last day"))) { redirect("past1"); return; } if (equal_ustring(command, loc("Last 10"))) { redirect("last10"); return; } if (equal_ustring(command, loc("Copy to"))) { copy_to(path, getparam("destc"), 0); return; } if (equal_ustring(command, loc("Move to"))) { copy_to(path, getparam("destm"), 1); return; } if (equal_ustring(command, loc("Config"))) { show_config_page(); return; } if (equal_ustring(command, loc("Change Password")) || isparam("newpwd")) { show_change_pwd_page(); return; } if (equal_ustring(command, loc("Save"))) { if (!save_config()) return; redirect("."); return; } if (equal_ustring(command, loc("Logout"))) { rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* log activity */ logf("Logout of user \"%s\" from logbook \"%s\"",getparam("unm"),logbook); /* delete user cookies */ if (getcfg("global", "Password file", str)) { rsprintf("Set-Cookie: upwd=; path=/; expires=Fri, 01 Jan 1983 00:00:00 GMT\r\n"); rsprintf("Set-Cookie: unm=; path=/; expires=Fri, 01 Jan 1983 00:00:00 GMT\r\n"); } else { rsprintf("Set-Cookie: upwd=; expires=Fri, 01 Jan 1983 00:00:00 GMT\r\n"); rsprintf("Set-Cookie: unm=; expires=Fri, 01 Jan 1983 00:00:00 GMT\r\n"); } rsprintf("Location: ../\r\n\r\nredir\r\n"); return; } strcpy(str, getparam("last")); if (strchr(str, ' ')) { i = atoi(strchr(str, ' ')); sprintf(str, "last%d", i); redirect(str); return; } strcpy(str, getparam("past")); if (strchr(str, ' ')) { i = atoi(strchr(str, ' ')); sprintf(str, "past%d", i); redirect(str); return; } if (equal_ustring(command, loc("Delete"))) { show_elog_delete(path); return; } if (strncmp(path, "past", 4) == 0) { show_elog_submit_find(atoi(path+4), 0); return; } if (strncmp(path, "last", 4) == 0 && strstr(path, ".gif") == NULL) { show_elog_submit_find(0, atoi(path+4)); return; } if (equal_ustring(command, loc("Back")) && getcfg(logbook, "Back to main", str) && atoi(str) == 1) { redirect3("/"); return; } /*---- check if file requested -----------------------------------*/ if ((strlen(path) > 13 && path[6] == '_' && path[13] == '_') || (strlen(path) > 13 && path[6] == '_' && path[13] == '/') || strstr(path, ".gif") || strstr(path, ".jpg") || strstr(path, ".jpeg") || strstr(path, ".png")) { if ((strlen(path) > 13 && path[6] == '_' && path[13] == '_') || (strlen(path) > 13 && path[6] == '_' && path[13] == '/')) { if (path[13] == '/') path[13] = '_'; /* file from data directory requested */ strcpy(file_name, data_dir); strcat(file_name, path); } else { /* file from theme directory requested */ strcpy(file_name, cfg_dir); if (file_name[0]) strcat(file_name, DIR_SEPARATOR_STR); strcat(file_name, "themes"); strcat(file_name, DIR_SEPARATOR_STR); if (theme_name[0]) { strcat(file_name, theme_name); strcat(file_name, DIR_SEPARATOR_STR); } strcat(file_name, path); } send_file(file_name); return; } /*---- check next/previous message -------------------------------*/ last_message = first_message = FALSE; if (equal_ustring(command, loc("Next")) || equal_ustring(command, loc("Previous")) || equal_ustring(command, loc("Last")) || equal_ustring(command, loc("First"))) { strcpy(orig_path, path); if (equal_ustring(command, loc("Last")) || equal_ustring(command, loc("First"))) path[0] = 0; do { if (equal_ustring(command, loc("Next")) || equal_ustring(command, loc("First"))) strcat(path, "+1"); if (equal_ustring(command, loc("Previous")) || equal_ustring(command, loc("Last"))) strcat(path, "-1"); status = el_search_message(path, NULL, TRUE, equal_ustring(command, loc("First"))); if (status != EL_SUCCESS) { if (equal_ustring(command, loc("Next"))) last_message = TRUE; else first_message = TRUE; strcpy(path, orig_path); break; } size = sizeof(text); el_retrieve(path, date, attr_list, attrib, n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); /* check for locked attributes */ for (i=0 ; i\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("\n"); if (atoi(gt("Merge menus")) != 1) { rsprintf("\n"); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); n = strbreak(menu_str, menu_item, MAX_N_LIST); if (atoi(gt("Use buttons")) == 1) { for (i=0 ; i\n", cmd); if (equal_ustring(cmd, loc("Copy to")) || equal_ustring(cmd, loc("Move to"))) { /* put one link for each logbook except current one */ if (equal_ustring(cmd, loc("Copy to"))) rsprintf("\n"); for (j=0 ; ; j++) { if (!enumgrp(j, str)) break; if (equal_ustring(str, "global")) continue; if (equal_ustring(str, logbook)) continue; rsprintf("
\n\n"); } /*---- next/previous buttons ----*/ if (!getcfg(logbook, "Enable browsing", str) || atoi(str) == 1) { if (atoi(gt("Merge menus")) != 1) { rsprintf("\n", gt("Menu2 cellpadding"), gt("Frame color")); rsprintf("\n"); } rsprintf("
\n", gt("Menu2 Align"), gt("Menu2 BGColor")); } else rsprintf("\n", gt("Menu2 Align"), gt("Menu2 BGColor")); if (atoi(gt("Menu2 use images")) == 1) { rsprintf("\n", loc("First entry")); rsprintf("\n", loc("Previous entry")); rsprintf("\n", loc("Next entry")); rsprintf("\n", loc("Last entry")); } else { rsprintf("\n", loc("First")); rsprintf("\n", loc("Previous")); rsprintf("\n", loc("Next")); rsprintf("\n", loc("Last")); } rsprintf("
\n\n"); /*---- message ----*/ /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); if (msg_status == EL_FILE_ERROR || (msg_status != EL_SUCCESS && !last_message && !first_message)) rsprintf("\n", loc("No message available")); else { /* check for locked attributes */ for (i=0 ; i\"%s = %s\"", loc("with"), attr_list[i], getparam(attr_list[i])); else str[0] = 0; if (last_message) rsprintf("\n", loc("This is the last entry"), str); if (first_message) rsprintf("\n", loc("This is the first entry"), str); /* check for mail submissions */ if (*getparam("suppress")) { if (getcfg(logbook, "Suppress default", str) && atoi(str) == 1) rsprintf("\n", loc("Email notification suppressed")); else rsprintf("\n", loc("Email notification suppressed")); i = 1; } else { for (i=0 ; ; i++) { sprintf(str, "mail%d", i); if (*getparam(str)) { if (i==0) rsprintf("\n"); /*---- display date ----*/ if (getcfg(logbook, "Date format", format)) { struct tm ts; memset(&ts, 0, sizeof(ts)); for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; ts.tm_mon = i; ts.tm_mday = atoi(date+8); ts.tm_hour = atoi(date+11); ts.tm_min = atoi(date+14); ts.tm_sec = atoi(date+17); ts.tm_year = atoi(date+20)-1900; mktime(&ts); strftime(str, sizeof(str), format, &ts); rsprintf("\n\n"); /*---- link to original message or reply ----*/ if (msg_status != EL_FILE_ERROR && (reply_tag[0] || orig_tag[0])) { if (orig_tag[0]) { rsprintf("\n", ref, orig_tag); } if (reply_tag[0]) { rsprintf("\n", ref, reply_tag); } } /*---- display attributes ----*/ for (i=0 ; i\n", attr_list[i], gt("Categories bgcolor2")); else rsprintf("%s:\n", attr_list[i], gt("Categories bgcolor2")); } /* display image for icon */ else if (attr_flags[i] & AF_ICON) { rsprintf("%s:\n"); } else { rsprintf("%s:\n"); } } rsprintf("\n"); rsputs("

%s

%s %s
%s %s
%s
%s
"); rsprintf("%s %s
\n", loc("Mail sent to"), getparam(str)); } else break; } } if (i>0) rsprintf("
%s:%s\n\n", gt("Categories bgcolor1"), loc("Entry date"), gt("Categories bgcolor2"), str); } else rsprintf("
%s:%s\n\n", gt("Categories bgcolor1"), loc("Entry date"), gt("Categories bgcolor2"), date); for (i=0 ; i\n", attr_list[i], attrib[i]); /* browsing flag to distinguish "/../=" from browsing */ rsprintf("\n"); rsprintf("
", gt("Categories bgcolor1")); sprintf(ref, "%s", orig_tag); rsprintf("%s:", loc("In reply to"), gt("Menu2 bgcolor")); rsprintf("%s
", gt("Categories bgcolor1")); sprintf(ref, "%s", reply_tag); rsprintf("%s:", loc("Reply to this"), gt("Menu2 bgcolor")); rsprintf("%s
", gt("Categories bgcolor1")); if (!getcfg(logbook, "Filtered browsing", str) || atoi(str) == 1) { if (*getparam(lattr) == '1') rsprintf(" ", lattr); else rsprintf(" ", lattr); } /* display checkbox for boolean attributes */ if (equal_ustring(attr_options[i][0], "boolean")) { if (atoi(attrib[i]) == 1) rsprintf("%s:
\n", attr_list[i], gt("Categories bgcolor2")); if (attrib[i][0]) rsprintf("", attrib[i]); rsprintf(" 
\n", attr_list[i], gt("Categories bgcolor2")); rsputs2(attrib[i]); rsprintf(" 
\n"); /*---- message text ----*/ if (!getcfg(logbook, "Show text", str) || atoi(str) == 1) { rsprintf("\n", gt("Frame color")); if (*gt("BGTimage")) rsprintf("\n"); rsputs("
\n", gt("BGTimage"), gt("Text BGColor")); else rsprintf("
\n", gt("Text BGColor")); if (equal_ustring(encoding, "plain")) { rsputs("
");
        rsputs2(text);
        rsputs("
"); } else rsputs(text); rsputs("
\n"); } for (index = 0 ; index < MAX_ATTACHMENTS ; index++) { if (attachment[index][0]) { for (i=0 ; i<(int)strlen(attachment[index]) ; i++) att[i] = toupper(attachment[index][i]); att[i] = 0; /* determine size of attachment */ strcpy(file_name, data_dir); strcat(file_name, attachment[index]); length = 0; fh = open(file_name, O_RDONLY | O_BINARY); if (fh > 0) { lseek(fh, 0, SEEK_END); length = TELL(fh); close(fh); } strcpy(str, attachment[index]); str[13] = 0; sprintf(ref, "%s/%s", str, attachment[index]+14); rsprintf("\n", gt("Frame color")); rsprintf("", gt("Categories bgcolor1"), loc("Attachment"), index+1); rsprintf("
 %s %d: %s\n", gt("Categories bgcolor2"), ref, attachment[index]+14); if (length < 1024) rsprintf(" %d Bytes", length); else if (length < 1024*1024) rsprintf(" %d kB", length/1024); else rsprintf(" %1.3lf MB", length/1024.0/1024.0); rsprintf("
\n"); if (!getcfg(logbook, "Show attachments", str) || atoi(str) == 1) { if (strstr(att, ".GIF") || strstr(att, ".JPG") || strstr(att, ".JPEG") || strstr(att, ".PNG")) { rsprintf("\n", gt("Frame color")); rsprintf("", ref); rsprintf("
", gt("Text bgcolor")); rsprintf("
\n\n"); } else { if (strstr(att, ".TXT") || strstr(att, ".ASC") || strchr(att, '.') == NULL) { /* display attachment */ rsprintf("\n", gt("Frame color")); rsprintf("
", gt("Text bgcolor")); if (!strstr(att, ".HTML")) rsprintf("
");

              strcpy(file_name, data_dir);
              strcat(file_name, attachment[index]);

              f = fopen(file_name, "rt");
              if (f != NULL)
                {
                while (!feof(f))
                  {
                  str[0] = 0;
                  fgets(str, sizeof(str), f);

                  if (!strstr(att, ".HTML"))
                    rsputs2(str);
                  else
                    rsputs(str);
                  }
                fclose(f);
                }

              if (!strstr(att, ".HTML"))
                rsprintf("
"); rsprintf("\n"); rsprintf("
\n"); } } } } } } /* table for message body */ rsprintf("\n\n"); /* overall table */ rsprintf("\n"); if (getcfg(logbook, "bottom text", str)) { FILE *f; char file_name[256], *buf; strcpy(file_name, cfg_dir); strcat(file_name, str); f = fopen(file_name, "r"); if (f != NULL) { fseek(f, 0, SEEK_END); size = TELL(fileno(f)); fseek(f, 0, SEEK_SET); buf = malloc(size+1); fread(buf, 1, size, f); buf[size] = 0; fclose(f); rsputs(buf); } } else /* add little logo */ rsprintf("

ELOG V%s
", VERSION); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ BOOL check_password(char *logbook, char *name, char *password, char *redir) { char str[256]; /* get password from configuration file */ if (getcfg(logbook, name, str)) { if (strcmp(password, str) == 0) return TRUE; /* show web password page */ show_standard_header(loc("ELOG password"), NULL); /* define hidden fields for current destination */ if (redir[0]) rsprintf("\n", redir); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); if (password[0]) rsprintf("\n", loc("Wrong password")); rsprintf("\n", gt("Title fontcolor"), loc("Please enter password to obtain write access")); rsprintf("\n", gt("Cell BGColor")); } else { rsprintf("%s\n", gt("Title fontcolor"), loc("Please enter password to obtain administration access")); rsprintf("\n", gt("Cell BGColor")); } rsprintf("", gt("Cell BGColor"), loc("Submit")); rsprintf("
%s!
\n", gt("Title bgcolor")); if (strcmp(name, "Write password") == 0) { rsprintf("%s
\n"); rsprintf("\r\n"); return FALSE; } else return TRUE; } /*------------------------------------------------------------------*/ BOOL check_user_password(char *logbook, char *user, char *password, char *redir) { char str[256], line[256], file_name[256], *p; FILE *f; getcfg(logbook, "Password file", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } f = fopen(file_name, "r"); if (f != NULL) { while (!feof(f)) { line[0] = 0; fgets(line, sizeof(line), f); if (line[0] == ';' || line[0] == '#' || line[0] == 0) continue; strcpy(str, line); if (strchr(str, ':')) *strchr(str, ':') = 0; if (strcmp(str, user) == 0) break; } fclose(f); /* if user found, check password */ if (user[0] && (strcmp(str, user) == 0)) { p = line+strlen(str); if (*p) p++; strcpy(str, p); if (strchr(str, ':')) *strchr(str, ':') = 0; if (strcmp(password, str) == 0) { p += strlen(str); if (*p) p++; strcpy(str, p); if (strchr(str, ':')) *strchr(str, ':') = 0; if (strchr(str, '\r')) *strchr(str, '\r') = 0; if (strchr(str, '\n')) *strchr(str, '\n') = 0; setparam("full_name", str); return TRUE; } } /* show login password page */ show_standard_header("ELOG login", NULL); /* define hidden fields for current destination */ if (redir[0]) rsprintf("\n", redir); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); if (password[0]) rsprintf("\n", loc("Wrong password")); rsprintf("\n", gt("Title fontcolor"), loc("Please login")); rsprintf("\n", gt("Cell BGColor"), loc("Username")); rsprintf("\n", gt("Cell BGColor"), loc("Password")); rsprintf("", gt("Cell BGColor"), loc("Submit")); rsprintf("
%s!
\n", gt("Title bgcolor")); rsprintf("%s
%s:   
%s:   
\n"); rsprintf("\r\n"); return FALSE; } else { sprintf(line, "Error: Password file \"%s\" not found", file_name); show_error(line); return FALSE; } } /*------------------------------------------------------------------*/ void show_selection_page() { int i; char str[10000], logbook[256]; rsprintf("HTTP/1.1 200 Document follows\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } rsprintf("Content-Type: text/html\r\n\r\n"); rsprintf("\n"); rsprintf("\n"); if (getcfg("global", "Page Title", str)) { rsprintf(""); rsputs(str); rsprintf("\n"); } else rsprintf("ELOG Logbook Selection\n"); rsprintf("\n\n"); rsprintf("\n\n"); rsprintf("

"); rsprintf("
\n"); rsprintf("\n", loc("Please select the one to connect to")); } for (i=0 ; ; i++) { if (!enumgrp(i, logbook)) break; if (equal_ustring(logbook, "global")) continue; strcpy(str, logbook); url_encode(str); rsprintf("", str, logbook); str[0] = 0; getcfg(logbook, "Comment", str); rsprintf("\n", str); } rsprintf("
\n"); if (getcfg("global", "Welcome title", str)) { rsputs(str); } else { rsprintf("\n"); rsprintf("%s.
\n", loc("Several logbooks are defined on this host")); rsprintf("%s:
%s%s 
\n"); rsprintf("\r\n\r\n"); } /*------------------------------------------------------------------*/ void get_password(char *password) { static char last_password[32]; if (strncmp(password, "set=", 4) == 0) strcpy(last_password, password+4); else strcpy(password, last_password); } /*------------------------------------------------------------------*/ void interprete(char *path) /********************************************************************\ Routine: interprete Purpose: Interprete parametersand generate HTML output. Input: char *path Message path _param/_value array accessible via getparam() \********************************************************************/ { int i, n, index; double exp; char str[256], enc_pwd[80], file_name[256]; char enc_path[256], dec_path[256]; char *experiment, *command, *value, *group; time_t now; struct tm *gmt; /* encode path for further usage */ strcpy(dec_path, path); url_decode(dec_path); url_decode(dec_path); /* necessary for %2520 -> %20 -> ' ' */ strcpy(enc_path, dec_path); url_encode(enc_path); experiment = getparam("exp"); command = getparam("cmd"); value = getparam("value"); group = getparam("group"); index = atoi(getparam("index")); /* if experiment given, use it as logbook (for elog!) */ if (experiment && experiment[0]) { strcpy(logbook_enc, experiment); strcpy(logbook, experiment); url_decode(logbook); } /* check for global selection page if no logbook given */ if (!logbook[0] && getcfg("global", "Selection page", str)) { strcpy(file_name, cfg_dir); strcat(file_name, str); send_file(file_name); return; } /* if no logbook given, display logbook selection page */ if (!logbook[0]) { for (i=n=0 ; ; i++) { if (!enumgrp(i, str)) break; if (!equal_ustring(str, "global")) { strcpy(logbook, str); n++; } } if (n > 1) { show_selection_page(); return; } strcpy(logbook_enc, logbook); url_encode(logbook_enc); } /* get theme for logbook */ if (getcfg(logbook, "Theme", str)) loadtheme(str); else loadtheme(NULL); /* get default values */ /* get data dir from configuration file */ getcfg(logbook, "Data dir", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(data_dir, str); else { strcpy(data_dir, cfg_dir); strcat(data_dir, str); } if (data_dir[strlen(data_dir)-1] != DIR_SEPARATOR) strcat(data_dir, DIR_SEPARATOR_STR); if (*getparam("wpassword")) { /* check if password correct */ do_crypt(getparam("wpassword"), enc_pwd); if (!check_password(logbook, "Write password", enc_pwd, getparam("redir"))) return; rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* get optional expriation from configuration file */ exp = 0; if (getcfg(logbook, "Write password expiration", str)) exp = atof(str); if (exp == 0) { if (getcfg("global", "Write password", str)) rsprintf("Set-Cookie: wpwd=%s; path=/\r\n", enc_pwd); else rsprintf("Set-Cookie: wpwd=%s\r\n", enc_pwd); } else { time(&now); now += (int) (3600*exp); gmt = gmtime(&now); strftime(str, sizeof(str), "%A, %d-%b-%y %H:%M:%S GMT", gmt); if (getcfg("global", "Write password", str)) rsprintf("Set-Cookie: wpwd=%s; path=/; expires=%s\r\n", enc_pwd, logbook_enc, str); else rsprintf("Set-Cookie: wpwd=%s; expires=%s\r\n", enc_pwd, logbook_enc, str); } sprintf(str, "%s", getparam("redir")); if (!str[0]) strcpy(str, "."); rsprintf("Location: %s\r\n\r\nredir\r\n", str); return; } if (*getparam("apassword")) { /* check if password correct */ do_crypt(getparam("apassword"), enc_pwd); if (!check_password(logbook, "Admin password", enc_pwd, getparam("redir"))) return; rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* get optional expriation from configuration file */ exp = 0; if (getcfg(logbook, "Admin password expiration", str)) exp = atof(str); if (exp == 0) { if (getcfg("global", "Admin password", str)) rsprintf("Set-Cookie: apwd=%s; path=/\r\n", enc_pwd); else rsprintf("Set-Cookie: apwd=%s\r\n", enc_pwd); } else { time(&now); now += (int) (3600*exp); gmt = gmtime(&now); strftime(str, sizeof(str), "%A, %d-%b-%y %H:%M:%S GMT", gmt); if (getcfg("global", "Admin password", str)) rsprintf("Set-Cookie: apwd=%s; path=/; expires=%s\r\n", enc_pwd); else rsprintf("Set-Cookie: apwd=%s; expires=%s\r\n", enc_pwd); } sprintf(str, "%s", getparam("redir")); if (!str[0]) strcpy(str, "."); rsprintf("Location: %s\r\n\r\nredir\r\n", str); return; } if (*getparam("uname") && getparam("upassword")) { /* check if password correct */ do_crypt(getparam("upassword"), enc_pwd); /* log logins */ logf("Login of user \"%s\" (attempt) for logbook \"%s\" ",getparam("uname"),logbook); if (!check_user_password(logbook, getparam("uname"), enc_pwd, getparam("redir"))) return; logf("Login of user \"%s\" (successful)",getparam("uname")); rsprintf("HTTP/1.1 302 Found\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (use_keepalive) { rsprintf("Connection: Keep-Alive\r\n"); rsprintf("Keep-Alive: timeout=60, max=10\r\n"); } /* get optional expriation from configuration file */ exp = 0; if (getcfg(logbook, "Login expiration", str)) exp = atof(str); if (exp == 0) { if (getcfg("global", "Password file", str)) { rsprintf("Set-Cookie: upwd=%s; path=/\r\n", enc_pwd); rsprintf("Set-Cookie: unm=%s; path=/\r\n", getparam("uname")); } else { rsprintf("Set-Cookie: upwd=%s\r\n", enc_pwd); rsprintf("Set-Cookie: unm=%s\r\n", getparam("uname")); } } else { time(&now); now += (int) (3600*exp); gmt = gmtime(&now); strftime(str, sizeof(str), "%A, %d-%b-%y %H:%M:%S GMT", gmt); if (getcfg("global", "Password file", str)) { rsprintf("Set-Cookie: upwd=%s; path=/; expires=%s\r\n", enc_pwd, str); rsprintf("Set-Cookie: unm=%s; path=/; expires=%s\r\n", getparam("uname"), str); } else { rsprintf("Set-Cookie: upwd=%s; expires=%s\r\n", enc_pwd, str); rsprintf("Set-Cookie: unm=%s; expires=%s\r\n", getparam("uname"), str); } } sprintf(str, "%s", getparam("redir")); if (!str[0]) strcpy(str, "."); rsprintf("Location: %s\r\n\r\nredir\r\n", str); return; } /*---- show ELog page --------------------------------------------*/ /* if password file given, check password and user name */ if (getcfg(logbook, "Password file", str)) { logf("Connection of user \"%s\"",getparam("unm")); /* don't check password for submit, since cookie might have been expired during editing */ if (!equal_ustring(command, loc("Submit"))) if (!check_user_password(logbook, getparam("unm"), getparam("upwd"), path)) return; } if (equal_ustring(command, loc("New")) || equal_ustring(command, loc("Edit")) || equal_ustring(command, loc("Reply")) || equal_ustring(command, loc("Delete"))) { sprintf(str, "%s?cmd=%s", path, command); if (!check_password(logbook, "Write password", getparam("wpwd"), str)) return; } if (equal_ustring(command, loc("Delete")) || equal_ustring(command, loc("Config")) || equal_ustring(command, loc("Copy to")) || equal_ustring(command, loc("Move to"))) { sprintf(str, "%s?cmd=%s", path, command); if (!check_password(logbook, "Admin password", getparam("apwd"), str)) return; } show_elog_page(logbook, dec_path); return; } /*------------------------------------------------------------------*/ void decode_get(char *string) { char path[256]; char *p, *pitem; strncpy(path, string, sizeof(path)); path[255] = 0; if (strchr(path, '?')) *strchr(path, '?') = 0; setparam("path", path); if (strchr(string, '?')) { p = strchr(string, '?')+1; /* cut trailing "/" from netscape */ if (p[strlen(p)-1] == '/') p[strlen(p)-1] = 0; p = strtok(p,"&"); while (p != NULL) { pitem = p; p = strchr(p,'='); if (p != NULL) { *p++ = 0; url_decode(pitem); url_decode(p); setparam(pitem, p); p = strtok(NULL,"&"); } } } interprete(path); } /*------------------------------------------------------------------*/ void decode_post(char *string, char *boundary, int length) { char *pinit, *p, *ptmp, file_name[256], str[256], line[256], item[256]; int i, n; for (i=0 ; ih_addrtype != AF_INET) { printf("Non Internet address for -h %s\n", tcp_hostname); return; } memcpy(&serv_addr.sin_addr.s_addr, phe->h_addr_list[0], phe->h_length); } serv_addr.sin_port = htons((short) tcp_port); /* try reusing address */ flag = 1; setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT)); status = bind(lsock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (status < 0) { printf("Cannot bind to port %d.\nPlease try later or use the \"-p\" flag to specify a different port\n", tcp_port); return; } /* get host name for mail notification */ gethostname(host_name, sizeof(host_name)); phe = gethostbyname(host_name); if (phe != NULL) phe = gethostbyaddr(phe->h_addr, sizeof(int), AF_INET); /* if domain name is not in host name, hope to get it from phe */ if (strchr(host_name, '.') == NULL && phe != NULL) strcpy(host_name, phe->h_name); /* open configuration file */ getcfg("dummy", "dummy", str); if (daemon) { printf("Becoming a daemon...\n"); ss_daemon_init(); } #ifdef OS_UNIX /* crate /var/run/elogd.pid file */ { int pid; FILE *f; pid = getpid(); f = fopen("/var/run/elogd.pid", "w"); if (f) { fprintf(f, "%d\n", pid); fclose(f); } } /* install signal handler */ signal(SIGTERM, ctrlc_handler); signal(SIGINT, ctrlc_handler); /* give up root privilege */ if (geteuid() == 0) { struct group *gr; struct passwd *pw; if (getcfg("global", "Group", str)) { gr = getgrnam(str); if (setgid(gr->gr_gid) < 0 || initgroups(gr->gr_name, gr->gr_gid) < 0) printf("Cannot set GID to group \"%s\"\n", gr->gr_name); } else setgid(getgid()); /* used for setuid programs */ if (getcfg("global", "User", str)) { pw = getpwnam(str); if (setuid(pw->pw_uid) < 0) printf("Cannot set UID to user \"%s\\n", str); } else setuid(getuid()); /* used for setuid programs */ } #endif /* listen for connection */ status = listen(lsock, SOMAXCONN); if (status < 0) { printf("Cannot listen\n"); return; } printf("Server listening...\n"); do { FD_ZERO(&readfds); FD_SET(lsock, &readfds); for (i=0 ; i 0) FD_SET(ka_sock[i], &readfds); timeout.tv_sec = 0; timeout.tv_usec = 100000; status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout); if (_abort) break; if (FD_ISSET(lsock, &readfds)) { len = sizeof(acc_addr); _sock = accept(lsock, (struct sockaddr *) &acc_addr, &len); /* find new entry in socket table */ for (i=0 ; i 0 && FD_ISSET(ka_sock[i], &readfds)) break; if (i == N_MAX_CONNECTION) { _sock = 0; } else { i_conn = i; _sock = ka_sock[i_conn]; ka_time[i_conn] = (int) time(NULL); memcpy(&rem_addr, &remote_addr[i_conn], sizeof(rem_addr)); #ifdef DEBUG_CONN printf("## received request on connection %d\n", i_conn); #endif } } /* turn off keep_alive by default */ keep_alive = FALSE; if (_sock > 0) { memset(net_buffer, 0, sizeof(net_buffer)); len = 0; header_length = 0; n_error = 0; do { FD_ZERO(&readfds); FD_SET(_sock, &readfds); timeout.tv_sec = 6; timeout.tv_usec = 0; status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout); if (FD_ISSET(_sock, &readfds)) i = recv(_sock, net_buffer+len, sizeof(net_buffer)-len, 0); else goto error; /* abort if connection got broken */ if (i<0) goto error; if (i>0) len += i; /* check if net_buffer too small */ if (len >= sizeof(net_buffer)) { /* drain incoming remaining data */ do { FD_ZERO(&readfds); FD_SET(_sock, &readfds); timeout.tv_sec = 2; timeout.tv_usec = 0; status = select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout); if (FD_ISSET(_sock, &readfds)) i = recv(_sock, net_buffer, sizeof(net_buffer), 0); else break; } while (i); memset(return_buffer, 0, sizeof(return_buffer)); strlen_retbuf = 0; return_length = 0; show_error("Submitted attachment too large, please increase WEB_BUFFER_SIZE in elogd.c and recompile"); send(_sock, return_buffer, strlen_retbuf+1, 0); keep_alive = 0; if (verbose) { printf("==== Return ================================\n"); puts(return_buffer); printf("\n\n"); } goto error; } if (i == 0) { n_error++; if (n_error == 100) goto error; } /* finish when empty line received */ if (strstr(net_buffer, "GET") != NULL && strstr(net_buffer, "POST") == NULL) { if (len>4 && strcmp(&net_buffer[len-4], "\r\n\r\n") == 0) break; if (len>6 && strcmp(&net_buffer[len-6], "\r\r\n\r\r\n") == 0) break; } else if (strstr(net_buffer, "POST") != NULL) { if (header_length == 0) { /* extract logbook */ strncpy(str, net_buffer+6, sizeof(str)); if (strstr(str, "HTTP")) *(strstr(str, "HTTP")-1) = 0; strcpy(logbook, str); strcpy(logbook_enc, str); url_decode(logbook); /* extract header and content length */ if (strstr(net_buffer, "Content-Length:")) content_length = atoi(strstr(net_buffer, "Content-Length:") + 15); else if (strstr(net_buffer, "Content-length:")) content_length = atoi(strstr(net_buffer, "Content-length:") + 15); boundary[0] = 0; if (strstr(net_buffer, "boundary=")) { strncpy(boundary, strstr(net_buffer, "boundary=")+9, sizeof(boundary)); if (strchr(boundary, '\r')) *strchr(boundary, '\r') = 0; } if (strstr(net_buffer, "\r\n\r\n")) header_length = (INT)strstr(net_buffer, "\r\n\r\n") - (INT)net_buffer + 4; if (strstr(net_buffer, "\r\r\n\r\r\n")) header_length = (INT)strstr(net_buffer, "\r\r\n\r\r\n") - (INT)net_buffer + 6; if (header_length) net_buffer[header_length-1] = 0; } if (header_length > 0 && len >= header_length+content_length) break; } else if (strstr(net_buffer, "HEAD") != NULL) { /* just return header */ rsprintf("HTTP/1.1 200 OK\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); rsprintf("Connection: close\r\n"); rsprintf("Content-Type: text/html\r\n\r\n"); keep_alive = FALSE; return_length = strlen_retbuf+1; send(_sock, return_buffer, return_length, 0); goto error; } else if (strstr(net_buffer, "OPTIONS") != NULL) goto error; else { printf(net_buffer); goto error; } } while (1); if (!strchr(net_buffer, '\r')) goto error; /* initialize parametr array */ initparam(); /* extract cookies */ if ((p = strstr(net_buffer, "Cookie:")) != NULL) { p += 6; do { p++; while (*p && *p == ' ') p++; strncpy(str, p, sizeof(str)); for (i=0 ; i<(int)strlen(str) ; i++) if (str[i] == '=' || str[i] == ';') break; if (str[i] == '=') { str[i] = 0; p += i+1; for (i=0 ; *p && *p != ';' && *p != '\r' && *p != '\n' ; i++) cookie[i] = *p++; cookie[i] = 0; } else { /* empty cookie */ str[i] = 0; cookie[0] = 0; p += i; } /* store cookie as parameter */ setparam(str, cookie); } while (*p && *p == ';'); } /* extract referer */ referer[0] = 0; if ((p = strstr(net_buffer, "Referer:")) != NULL) { p += 9; while (*p && *p == ' ') p++; strncpy(referer, p, sizeof(referer)); if (strchr(referer, '\r')) *strchr(referer, '\r') = 0; if (strchr(referer, '?')) *strchr(referer, '?') = 0; for (p=referer+strlen(referer)-1 ; p>referer && *p != '/' ; p--) *p = 0; } memset(return_buffer, 0, sizeof(return_buffer)); strlen_retbuf = 0; if (strncmp(net_buffer, "GET", 3) != 0 && strncmp(net_buffer, "POST", 4) != 0) goto error; return_length = 0; /* extract logbook */ p = strchr(net_buffer, '/')+1; logbook[0] = 0; for (i=0 ; *p && *p != '/' && *p != '?' && *p != ' '; i++) logbook[i] = *p++; logbook[i] = 0; strcpy(logbook_enc, logbook); url_decode(logbook); /* check if logbook exists */ for (i=0 ; ; i++) { if (!enumgrp(i, str)) break; if (equal_ustring(logbook, str)) break; } if (strstr(logbook, ".gif") || strstr(logbook, ".jpg") || strstr(logbook, ".jpg") || strstr(logbook, ".png") || strstr(logbook, ".htm")) { /* serve file directly */ strcpy(str, cfg_dir); strcat(str, logbook); send_file(str); send(_sock, return_buffer, return_length, 0); goto error; } else { if (!equal_ustring(logbook, str) && logbook[0]) { if (verbose) printf("\n\n\n%s\n", net_buffer); sprintf(str, "Error: logbook \"%s\" not defined in elogd.cfg", logbook); show_error(str); send(_sock, return_buffer, strlen(return_buffer), 0); if (verbose) { printf("==== Return ================================\n"); puts(return_buffer); printf("\n\n"); } goto error; } } /* if no logbook is given and only one logbook defined, use this one */ if (!logbook[0]) { for (i=n=0 ; ; i++) { if (!enumgrp(i, str)) break; if (!equal_ustring(str, "global")) n++; } if (n == 1) { if (verbose) printf("\n\n\n%s\n", net_buffer); strcpy(logbook, str); strcpy(logbook_enc, logbook); url_encode(logbook_enc); strcat(logbook_enc, "/"); /* redirect to logbook, necessary to get optional cookies for that logbook */ redirect(logbook_enc); send(_sock, return_buffer, strlen(return_buffer), 0); if (verbose) { printf("==== Return ================================\n"); puts(return_buffer); printf("\n\n"); } goto error; } } /* force re-read configuration file */ if (cfgbuffer) { free(cfgbuffer); cfgbuffer = NULL; } /*---- check "hosts deny" ----*/ authorized = 1; if (getcfg(logbook, "Hosts deny", list)) { phe = gethostbyaddr((char *) &rem_addr, 4, PF_INET); if (phe != NULL) strcpy(rem_host_name, phe->h_name); else strcpy(rem_host_name, ""); strcpy(rem_host_ip, (char *)inet_ntoa(rem_addr)); n = strbreak(list, host_list, MAX_N_LIST); /* check if current connection matches anyone on the list */ for (i=0 ; i strlen(host_list[i]) && equal_ustring(host_list[i], rem_host_name+strlen(rem_host_name)-strlen(host_list[i]))) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts deny\". Access denied.\n", rem_host_name, host_list[i]); authorized = 0; break; } } if (host_list[i][strlen(host_list[i])-1] == '.') { strcpy(str, rem_host_ip); if (strlen(str) > strlen(host_list[i])) str[strlen(host_list[i])] = 0; if (equal_ustring(host_list[i], str)) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts deny\". Access denied.\n", rem_host_ip, host_list[i]); authorized = 0; break; } } } } /*---- check "hosts allow" ----*/ if (getcfg(logbook, "Hosts allow", list)) { phe = gethostbyaddr((char *) &rem_addr, 4, PF_INET); if (phe != NULL) strcpy(rem_host_name, phe->h_name); else strcpy(rem_host_name, ""); strcpy(rem_host_ip, (char *)inet_ntoa(acc_addr.sin_addr)); n = strbreak(list, host_list, MAX_N_LIST); /* check if current connection matches anyone on the list */ for (i=0 ; i strlen(host_list[i]) && equal_ustring(host_list[i], rem_host_name+strlen(rem_host_name)-strlen(host_list[i]))) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts allow\". Access granted.\n", rem_host_name, host_list[i]); authorized = 1; break; } } if (host_list[i][strlen(host_list[i])-1] == '.') { strcpy(str, rem_host_ip); if (strlen(str) > strlen(host_list[i])) str[strlen(host_list[i])] = 0; if (equal_ustring(host_list[i], str)) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts allow\". Access granted.\n", rem_host_ip, host_list[i]); authorized = 1; break; } } } } if (!authorized) { keep_alive = 0; goto error; } /* ask for password if configured */ authorized = 1; if (getcfg(logbook, "Read Password", pwd)) { authorized = 0; /* decode authorization */ if (strstr(net_buffer, "Authorization:")) { p = strstr(net_buffer, "Authorization:")+14; if (strstr(p, "Basic")) { p = strstr(p, "Basic")+6; while (*p == ' ') p++; i = 0; while (*p && *p != ' ' && *p != '\r') str[i++] = *p++; str[i] = 0; } base64_decode(str, cl_pwd); if (strchr(cl_pwd, ':')) { p = strchr(cl_pwd, ':')+1; do_crypt(p, str); strcpy(cl_pwd, str); /* check authorization */ if (strcmp(str, pwd) == 0) authorized = 1; } } } /* check for Keep-alive */ if (strstr(net_buffer, "Keep-Alive") != NULL && use_keepalive) keep_alive = TRUE; if (!authorized) { /* return request for authorization */ rsprintf("HTTP/1.1 401 Authorization Required\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); rsprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", logbook); rsprintf("Connection: close\r\n"); rsprintf("Content-Type: text/html\r\n\r\n"); rsprintf("\r\n"); rsprintf("401 Authorization Required\r\n"); rsprintf("\r\n"); rsprintf("

Authorization Required

\r\n"); rsprintf("This server could not verify that you\r\n"); rsprintf("are authorized to access the document\r\n"); rsprintf("requested. Either you supplied the wrong\r\n"); rsprintf("credentials (e.g., bad password), or your\r\n"); rsprintf("browser doesn't understand how to supply\r\n"); rsprintf("the credentials required.

\r\n"); rsprintf("\r\n"); keep_alive = FALSE; } else { if (verbose) printf("\n\n\n%s\n", net_buffer); if (strncmp(net_buffer, "GET", 3) == 0) { /* extract path and commands */ *strchr(net_buffer, '\r') = 0; if (!strstr(net_buffer, "HTTP")) goto error; *(strstr(net_buffer, "HTTP")-1)=0; /* skip logbook from path */ p = net_buffer+5; for (i=0 ; *p && *p != '/' && *p != '?'; p++); while (*p && *p == '/') p++; /* decode command and return answer */ decode_get(p); } else if (strncmp(net_buffer, "POST", 4) == 0) { if (verbose) printf("%s\n", net_buffer+header_length); decode_post(net_buffer+header_length, boundary, content_length); } else { net_buffer[50] = 0; sprintf(str, "Unknown request:

%s", net_buffer); show_error(str); } } if (return_length != -1) { if (return_length == 0) return_length = strlen_retbuf+1; if (keep_alive && strstr(return_buffer, "Content-Length") == NULL || strstr(return_buffer, "Content-Length") > strstr(return_buffer, "\r\n\r\n")) { /*---- add content-length ----*/ p = strstr(return_buffer, "\r\n\r\n"); if (p != NULL) { length = strlen(p+4); header_length = (int) (p - return_buffer); memcpy(header_buffer, return_buffer, header_length); sprintf(header_buffer+header_length, "\r\nContent-Length: %d\r\n\r\n", length); send(_sock, header_buffer, strlen(header_buffer), 0); send(_sock, p+4, length, 0); if (verbose) { printf("==== Return ================================\n"); puts(header_buffer); puts(p+2); printf("\n"); } } else printf("Internal error, no valid header!\n"); } else { send(_sock, return_buffer, return_length, 0); if (verbose) { printf("==== Return ================================\n"); puts(return_buffer); printf("\n\n"); } } error: if (!keep_alive) { closesocket(_sock); ka_sock[i_conn] = 0; #ifdef DEBUG_CONN printf("## close connection %d\n", i_conn); #endif } } } } while (!_abort); printf("Server aborted.\n"); } /*------------------------------------------------------------------*/ void create_password(char *logbook, char *name, char *pwd) { int fh, length, i; char *cfgbuffer, str[256], *p; fh = open(cfg_file, O_RDONLY); if (fh < 0) { /* create new file */ fh = open(cfg_file, O_CREAT | O_WRONLY, 0640); if (fh < 0) { printf("Cannot create \"%s\".\n", cfg_file); return; } sprintf(str, "[%s]\n%s=%s\n", logbook, name, pwd); write(fh, str, strlen(str)); close(fh); printf("File \"%s\" created with password in logbook \"%s\".\n", cfg_file, logbook); return; } /* read existing file and add password */ length = lseek(fh, 0, SEEK_END); lseek(fh, 0, SEEK_SET); cfgbuffer = malloc(length+1); if (cfgbuffer == NULL) { close(fh); return; } length = read(fh, cfgbuffer, length); cfgbuffer[length] = 0; close(fh); fh = open(cfg_file, O_TRUNC | O_WRONLY, 0640); sprintf(str, "[%s]", logbook); /* check if logbook exists already */ if (strstr(cfgbuffer, str)) { p = strstr(cfgbuffer, str); /* search password in current logbook */ do { while (*p && *p != '\n') p++; if (*p && *p == '\n') p++; if (strncmp(p, name, strlen(name)) == 0) { /* replace existing password */ i = (int) (p - cfgbuffer); write(fh, cfgbuffer, i); sprintf(str, "%s=%s\n", name, pwd); write(fh, str, strlen(str)); printf("Password replaced in logbook \"%s\".\n", logbook); while (*p && *p != '\n') p++; if (*p && *p == '\n') p++; /* write remainder of file */ write(fh, p, strlen(p)); free(cfgbuffer); close(fh); return; } } while (*p && *p != '['); if (!*p || *p == '[') { /* enter password into current logbook */ p = strstr(cfgbuffer, str); while (*p && *p != '\n') p++; if (*p && *p == '\n') p++; i = (int) (p - cfgbuffer); write(fh, cfgbuffer, i); sprintf(str, "%s=%s\n", name, pwd); write(fh, str, strlen(str)); printf("Password added to logbook \"%s\".\n", logbook); /* write remainder of file */ write(fh, p, strlen(p)); free(cfgbuffer); close(fh); return; } } else /* write new logbook entry */ { write(fh, cfgbuffer, strlen(cfgbuffer)); sprintf(str, "\n[%s]\n%s=%s\n\n", logbook, name, pwd); write(fh, str, strlen(str)); printf("Password added to new logbook \"%s\".\n", logbook); } free(cfgbuffer); close(fh); } /*------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int i, fh; int daemon = FALSE; char read_pwd[80], write_pwd[80], admin_pwd[80], str[80]; time_t now; struct tm *tms; tzset(); read_pwd[0] = write_pwd[0] = admin_pwd[0] = logbook[0] = 0; strcpy(cfg_file, "elogd.cfg"); use_keepalive = TRUE; /* parse command line parameters */ for (i=1 ; itm_year % 100, tms->tm_mon+1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec); return 0; } else if (argv[i][0] == '-') { if (i+1 >= argc || argv[i+1][0] == '-') goto usage; if (argv[i][1] == 'p') tcp_port = atoi(argv[++i]); else if (argv[i][1] == 'c') strcpy(cfg_file, argv[++i]); else if (argv[i][1] == 'r') strcpy(read_pwd, argv[++i]); else if (argv[i][1] == 'w') strcpy(write_pwd, argv[++i]); else if (argv[i][1] == 'a') strcpy(admin_pwd, argv[++i]); else if (argv[i][1] == 'l') strcpy(logbook, argv[++i]); else if (argv[i][1] == 'h') strncpy(tcp_hostname, argv[++i], sizeof(tcp_hostname)); else { usage: printf("usage: %s [-p port] [-h hostname] [-D] [-c file] [-r pwd] [-w pwd] [-a pwd] [-l logbook]\n\n", argv[0]); printf(" -p TCP/IP port\n"); printf(" -h TCP/IP hostname\n"); printf(" -D become a daemon\n"); printf(" -c specify configuration file\n"); printf(" -v debugging output\n"); printf(" -r create/overwrite read password in config file\n"); printf(" -w create/overwrite write password in config file\n"); printf(" -a create/overwrite admin password in config file\n"); printf(" -l specify logbook for -r and -w commands\n\n"); printf(" -k do not use keep-alive\n\n"); return 0; } } } if (read_pwd[0]) { if (!logbook[0]) { printf("Must specify a lookbook via the -l parameter.\n"); return 0; } do_crypt(read_pwd, str); create_password(logbook, "Read Password", str); return 0; } if (write_pwd[0]) { if (!logbook[0]) { printf("Must specify a lookbook via the -l parameter.\n"); return 0; } do_crypt(write_pwd, str); create_password(logbook, "Write Password", str); return 0; } if (admin_pwd[0]) { if (!logbook[0]) { printf("Must specify a lookbook via the -l parameter.\n"); return 0; } do_crypt(admin_pwd, str); create_password(logbook, "Admin Password", str); return 0; } /* extract directory from configuration file */ if (cfg_file[0] && strchr(cfg_file, DIR_SEPARATOR)) { strcpy(cfg_dir, cfg_file); for (i=strlen(cfg_dir)-1 ; i>0 ; i--) { if (cfg_dir[i] == DIR_SEPARATOR) break; cfg_dir[i] = 0; } } /* check for configuration file */ fh = open(cfg_file, O_RDONLY | O_BINARY); if (fh < 0) { printf("Configuration file \"%s\" not found.\n", cfg_file); return 1; } close(fh); server_loop(tcp_port, daemon); #ifdef OS_UNIX unlink("/var/run/elogd.pid"); #endif return 0; }