/********************************************************************\ Name: elogd.c Created by: Stefan Ritt Contents: Web server program for Electronic Logbook ELOG $Log$ Revision 2.103 2002/11/22 07:56:53 midas Fixed bug with self register in German Revision 2.102 2002/11/21 09:25:05 midas Fixed bug with 'hosts allow' Revision 2.101 2002/11/21 09:13:33 midas Added 'menu text' and 'find menu text' Revision 2.100 2002/11/20 14:20:16 midas Fixed bug with bottom text file display Revision 2.99 2002/11/20 13:48:10 midas Create data dir automatically, allow for substitutions in find attributes Revision 2.98 2002/11/19 11:17:31 midas Added 'table align' Revision 2.97 2002/11/19 08:32:29 midas Fixed bug with 10 attachments Revision 2.96 2002/11/06 13:39:29 midas Added charset= option Revision 2.95 2002/11/06 08:59:18 midas Files can be specified with absolute path Revision 2.94 2002/11/05 15:40:58 midas Hide non-allowed commands Revision 2.93 2002/11/05 15:14:37 midas Move whole thread on re-submission of individual entry Revision 2.92 2002/11/04 16:20:26 midas Made 'allow = ' work in localized versions Revision 2.91 2002/11/04 12:56:25 midas Fixed bug selecting messages in other languages Revision 2.90 2002/10/25 04:21:19 midas Made self registration work with global password file Revision 2.89 2002/10/18 05:36:20 midas Fixed bugs with 'Start page = ...' Revision 2.88 2002/10/15 08:49:02 midas Version 2.2.1 Revision 2.87 2002/10/15 08:07:13 midas Fixed display of multiple messages in threaded find Revision 2.86 2002/09/30 07:07:02 midas Fixed typo Revision 2.85 2002/09/26 06:57:14 midas Check reverse sort box if 'reverse sort = 1' Revision 2.84 2002/09/25 15:00:31 midas Fixed HTML bug Revision 2.83 2002/09/25 10:33:47 midas Fixed URL problem with delete Revision 2.82 2002/09/24 15:16:05 midas Version 2.2.0 Revision 2.81 2002/09/24 14:28:11 midas 'Show last xxx' finished Revision 2.80 2002/09/23 07:18:05 midas 'Show last' xxx half finished Revision 2.79 2002/09/16 08:27:20 midas Fixed problem with Konqueror and 'Cancel' Revision 2.78 2002/09/16 07:02:54 midas Version 2.1.3 Revision 2.77 2002/09/16 06:45:22 midas Fixed problem with saving other user as admin Revision 2.76 2002/09/16 06:22:45 midas Various fixed and enhancement Revision 2.75 2002/09/13 15:32:58 midas Various fixes and enhancements Revision 2.74 2002/09/12 10:08:25 midas Fixed problem with 'self register = 3' Revision 2.73 2002/09/12 08:48:54 midas Fixed sorting bug Revision 2.72 2002/09/10 15:34:38 midas Version 2.1.2 Revision 2.71 2002/09/10 05:59:04 midas Made selections work with 'copy to' and 'move to' Revision 2.70 2002/09/09 08:04:58 midas Added select boxes Revision 2.69 2002/08/13 12:24:37 midas Version 2.1.1 Revision 2.68 2002/08/13 12:23:01 midas Implemented 'self register = 3' Revision 2.67 2002/08/12 15:03:42 midas Improved error dispaly for too large parameters Revision 2.66 2002/08/09 13:43:14 midas Preserve attributes on edit also for preset attributes Revision 2.65 2002/08/06 13:41:40 midas Fixed problem with empty logbooks Revision 2.64 2002/08/06 12:26:20 midas Fixed crash for logbooks without a password file Revision 2.63 2002/08/06 12:01:19 midas Fixed another problem with file truncate Revision 2.62 2002/08/06 11:40:00 midas Fixed problem with file truncate Revision 2.61 2002/08/06 11:06:48 midas Adjusted text box sized Revision 2.60 2002/08/06 10:50:53 midas Added 'guest find menu commands' Revision 2.59 2002/08/06 10:23:11 midas Added 'entry date' to substitution list Revision 2.58 2002/08/06 09:26:16 midas Added automatic creation of new password file Revision 2.57 2002/08/06 09:03:41 midas Removed itoa() Revision 2.56 2002/08/06 08:57:39 midas Added email notify flag to password file Revision 2.55 2002/08/05 15:37:21 midas First version of self-registration Revision 2.54 2002/08/02 11:00:10 midas Started working on user configuration page Revision 2.53 2002/07/31 11:48:08 midas Added page wise display Revision 2.52 2002/07/30 12:44:54 midas Added sortable columns Revision 2.51 2002/07/27 14:09:24 midas Fixed processing of password file Revision 2.50 2002/07/27 06:52:14 midas Added guest menu and user_email Revision 2.49 2002/07/26 08:40:56 midas Fixed type Revision 2.48 2002/07/25 15:37:26 midas Fixed bug with ss_find_file under unix Revision 2.47 2002/07/25 09:22:05 midas Removed scandir() for Solaris compatibility Revision 2.46 2002/07/23 13:50:11 midas Improved speed for threaded display Revision 2.45 2002/07/23 11:31:33 midas Store encoded user name in 'new' page for expired cookies Revision 2.44 2002/07/11 08:49:49 midas Fixed caching problem in Konqueror Revision 2.43 2002/07/11 08:13:31 midas Fixed problem of submitting messages with konqueror Revision 2.42 2002/07/11 07:22:42 midas Made 'elog:/' reference work Revision 2.41 2002/07/09 07:37:37 midas Fixed bug that 'last xx entries?mode=threaded' was displayed Revision 2.40 2002/07/09 07:31:13 midas Removed alphasort() for Solaris compatibility Revision 2.39 2002/07/09 07:22:12 midas Fixed bug in error display on save config file Revision 2.38 2002/07/08 08:39:18 midas Fixed various small bugs Revision 2.37 2002/07/02 07:33:48 midas Added attribute lists with commas Revision 2.36 2002/07/01 09:32:32 midas Fixed problem with submitting '------' as only text Revision 2.35 2002/07/01 08:29:08 midas Propagage '?mode=xxx' though 'lastxx' commands Revision 2.34 2002/07/01 08:13:46 midas Fixed problem with wrong color in command '?cmd=Search' Revision 2.33 2002/06/26 11:53:43 midas Use ts->tm_isdst instead daylight Revision 2.32 2002/06/26 11:44:54 midas Fixed bug when deleting last message in logbook Revision 2.31 2002/06/25 12:08:32 midas Version 2.0.3 Revision 2.30 2002/06/25 11:52:24 midas Fixed problem with changeing passwords Revision 2.29 2002/06/20 14:53:33 midas Synchronize indices if several logbooks share the same data directory Revision 2.28 2002/06/20 09:41:11 midas Added syntax help link to configuration page Revision 2.27 2002/06/20 09:19:10 midas Fixed problems with find Revision 2.26 2002/06/19 10:58:57 midas Fixed bug that 'date format = %A...' always produced 'Sunday' Revision 2.25 2002/06/18 13:15:29 midas Version 2.0.1 Revision 2.24 2002/06/18 07:48:33 midas Fixed bug with previous submission Revision 2.23 2002/06/18 07:32:03 midas Add logbook name when URL is specified Revision 2.22 2002/06/18 07:22:28 midas Removed width from logbook selection page Revision 2.21 2002/06/14 18:34:38 midas Fixed bug in el_build_index() Revision 2.20 2002/06/14 09:28:40 midas Show error for URLs like '/logbook//' Revision 2.19 2002/06/14 07:21:38 midas Corrected parameters to qsort() Revision 2.18 2002/06/14 07:15:22 midas Fixed on resubmits Revision 2.17 2002/06/14 06:55:33 midas Rebuild index if data file got deleted Revision 2.16 2002/06/14 06:46:41 midas Introduced wrapping logbook tabs Revision 2.15 2002/06/14 06:08:19 midas Sort index by date Revision 2.14 2002/06/13 12:46:09 midas Fixed problem wiht 'reply to:' in subject Revision 2.13 2002/06/13 08:59:53 midas Made '../last10?mode=summary' work Revision 2.12 2002/06/12 10:18:16 midas Added redirection if '/' is missing after logbook Revision 2.11 2002/06/12 09:30:03 midas Added elog:x HTML link Revision 2.10 2002/06/12 07:48:56 midas Display message ID's Revision 2.9 2002/06/11 12:01:56 midas Added 'download' command Revision 2.8 2002/06/10 11:46:36 midas Changed comma display in search result page Revision 2.7 2002/06/10 11:22:41 midas Added 'Subst on reply' option Revision 2.6 2002/06/10 10:38:22 midas Added 'top level only' flag Revision 2.5 2002/06/07 14:56:53 midas Fixed time offset due to DST when using 'Date format' Revision 2.4 2002/06/07 14:40:37 midas Check URL tail before displaying logbook page Revision 2.3 2002/06/07 14:22:00 midas Workaround for Konqueror browser Revision 2.2 2002/06/07 11:58:43 midas 'Display search' can now supress display of '#', 'Logbook' and 'Date' Revision 2.1 2002/06/07 09:37:02 midas Added 'HTML default = 3' Revision 2.0 2002/06/06 15:16:39 midas First version with new database scheme 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 "2.2.4" #include #include #include #include #include #include #ifdef _MSC_VER #define OS_WINNT #define DIR_SEPARATOR '\\' #define DIR_SEPARATOR_STR "\\" #define snprintf _snprintf #include #include #include #include #else #define OS_UNIX #define TRUE 1 #define FALSE 0 #define DIR_SEPARATOR '/' #define DIR_SEPARATOR_STR "/" #define __USE_XOPEN /* needed for crypt() */ typedef int BOOL; #include #include #include #include #include #include #include #include #include #include #include #include #include #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 EL_UPGRADE 6 #define EL_EMPTY 7 #define EL_MEM_ERROR 8 #define EL_FIRST 1 #define EL_LAST 2 #define EL_NEXT 3 #define EL_PREV 4 #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 browser[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 CMD_SIZE 10000 #define TEXT_SIZE 100000 #define MAX_PATH_LENGTH 256 char _param[MAX_PARAM][PARAM_LENGTH]; char _value[MAX_PARAM][VALUE_SIZE]; char _text[TEXT_SIZE]; char _cmdline[CMD_SIZE]; char *_attachment_buffer[MAX_ATTACHMENTS]; INT _attachment_size[MAX_ATTACHMENTS]; struct in_addr rem_addr; char rem_host[256]; 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_EDIT (1<<3) #define AF_FIXED_REPLY (1<<4) #define AF_ICON (1<<5) #define AF_RADIO (1<<6) 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" }, { "" }, }; typedef struct { int message_id; char file_name[32]; time_t file_time; int offset; BOOL thread_head; } EL_INDEX; typedef struct { char name[256]; char name_enc[256]; char data_dir[256]; EL_INDEX *el_index; int *n_el_index; int n_attr; } LOGBOOK; typedef struct { LOGBOOK *lbs; int index; char string[256]; } MSG_LIST; LOGBOOK *lb_list = NULL; void show_error(char *error); void show_http_header(); BOOL enum_user_line(LOGBOOK *lbs, int n, char *user); int get_user_line(char *logbook_name, char *user, char *password, char *full_name, char *email, char *email_notify); int strbreak(char *str, char list[][NAME_LENGTH], int size); /*---- 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[TEXT_SIZE+1000]; 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 (ts->tm_isdst) 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, *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 */ str = malloc(10000); 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); free(str); return 1; } } if (p) p = strchr(p, '\n'); if (p) p++; } } } if (p) p = strchr(p, '\n'); if (p) p++; } while (p); free(str); /* 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; ptrans[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; } printf("Language error: string \"%s\" not found for language \"%s\"\n", orig, language); return orig; } /*-------------------------------------------------------------------*/ /* translate back from localized string to english */ char *unloc(char *orig) { int n; if (!locbuffer) return orig; /* search string and return translation */ for (n = 0; ptrans[n] ; n++) if (strcmp(orig, ptrans[n]) == 0) { if (*porig[n]) return porig[n]; return orig; } printf("Language error: string \"%s\" not found\n", 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", "" }, { "Thread image", "" }, { "Thread reply image", "" }, { "" } }; 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, *ph; if (result == NULL) return; *result = 0; ph = strstr(message, "========================================\n"); if ((pc = strstr(message, key)) != NULL && pc < ph && (*(pc-1) == '\n' || *(pc-1) == '\r')) { for (pc=strstr(message, key)+strlen(key) ; *pc != '\n' && *pc != '\r' ; ) *result++ = *pc++; *result = 0; } else *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 file list Function value: int Number of files matching request \********************************************************************/ { #ifdef OS_UNIX DIR *dir_pointer; struct dirent *dp; int i; 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); return i; #endif #ifdef OS_WINNT HANDLE pffile; LPWIN32_FIND_DATA lpfdata; char str[255]; int i, 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); return i; #endif } /*------------------------------------------------------------------*/ int eli_compare(const void *e1, const void *e2) { if (((EL_INDEX *)e1)->file_time < ((EL_INDEX *)e2)->file_time) return -1; if (((EL_INDEX *)e1)->file_time >= ((EL_INDEX *)e2)->file_time) return 1; return 0; } /*------------------------------------------------------------------*/ int el_build_index(LOGBOOK *lbs, BOOL rebuild) /* scan all ??????a.log files and build an index table in eli[] */ { char *file_list, str[256], date[256], dir[256], file_name[256], *buffer, *p, in_reply_to[80]; int index, n, length; int i, fh; time_t ltime; struct tm tms; if (rebuild) { free(lbs->el_index); free(lbs->n_el_index); } /* check if this logbook has same data dir as previous */ for (i=0 ; lb_list[i].name[0] && &lb_list[i] != lbs; i++) if (equal_ustring(lb_list[i].data_dir, lbs->data_dir)) break; if (equal_ustring(lb_list[i].data_dir, lbs->data_dir) && &lb_list[i] != lbs) { if (verbose) printf(" Same index as logbook %s\n", lb_list[i].name); lbs->el_index = lb_list[i].el_index; lbs->n_el_index = lb_list[i].n_el_index; return EL_SUCCESS; } lbs->n_el_index = malloc(sizeof(int)); *lbs->n_el_index = 0; lbs->el_index = malloc(0); /* get data directory */ strcpy(dir, lbs->data_dir); file_list = NULL; n = ss_file_find(dir, "??????a.log", &file_list); if (n == 0) { if (file_list) free(file_list); file_list = NULL; n = ss_file_find(dir, "??????.log", &file_list); if (n > 0) return EL_UPGRADE; return EL_EMPTY; } /* go through all files */ for (index=0 ; index 0) { buffer = malloc(length+1); if (buffer == NULL) { printf("Not enough memory to allocate file buffer (%d bytes)\n", length); return EL_MEM_ERROR; } lseek(fh, 0, SEEK_SET); read(fh, buffer, length); buffer[length] = 0; close(fh); /* go through buffer */ p = buffer; do { p = strstr(p, "$@MID@$:"); if (p) { lbs->el_index = realloc(lbs->el_index, sizeof(EL_INDEX)*(*lbs->n_el_index+1)); if (lbs->el_index == NULL) { printf("Not enough memory to allocate message index\n"); return EL_MEM_ERROR; } strcpy(str, file_list+index*MAX_PATH_LENGTH); strcpy(lbs->el_index[*lbs->n_el_index].file_name, str); el_decode(p, "Date: ", date); el_decode(p, "In reply to: ", in_reply_to); memset(&tms, 0, sizeof(struct tm)); for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; tms.tm_mon = i; tms.tm_mday = atoi(date+8); tms.tm_hour = atoi(date+11); tms.tm_min = atoi(date+14); tms.tm_sec = atoi(date+17); tms.tm_year = atoi(date+20)-1900; tms.tm_isdst = -1; if (tms.tm_year < 90) tms.tm_year += 100; ltime = mktime(&tms); lbs->el_index[*lbs->n_el_index].file_time = ltime; lbs->el_index[*lbs->n_el_index].message_id = atoi(p+8); lbs->el_index[*lbs->n_el_index].offset = (int) p - (int) buffer; lbs->el_index[*lbs->n_el_index].thread_head = (in_reply_to[0] == 0); if (lbs->el_index[*lbs->n_el_index].message_id > 0) { if (verbose) printf(" ID %3d in %s, offset %5d, %s\n", lbs->el_index[*lbs->n_el_index].message_id, str, lbs->el_index[*lbs->n_el_index].offset, lbs->el_index[*lbs->n_el_index].thread_head ? "thread head" : "reply"); /* valid ID */ (*lbs->n_el_index)++; } p += 8; } } while (p); free(buffer); } } free(file_list); /* sort entries according to date */ qsort(lbs->el_index, *lbs->n_el_index, sizeof(EL_INDEX), eli_compare); if (verbose) { printf("After sort:\n"); for (i=0 ; i<*lbs->n_el_index ; i++) printf(" ID %3d in %s, offset %5d\n", lbs->el_index[i].message_id, lbs->el_index[i].file_name, lbs->el_index[i].offset); } return EL_SUCCESS; } /*------------------------------------------------------------------*/ int el_index_logbooks(BOOL reinit) { char str[256], data_dir[256], logbook[256]; int i, j, n, status; if (reinit) { for (i=0 ; lb_list[i].name[0] ; i++) { if (lb_list[i].el_index != NULL) { free(lb_list[i].el_index); free(lb_list[i].n_el_index); /* check if other logbook uses same index */ for (j=i+1 ; lb_list[j].name[0] ; j++) { /* mark that logbook already freed */ if (lb_list[j].el_index == lb_list[i].el_index) lb_list[j].el_index = NULL; } } } free(lb_list); } /* count logbooks */ for (i=n=0 ; ; i++) { if (!enumgrp(i, str)) break; if (equal_ustring(str, "global")) continue; n++; } lb_list = calloc(sizeof(LOGBOOK), n+1); for (i=n=0 ; ; i++) { if (!enumgrp(i, logbook)) break; if (equal_ustring(logbook, "global")) continue; strcpy(lb_list[n].name, logbook); strcpy(lb_list[n].name_enc, logbook); url_encode(lb_list[n].name_enc); /* 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); /* create data directory if not existing */ getcwd(str, sizeof(str)); j = chdir(data_dir); if (j < 0) { #ifdef OS_WINNT j = mkdir(data_dir); #else j = mkdir(data_dir, 0755); #endif if (j == 0) printf("Created directory \"%s\"\n", data_dir); else { perror("el_index_logbooks"); printf("Cannot create directlry \"%s\"\n", data_dir); } } chdir(str); strcpy(lb_list[n].data_dir, data_dir); lb_list[n].el_index = NULL; printf("Indexing logbook \"%s\"...\n", logbook); status = el_build_index(&lb_list[n], FALSE); if (status == EL_EMPTY) printf("Found empty logbook \"%s\"\n", logbook); else if (status == EL_UPGRADE) { printf("Please upgrade data files in \"%s\" with the elconv program.\n", data_dir); return EL_UPGRADE; } else if (status != EL_SUCCESS) { printf("Error generating index.\n"); return status; } n++; } return EL_SUCCESS; } /*------------------------------------------------------------------*/ int el_search_message(LOGBOOK *lbs, int mode, int message_id, BOOL head_only) /********************************************************************\ Routine: el_search_message Purpose: Search for a specific message in a logbook Input: int mode Search mode, EL_FIRST, EL_LAST, EL_NEXT, EL_PREV int message_id Message id for EL_NEXT and EL_PREV Function value: int New message id \********************************************************************/ { int i; if (lbs->n_el_index == 0) return 0; if (mode == EL_FIRST) { if (head_only) { for (i=0 ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].thread_head) return lbs->el_index[i].message_id; return 0; } if (*lbs->n_el_index == 0) return 0; return lbs->el_index[0].message_id; } if (mode == EL_LAST) { if (head_only) { for (i=*lbs->n_el_index-1 ; i>=0 ; i--) if (lbs->el_index[i].thread_head) return lbs->el_index[i].message_id; return 0; } if (*lbs->n_el_index == 0) return 0; return lbs->el_index[*lbs->n_el_index-1].message_id; } if (mode == EL_NEXT) { for (i=0 ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].message_id == message_id) break; if (i == *lbs->n_el_index) return 0; // message not found if (i == *lbs->n_el_index-1) return 0; // last message if (head_only) { for (i++ ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].thread_head) return lbs->el_index[i].message_id; return 0; } return lbs->el_index[i+1].message_id; } if (mode == EL_PREV) { for (i=0 ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].message_id == message_id) break; if (i == *lbs->n_el_index) return 0; // message not found if (i == 0) return 0; // first message if (head_only) { for (i-- ; i>=0 ; i--) if (lbs->el_index[i].thread_head) return lbs->el_index[i].message_id; return 0; } return lbs->el_index[i-1].message_id; } return 0; } /*------------------------------------------------------------------*/ INT el_retrieve(LOGBOOK *lbs, int message_id, 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 *in_reply_to, char *reply_to, char attachment[MAX_ATTACHMENTS][256], char *encoding) /********************************************************************\ Routine: el_retrieve Purpose: Retrieve an ELog entry by its message tab Input: LOGBOOK lbs Logbook structure int message_id Message ID to retrieve 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 *in_reply_to Original message if this one is a reply char *reply_to Replies 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_EMPTY Logbook is empty EL_NO_MSG Message doesn't exist EL_FILE_ERROR Internal error \********************************************************************/ { int i, index, size, fh; char str[256], file_name[256], *p; char message[TEXT_SIZE+1000], attachment_all[64*MAX_ATTACHMENTS]; if (message_id == 0) /* open most recent message */ message_id = el_search_message(lbs, EL_LAST, 0, FALSE); if (message_id == 0) return EL_EMPTY; for (index = 0 ; index < *lbs->n_el_index ; index++) if (lbs->el_index[index].message_id == message_id) break; if (index == *lbs->n_el_index) return EL_NO_MSG; sprintf(file_name, "%s%s", lbs->data_dir, lbs->el_index[index].file_name); fh = open(file_name, O_RDWR | O_BINARY, 0644); if (fh < 0) { /* file might have been deleted, rebuild index */ el_build_index(lbs, TRUE); return el_retrieve(lbs, message_id, date, attr_list, attrib, n_attr, text, textsize, in_reply_to, reply_to, attachment, encoding); } lseek(fh, lbs->el_index[index].offset, SEEK_SET); i = read(fh, message, sizeof(message)-1); if (i <= 0) { close(fh); return EL_FILE_ERROR; } message[i] = 0; close(fh); if (strncmp(message, "$@MID@$:", 8) != 0) { /* file might have been edited, rebuild index */ el_build_index(lbs, TRUE); return el_retrieve(lbs, message_id, date, attr_list, attrib, n_attr, text, textsize, in_reply_to, reply_to, attachment, encoding); } /* check for correct ID */ if (atoi(message+8) != message_id) return EL_FILE_ERROR; /* decode message size */ p = strstr(message+8, "$@MID@$:"); if (p == NULL) size = strlen(message); else size = (int) p - (int) message; message[size] = 0; /* decode message */ if (date) el_decode(message, "Date: ", date); if (reply_to) el_decode(message, "Reply to: ", reply_to); if (in_reply_to) el_decode(message, "In reply to: ", in_reply_to); if (attrib) for (i=0 ; i \r conversion (e.g. zipping/unzipping) */ if (p == NULL) p = strstr(message, "========================================\r"); if (text) { 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 CR at end */ if (text[strlen(text)-1] == '\n') { text[strlen(text)-1] = 0; if (text[strlen(text)-1] == '\r') text[strlen(text)-1] = 0; } *textsize = strlen(text); } } else { text[0] = 0; *textsize = 0; } } return EL_SUCCESS; } /*------------------------------------------------------------------*/ int el_submit(LOGBOOK *lbs, int message_id, char *date, char attr_name[MAX_N_ATTR][NAME_LENGTH], char attr_value[MAX_N_ATTR][NAME_LENGTH], int n_attr, char *text, char *in_reply_to, char *reply_to, char *encoding, char afilename[MAX_ATTACHMENTS][256], char *buffer[MAX_ATTACHMENTS], INT buffer_size[MAX_ATTACHMENTS], BOOL mark_original) /********************************************************************\ Routine: el_submit Purpose: Submit an ELog entry Input: LOGBOOK lbs Logbook structure int message_id Message id for existing message, 0 for new message char *date Message date char attr_name[][] Name of attributes char attr_value[][] Value of attributes int n_attr Number of attributes char *text Message text char *in_reply_to In reply to this message char *reply_to Replie(s) 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 BOOL mark_original Tag original message for replies Function value: int New message ID \********************************************************************/ { INT n, i, j, size, fh, index, tail_size, orig_size, delta, reply_id; struct tm tms; char file_name[256], afile_name[MAX_ATTACHMENTS][256], dir[256], str[256], attachment_all[64*MAX_ATTACHMENTS], rep1[256], rep2[256]; time_t now, ltime; char message[TEXT_SIZE+100], *p; BOOL bedit; 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, lbs->data_dir); time(&now); memcpy(&tms, localtime(&now), sizeof(struct tm)); 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, lbs->data_dir); bedit = (message_id > 0); rep1[0] = rep2[0] = 0; if (bedit) { /* edit existing message */ for (index=0 ; index<*lbs->n_el_index ; index++) if (lbs->el_index[index].message_id == message_id) break; if (index == *lbs->n_el_index) return -1; sprintf(file_name, "%s%s", lbs->data_dir, lbs->el_index[index].file_name); fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644); if (fh < 0) return -1; lseek(fh, lbs->el_index[index].offset, SEEK_SET); i = read(fh, message, sizeof(message)-1); message[i] = 0; /* check for valid message */ if (strncmp(message, "$@MID@$:", 8) != 0) { close(fh); /* file might have been edited, rebuild index */ el_build_index(lbs, TRUE); return el_submit(lbs, message_id, date, attr_name, attr_value, n_attr, text, in_reply_to, reply_to, encoding, afilename, buffer, buffer_size, TRUE); } /* check for correct ID */ if (atoi(message+8) != message_id) { close(fh); return -1; } /* decode message size */ p = strstr(message+8, "$@MID@$:"); if (p == NULL) size = strlen(message); else size = (int) p - (int) message; message[size] = 0; if (equal_ustring(date, "")) el_decode(message, "Date: ", date); if (equal_ustring(reply_to, "")) el_decode(message, "Reply to: ", reply_to); if (equal_ustring(in_reply_to, "")) el_decode(message, "In reply to: ", in_reply_to); el_decode(message, "Attachment: ", attachment_all); /* buffer tail of logfile */ lseek(fh, 0, SEEK_END); orig_size = size; tail_size = TELL(fh) - (lbs->el_index[index].offset+size); if (tail_size > 0) { buffer = malloc(tail_size); if (buffer == NULL) { close(fh); return -1; } lseek(fh, lbs->el_index[index].offset+size, SEEK_SET); n = read(fh, buffer, tail_size); } lseek(fh, lbs->el_index[index].offset, SEEK_SET); } else { /* create new message */ if (!date[0]) { time(&now); strcpy(date, ctime(&now)); date[24] = 0; } for (i=0 ; i<12 ; i++) if (strncmp(date+4, mname[i], 3) == 0) break; memset(&tms, 0, sizeof(struct tm)); tms.tm_mon = i; tms.tm_mday = atoi(date+8); tms.tm_hour = atoi(date+11); tms.tm_min = atoi(date+14); tms.tm_sec = atoi(date+17); tms.tm_year = atoi(date+20)-1900; if (tms.tm_year < 90) tms.tm_year += 100; ltime = mktime(&tms); if (date[8] == ' ') date[8] = '0'; sprintf(file_name, "%c%c%02d%c%ca.log", date[22], date[23], i+1, date[8], date[9]); sprintf(str, "%s%s", dir, file_name); fh = open(str, O_CREAT | O_RDWR | O_BINARY, 0644); if (fh < 0) return -1; lseek(fh, 0, SEEK_END); /* new message id is old plus one */ message_id = 1; for (i= 0 ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].message_id >= message_id) message_id = lbs->el_index[i].message_id + 1; /* enter message in index */ (*lbs->n_el_index)++; lbs->el_index = realloc(lbs->el_index, sizeof(EL_INDEX)*(*lbs->n_el_index)); lbs->el_index[*lbs->n_el_index-1].message_id = message_id; strcpy(lbs->el_index[*lbs->n_el_index-1].file_name, file_name); lbs->el_index[*lbs->n_el_index-1].file_time = ltime; lbs->el_index[*lbs->n_el_index-1].offset = TELL(fh); lbs->el_index[*lbs->n_el_index-1].thread_head = (in_reply_to[0] == 0); /* if index not ordered, sort it */ i = *lbs->n_el_index; if (i > 1 && lbs->el_index[i-1].file_time < lbs->el_index[i-2].file_time) qsort(lbs->el_index, i, sizeof(EL_INDEX), eli_compare); /* if other logbook has same index, update pointers */ for (i=0 ; lb_list[i].name[0] ; i++) if (&lb_list[i] != lbs && lb_list[i].n_el_index == lbs->n_el_index) lb_list[i].el_index = lbs->el_index; } /* compose message */ sprintf(message, "$@MID@$: %d\n", message_id); sprintf(message+strlen(message), "Date: %s\n", date); if (reply_to[0]) sprintf(message+strlen(message), "Reply to: %s\n", reply_to); if (in_reply_to[0]) sprintf(message+strlen(message), "In reply to: %s\n", in_reply_to); for (i=0 ; i")))) { /* delete old attachment */ strcpy(str, lbs->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), "%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), "%s", p); n++; } else sprintf(message+strlen(message), ",%s", p); } } } else { sprintf(message+strlen(message), afile_name[0]); for (i=1 ; i 0) { n = write(fh, buffer, tail_size); free(buffer); /* correct offsets for remaining messages in same file */ delta = strlen(message) - orig_size; for (i=0 ; i<*lbs->n_el_index ; i++) if (lbs->el_index[i].message_id == message_id) break; for (j = i+1 ; j<*lbs->n_el_index && equal_ustring(lbs->el_index[i].file_name, lbs->el_index[j].file_name); j++) lbs->el_index[j].offset += delta; } /* truncate file here */ #ifdef _MSC_VER chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif } close(fh); /* if reply, mark original message */ if (mark_original && in_reply_to[0] && !bedit && atoi(in_reply_to) > 0) { char date[80], attr[MAX_N_ATTR][NAME_LENGTH], enc[80], att[MAX_ATTACHMENTS][256], reply_to[256]; reply_id = atoi(in_reply_to); /* retrieve original message */ size = sizeof(message); el_retrieve(lbs, reply_id, date, attr_list, attr, n_attr, message, &size, in_reply_to, reply_to, att, enc); if (reply_to[0]) strcat(reply_to, ", "); sprintf(reply_to + strlen(reply_to), "%d", message_id); /* don't resubmit attachments */ memset(att, 0, sizeof(att)); /* write modified message */ el_submit(lbs, reply_id, date, attr_list, attr, n_attr, message, in_reply_to, reply_to, enc, att, NULL, NULL, TRUE); } return message_id; } /*------------------------------------------------------------------*/ void remove_reference(LOGBOOK *lbs, int message_id, int remove_id, BOOL reply_to_flag) { char date[80], attr[MAX_N_ATTR][NAME_LENGTH], enc[80], in_reply_to[80], reply_to[256], att[MAX_ATTACHMENTS][256]; char *p, *ps, message[TEXT_SIZE+1000]; int size, status; /* retrieve original message */ size = sizeof(message); status = el_retrieve(lbs, message_id, date, attr_list, attr, lbs->n_attr, message, &size, in_reply_to, reply_to, att, enc); if (status != EL_SUCCESS) return; if (reply_to_flag) p = reply_to; else p = in_reply_to; while (*p) { while (*p && (*p == ',' || *p == ' ')) p++; ps = p; while (isdigit(*ps)) ps++; while (*ps && (*ps == ',' || *ps == ' ')) ps++; if (atoi(p) == remove_id) strcpy(p, ps); else while (isdigit(*p)) p++; } /* don't resubmit attachments */ memset(att, 0, sizeof(att)); /* write modified message */ el_submit(lbs, message_id, date, attr_list, attr, lbs->n_attr, message, in_reply_to, reply_to, enc, att, NULL, NULL, TRUE); } /*------------------------------------------------------------------*/ INT el_delete_message(LOGBOOK *lbs, int message_id, BOOL delete_attachments, char attachment[MAX_ATTACHMENTS][256], BOOL delete_bw_ref, BOOL delete_reply_to) /********************************************************************\ Routine: el_delete_message Purpose: Delete an ELog entry including attachments Input: LOGBOOK *lbs Pointer to logbook structure int message_id Message ID BOOL delete_attachments Delete attachments if TRUE char attachment Used to return attachments (on move) BOOL delete_bw_ref If true, delete backward references BOOL delete_reply_to If true, delete replies to this message Output: Function value: EL_SUCCESS Successful completion \********************************************************************/ { INT i, index, n, size, fh, tail_size; char str[256], file_name[256], reply_to[80], in_reply_to[256]; char *buffer, *p; char message[TEXT_SIZE+1000], attachment_all[64*MAX_ATTACHMENTS]; for (index = 0 ; index < *lbs->n_el_index ; index++) if (lbs->el_index[index].message_id == message_id) break; if (index == *lbs->n_el_index) return -1; sprintf(file_name, "%s%s", lbs->data_dir, lbs->el_index[index].file_name); fh = open(file_name, O_RDWR | O_BINARY, 0644); if (fh < 0) return EL_FILE_ERROR; lseek(fh, lbs->el_index[index].offset, SEEK_SET); i = read(fh, message, sizeof(message)-1); if (i <= 0) { close(fh); return EL_FILE_ERROR; } message[i] = 0; if (strncmp(message, "$@MID@$:", 8) != 0) { close(fh); /* file might have been edited, rebuild index */ el_build_index(lbs, TRUE); return el_delete_message(lbs, message_id, delete_attachments, attachment, delete_bw_ref, delete_reply_to); } /* check for correct ID */ if (atoi(message+8) != message_id) { close(fh); return EL_FILE_ERROR; } /* decode message size */ p = strstr(message+8, "$@MID@$:"); if (p == NULL) size = strlen(message); else size = (int) p - (int) message; message[size] = 0; /* delete attachments */ el_decode(message, "Attachment: ", attachment_all); for (i=0 ; idata_dir); strcat(str, p); remove(str); } /* return old attachment if no new one */ if (!attachment[i][0] && p) strcpy(attachment[i], p); } if (delete_attachments && p) { strcpy(str, lbs->data_dir); strcat(str, p); remove(str); } } /* decode references */ el_decode(message, "Reply to: ", reply_to); el_decode(message, "In reply to: ", in_reply_to); /* buffer tail of logfile */ lseek(fh, 0, SEEK_END); tail_size = TELL(fh) - (lbs->el_index[index].offset+size); if (tail_size > 0) { buffer = malloc(tail_size); if (buffer == NULL) { close(fh); return EL_FILE_ERROR; } lseek(fh, lbs->el_index[index].offset+size, SEEK_SET); n = read(fh, buffer, tail_size); } lseek(fh, lbs->el_index[index].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); /* remove message from index */ strcpy(str, lbs->el_index[index].file_name); for (i=index ; i<*lbs->n_el_index-1 ; i++) { memcpy(&lbs->el_index[i], &lbs->el_index[i+1], sizeof(EL_INDEX)); if (equal_ustring(lbs->el_index[i].file_name, str)) lbs->el_index[i].offset -= size; } (*lbs->n_el_index)--; lbs->el_index = realloc(lbs->el_index, sizeof(EL_INDEX)*(*lbs->n_el_index)); /* if other logbook has same index, update pointers */ for (i=0 ; lb_list[i].name[0] ; i++) if (&lb_list[i] != lbs && lb_list[i].n_el_index == lbs->n_el_index) lb_list[i].el_index = lbs->el_index; /* delete also replies to this message */ if (delete_reply_to && reply_to[0]) { p = reply_to; if (isdigit(*p)) do { if (atoi(p)) el_delete_message(lbs, atoi(p), TRUE, NULL, FALSE, TRUE); while (*p && isdigit(*p)) p++; while (*p && (*p == ',' || *p == ' ')) p++; } while(*p); } /* delete backward references */ if (in_reply_to[0] && delete_bw_ref) { p = in_reply_to; do { if (atoi(p)) remove_reference(lbs, atoi(p), message_id, TRUE); while (*p && isdigit(*p)) p++; while (*p && (*p == ',' || *p == ' ')) p++; } while(*p); } return EL_SUCCESS; } /*------------------------------------------------------------------*/ int el_correct_links(LOGBOOK *lbs, int old_id, int new_id) /* If a message gets resubmitted, the links to that message are wrong. This routine corrects that. */ { int i, i1, n, n1, size; char date[80], attrib[MAX_N_ATTR][NAME_LENGTH], text[TEXT_SIZE], in_reply_to[80], reply_to[256], encoding[80]; char list[MAX_N_ATTR][NAME_LENGTH], list1[MAX_N_ATTR][NAME_LENGTH]; char att_file[MAX_ATTACHMENTS][256]; el_retrieve(lbs, new_id, date, attr_list, attrib, lbs->n_attr, NULL, 0, in_reply_to, reply_to, att_file, encoding); /* go through in_reply_to list */ n = strbreak(in_reply_to, list, MAX_N_ATTR); for (i=0 ; in_attr, text, &size, in_reply_to, reply_to, att_file, encoding); n1 = strbreak(reply_to, list1, MAX_N_ATTR); reply_to[0] = 0; for (i1 = 0 ; i1 < n1 ; i1++) { /* replace old ID by new ID */ if (atoi(list1[i1]) == old_id) sprintf(reply_to+strlen(reply_to), "%d", new_id); else strcat(reply_to, list1[i1]); if (i1 < n1-1) strcat(reply_to, ", "); } el_submit(lbs, atoi(list[i]), date, attr_list, attrib, lbs->n_attr, text, in_reply_to, reply_to, encoding, att_file, _attachment_buffer, _attachment_size, TRUE); } el_retrieve(lbs, new_id, date, attr_list, attrib, lbs->n_attr, NULL, 0, in_reply_to, reply_to, att_file, encoding); /* go through reply_to list */ n = strbreak(reply_to, list, MAX_N_ATTR); for (i=0 ; in_attr, text, &size, in_reply_to, reply_to, att_file, encoding); n1 = strbreak(in_reply_to, list1, MAX_N_ATTR); in_reply_to[0] = 0; for (i1 = 0 ; i1 < n1 ; i1++) { /* replace old ID by new ID */ if (atoi(list1[i1]) == old_id) sprintf(in_reply_to+strlen(in_reply_to), "%d", new_id); else strcat(in_reply_to, list1[i1]); if (i1 < n1-1) strcat(in_reply_to, ", "); } el_submit(lbs, atoi(list[i]), date, attr_list, attrib, lbs->n_attr, text, in_reply_to, reply_to, encoding, att_file, _attachment_buffer, _attachment_size, TRUE); } return EL_SUCCESS; } /*------------------------------------------------------------------*/ int el_move_message_thread(LOGBOOK *lbs, int message_id) { int i, n, size, new_id; char date[80], attrib[MAX_N_ATTR][NAME_LENGTH], text[TEXT_SIZE], in_reply_to[80], reply_to[256], encoding[80]; char list[MAX_N_ATTR][NAME_LENGTH]; char att_file[MAX_ATTACHMENTS][256]; /* retrieve message */ size = sizeof(text); el_retrieve(lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, in_reply_to, reply_to, att_file, encoding); /* submit as new message */ date[0] = 0; new_id = el_submit(lbs, 0, date, attr_list, attrib, lbs->n_attr, text, in_reply_to, reply_to, encoding, att_file, _attachment_buffer, _attachment_size, FALSE); /* correct links */ el_correct_links(lbs, message_id, new_id); /* delete original message */ el_delete_message(lbs, message_id, FALSE, NULL, FALSE, FALSE); /* move all replies recursively */ if (reply_to[0]) { n = strbreak(reply_to, list, MAX_N_ATTR); for (i=0 ; i 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 if (strncmp(str+i, "elog:", 5) == 0) { p = (char *) (str+i+5); i += 5; for (k=0 ; *p && *p != '>' && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++) link[k] = *p++; link[k] = 0; i--; /* if link contains '/' (reference to other logbook), add ".." in front */ if (strchr(link, '/')) sprintf(return_buffer+j, "elog:%s", link, link); else sprintf(return_buffer+j, "elog:%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; _cmdline[0] = 0; } int setparam(char *param, char *value) { int i; char str[10000]; 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; } if (equal_ustring(param, "cmdline")) { if (strlen(value) >= CMD_SIZE) { sprintf(str, "Error: Command line too big (%d bytes). Please increase CMD_SIZE and recompile elogd\n", strlen(value)); show_error(str); return 0; } strncpy(_cmdline, value, CMD_SIZE); _cmdline[CMD_SIZE-1] = 0; return 1; } /* paremeters can be superseeded */ for (i=0 ; i= VALUE_SIZE) { sprintf(str, "Error: Parameter value for parameter %s too big (%d bytes). Please increase VALUE_SIZE and recompile elogd\n", param, strlen(value)); show_error(str); 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; if (equal_ustring(param, "cmdline")) return _cmdline; 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; } /*------------------------------------------------------------------*/ 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 = str; if (!p || !*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(lbs->name, "Types", str);
  rsprintf("Options Type = %s\n", str);
  getcfg(lbs->name, "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_http_header() { char str[256]; rsprintf("HTTP/1.1 200 Document follows\r\n"); rsprintf("Server: ELOG HTTP %s\r\n", VERSION); if (getcfg("global", "charset", str)) rsprintf("Content-Type: text/html;charset=%s\r\n", str); else 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"); } void show_standard_header(char *title, char *path) { show_http_header(); 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, j; /* 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(logbook, "logbook tabs", str) && atoi(str) == 1) { rsprintf("\n\n"); } /*---- title row ----*/ rsprintf("\n\n"); } /*------------------------------------------------------------------*/ void show_error(char *error) { /* header */ show_standard_header("ELOG error", ""); rsprintf("

\n"); if (getcfg("global", "main tab", str)) rsprintf(" %s  \n", str); 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(" ", gt("Title fontcolor"), gt("Title BGColor")); for (j=0 ; j<(int)strlen(str) ; j++) if (str[j] == ' ') rsprintf(" "); else rsprintf("%c", str[j]); rsprintf("  \n"); } else { rsprintf(" "); rsprintf("", ref); for (j=0 ; j<(int)strlen(str) ; j++) if (str[j] == ' ') rsprintf(" "); else rsprintf("%c", str[j]); rsprintf("  \n"); } } rsprintf("
\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")); } else { if (getcfg(logbook, "Guest menu commands", str)) { rsprintf("\n", gt("Title fontcolor"), loc("Not logged in")); } } /* 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")); rsprintf("  %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 set_login_cookies(LOGBOOK *lbs, char *user, char *enc_pwd) { char str[256], str2[256], lb_name[256]; double exp; time_t now; struct tm *gmt; 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"); } if (lbs) strcpy(lb_name, lbs->name); else strcpy(lb_name, "global"); /* get optional expriation from configuration file */ exp = 0; if (getcfg(lb_name, "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", user); } else { rsprintf("Set-Cookie: upwd=%s\r\n", enc_pwd); rsprintf("Set-Cookie: unm=%s\r\n", user); } } 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", str2)) { rsprintf("Set-Cookie: upwd=%s; path=/; expires=%s\r\n", enc_pwd, str); rsprintf("Set-Cookie: unm=%s; path=/; expires=%s\r\n", user, str); } else { rsprintf("Set-Cookie: upwd=%s; expires=%s\r\n", enc_pwd, str); rsprintf("Set-Cookie: unm=%s; expires=%s\r\n", user, str); } } sprintf(str, "%s", getparam("redir")); if (!str[0]) { if (lbs) sprintf(str, "../%s/", lbs->name_enc); else sprintf(str, "."); } rsprintf("Location: %s\r\n\r\nredir\r\n", str); return; } /*------------------------------------------------------------------*/ 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(LOGBOOK *lbs, 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; /* copy attribute list */ for (i=0 ; in_attr ; i++) { strcpy(list[i], attr_list[i]); if (attrib) strcpy(value[i], attrib[i]); else strcpy(value[i], getparam(attr_list[i])); } /* add remote host */ strcpy(list[i], "remote_host"); strcpy(value[i++], rem_host); /* 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 email */ strcpy(list[i], "user_email"); strcpy(value[i], "mailto:"); strcat(value[i++], getparam("user_email")); /* add logbook */ strcpy(list[i], "logbook"); strcpy(value[i++], lbs->name); /* add date */ strcpy(list[i], "date"); time(&now); ts = localtime(&now); if (getcfg(lbs->name, "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(LOGBOOK *lbs) { char str[256], str2[256], file_name[256], line[256], *p, *pl, old_pwd[32], new_pwd[32], new_pwd2[32], user[80]; char *buf; int i, fh, wrong_pwd, size; do_crypt(getparam("oldpwd"), old_pwd); do_crypt(getparam("newpwd"), new_pwd); do_crypt(getparam("newpwd2"), new_pwd2); strcpy(user, getparam("unm")); if (isparam("config")) strcpy(user, getparam("config")); getcfg(lbs->name, "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]) { fh = open(file_name, O_RDWR | O_BINARY, 644); if (fh > 0) { lseek(fh, 0, SEEK_END); size = TELL(fh); lseek(fh, 0, SEEK_SET); buf = malloc(size+1); read(fh, buf, size); 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, user) == 0) break; pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; } /* if user found, check old password */ if (user[0] && (strcmp(str, user) == 0)) { p = line+strlen(str); if (*p) p++; strcpy(str2, p); if (strchr(str2, ':')) *strchr(str2, ':') = 0; if (getcfg(lbs->name, "Admin user", str) && strstr(str, getparam("unm")) != 0) wrong_pwd = 0; else { if (strcmp(old_pwd, str2) != 0) wrong_pwd = 1; } if (strcmp(new_pwd, new_pwd2) != 0) wrong_pwd = 2; } /* replace password */ if (!wrong_pwd) { lseek(fh, 0, SEEK_SET); write(fh, buf, pl-buf); sprintf(str, "%s:%s:%s:%s\n", user, new_pwd, getparam("full_name"), getparam("user_email")); write(fh, str, strlen(str)); pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; write(fh, pl, strlen(pl)); #ifdef _MSC_VER chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif } free(buf); close(fh); if (!wrong_pwd && strcmp(user, getparam("unm")) == 0) { set_login_cookies(lbs, user, new_pwd); return; } if (!wrong_pwd) { redirect("."); return; } } } show_standard_header(loc("ELOG change password"), NULL); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); if (wrong_pwd == 1) rsprintf("\n", loc("Wrong password")); if (wrong_pwd == 2) rsprintf("\n", loc("New passwords do not match, please retype")); rsprintf("\n", gt("Title fontcolor"), loc("Change password for user"), user); if (!getcfg(lbs->name, "Admin user", str) || !strstr(str, getparam("unm")) != 0) { rsprintf("\n", gt("Cell BGColor"), loc("Old Password")); } rsprintf("\n", gt("Cell BGColor"), loc("New Password")); rsprintf("\n", gt("Cell BGColor"), loc("Retype new password")); rsprintf("", gt("Cell BGColor"), loc("Submit")); rsprintf("
%s!
%s!
\n", gt("Title bgcolor")); rsprintf("", user); rsprintf("%s \"%s\"
%s:     
%s:     
%s:     
\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ BOOL allow_user(LOGBOOK *lbs, char *command) { char str[1000], users[2000]; char list[MAX_N_LIST][NAME_LENGTH]; int i, n; /* check for user level access */ if (!getcfg(lbs->name, "Password file", str)) return TRUE; /* check for deny */ sprintf(str, "Deny %s", command); if (getcfg(lbs->name, str, users)) { /* check if current user in list */ n = strbreak(users, list, MAX_N_LIST); for (i=0 ; iname, "Admin user", str)) { if (strstr(str, getparam("unm")) != 0) return TRUE; else return FALSE; } } /* check for allow */ sprintf(str, "Allow %s", unloc(command)); if (!getcfg(lbs->name, str, users)) return TRUE; /* check if current user in list */ n = strbreak(users, list, MAX_N_LIST); for (i=0 ; in_attr, NULL, 0, in_reply_to, reply_to, 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(LOGBOOK *lbs, int message_id, BOOL bedit) { int i, j, n, index, size, width, height, 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; for (i=0 ; in_attr ; i++) attrib[i][0] = 0; if (message_id) { /* get message for reply */ size = sizeof(text); el_retrieve(lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, orig_tag, reply_tag, att, encoding); } else { /* get preset attributes */ for (i=0 ; in_attr ; i++) { sprintf(str, "p%s", attr_list[i]); strcpy(attrib[i], getparam(str)); } } /* check for author */ if (bedit && getcfg(lbs->name, "Restrict edit", str) && atoi(str) == 1) { /* search attribute which contains author */ for (i=0 ; in_attr ; i++) { sprintf(str, "Preset %s", attr_list[i]); if (getcfg(lbs->name, str, preset)) { if (strstr(preset, "$short_name")) { if (strstr(attrib[i], getparam("unm")) == NULL) { sprintf(str, loc("Only user %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 (message_id && !bedit) { getcfg(lbs->name, "Remove on reply", str); n = strbreak(str, list, MAX_N_ATTR); for (i=0 ; in_attr ; j++) { if (equal_ustring(attr_list[j], list[i])) attrib[j][0] = 0; } } /* subst attributes for replies */ if (message_id && !bedit) { for (index = 0 ; index < lbs->n_attr ; index++) { sprintf(str, "Subst on reply %s", attr_list[index]); if (getcfg(lbs->name, str, preset)) { /* check if already second reply */ if (orig_tag[0] == 0) { i = build_subst_list(lbs, slist, svalue, attrib); strsubst(preset, slist, svalue, i); strcpy(attrib[index], preset); } } } } /* header */ show_http_header(); rsprintf("ELOG\n"); rsprintf("\n"); /*---- add password in case cookie expires during edit ----*/ if (getcfg(lbs->name, "Write password", str)) rsprintf("\n", str); if (getcfg(lbs->name, "Password file", str)) { rsprintf("\n", getparam("unm")); rsprintf("\n", getparam("upwd")); } /*---- title row ----*/ show_standard_title(lbs->name, "", 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 < lbs->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(lbs->name, "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; ts.tm_isdst = -1; /* let mktime compute DST */ 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(lbs->name, "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 < lbs->n_attr ; index++) { strcpy(star, (attr_flags[index] & AF_REQUIRED) ? "*" : ""); /* check for preset string */ sprintf(str, "Preset %s", attr_list[index]); if (getcfg(lbs->name, str, preset)) { if (!bedit) { i = build_subst_list(lbs, slist, svalue, NULL); strsubst(preset, slist, svalue, i); /* check for index substitution */ if (!bedit && strchr(preset, '%')) { /* get index */ i = get_last_index(lbs, 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_EDIT)) || (message_id && !bedit && (attr_flags[index] & AF_FIXED_REPLY))) { 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_RADIO) { /* display radio buttons */ rsprintf("\n"); } else if (attr_flags[index] & AF_ICON) { /* display icons */ rsprintf("\n"); } else { /* display drop-down box */ rsprintf("\n"); } } } } } if (message_id) { /* hidden text for original message */ rsprintf("\n", message_id); if (bedit) rsprintf("\n"); } rsprintf("\n"); /* set textarea width */ width = 76; if (getcfg(lbs->name, "Message width", str)) width = atoi(str); /* increased wrapping width for replies (leave space for '> ' */ if (message_id && !bedit) width += 2; /* set textarea height */ height = 20; if (getcfg(lbs->name, "Message height", str)) height = atoi(str); rsprintf("\n"); if (getcfg(lbs->name, "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:\n", gt("Categories bgcolor2")); rsputs2(attrib[index]); if (attr_flags[index] & AF_MULTI) { for (i=0 ; i\n", str, attr_options[index][i]); } } else if (attr_flags[index] & AF_RADIO) { 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%s \n", attr_list[index], attr_options[index][i], attr_options[index][i]); else rsprintf("%s \n", attr_list[index], 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(lbs->name, "Message comment", comment) && !bedit && !message_id) { rsputs(comment); rsputs("
\n"); } if (!getcfg(lbs->name, "Show text", str) || atoi(str) == 1) { rsprintf("
\n"); /* HTML check box */ if (message_id) { if (getcfg(lbs->name, "HTML default", str)) { if (atoi(str) < 2) { if (encoding[0] == 'H') rsprintf("%s\n", loc("Submit as HTML text")); else rsprintf("%s\n", loc("Submit as HTML text")); } else if (atoi(str) == 3) { rsprintf("\n"); } } else { if (encoding[0] == 'H') rsprintf("%s\n", loc("Submit as HTML text")); else rsprintf("%s\n", loc("Submit as HTML text")); } } else { if (getcfg(lbs->name, "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 if (atoi(str) == 3) { rsprintf("\n"); } } else rsprintf("%s\n", loc("Submit as HTML text")); } } /* Suppress check box */ if ( !(bedit && getcfg(lbs->name, "Suppress Email on edit", str) && atoi(str) == 1) ) { if (getcfg(lbs->name, "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(lbs->name, "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(LOGBOOK *lbs) { int i, j; char str[256], mode[256]; /*---- header ----*/ show_standard_header(loc("ELOG find"), NULL); /*---- title ----*/ show_standard_title(lbs->name, "", 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")); rsprintf("\n"); if (!getcfg(lbs->name, "Number attachments", str) || atoi(str) > 0) { rsprintf("\n", loc("Show attachments")); } rsprintf("\n", loc("Printable output")); rsprintf("\n", loc("Sort in reverse order")); else rsprintf("%s\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(lbs->name, "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 ; in_attr ; i++) { rsprintf("", gt("Categories bgcolor1"), attr_list[i]); rsprintf("\n"); } if (!getcfg(lbs->name, "Show text", str) || atoi(str) == 1) { rsprintf("", gt("Categories bgcolor1"), loc("Text")); rsprintf("\n", loc("(case insensitive substring)")); } rsprintf("
", gt("Categories bgcolor2")); rsprintf("Mode:  "); if (!getcfg(lbs->name, "Display mode", mode)) strcpy(mode, "Full"); if (!getcfg(lbs->name, "Show text", str) || atoi(str) == 1) { if (equal_ustring(mode, "Full")) rsprintf("%s  \n", loc("Display full message")); else rsprintf("%s  \n", loc("Display full message")); if (equal_ustring(mode, "Summary")) rsprintf("%s  \n", loc("Summary only")); else rsprintf("%s  \n", loc("Summary only")); if (equal_ustring(mode, "Threaded")) rsprintf("%s  \n", loc("Display threads")); else rsprintf("%s  \n", loc("Display threads")); } rsprintf("
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); if (getcfg(lbs->name, "Reverse sort", str) && atoi(str) == 1) rsprintf("%s
", gt("Categories bgcolor2")); rsprintf("%s
", gt("Categories bgcolor2")); rsprintf(loc("Display")); if (!getcfg(lbs->name, "Entries per page", str)) strcpy(str, "20"); rsprintf(" ", str); rsprintf(loc("entries per page")); rsprintf("
%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_admin_page(LOGBOOK *lbs) { int fh, length; char *buffer; /*---- header ----*/ show_http_header(); rsprintf("ELOG config\n"); rsprintf("

\n"); /*---- title ----*/ show_standard_title(lbs->name, "", 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"); /* put link for config page */ rsprintf("Syntax Help"); 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_admin_config() { int fh, i; char str[80]; fh = open(cfg_file, O_RDWR | O_BINARY | O_TRUNC, 644); if (fh < 0) { sprintf(str, loc("Cannot open file %s"), cfg_file); strcat(str, ": "); strcat(str, strerror(errno)); show_error(str); return 0; } i = write(fh, _text, strlen(_text)); if (i < (int)strlen(_text)) { sprintf(str, loc("Cannot write to %s"), cfg_file); strcat(str, ": "); strcat(str, strerror(errno)); show_error(str); close(fh); return 0; } close(fh); return 1; } /*------------------------------------------------------------------*/ int save_user_config(LOGBOOK *lbs, char *user, BOOL new_user, BOOL activate) { char file_name[256], str[256], line[256], *buf, *pl, new_pwd[80], new_pwd2[80]; char smtp_host[256], email_addr[256], mail_from[256], subject[256], mail_text[2000]; char admin_user[80], enc_pwd[80], url[256]; int i, fh, size, self_register; /* check self register flag */ self_register = 0; if (getcfg(lbs->name, "Self register", str)) self_register = atoi(str); if (!activate) { /* check for hidden password */ if (isparam("hpwd")) { strcpy(new_pwd, getparam("hpwd")); } else { /* check if passwords match */ do_crypt(getparam("newpwd"), new_pwd); do_crypt(getparam("newpwd2"), new_pwd2); if (strcmp(new_pwd, new_pwd2) != 0) { show_error(loc("New passwords do not match, please retype")); return 0; } } } if (activate || !new_user || self_register != 3) /* do not save in mode 3 */ { getcfg(lbs->name, "Password file", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } fh = open(file_name, O_RDWR | O_BINARY | O_CREAT, 644); if (fh < 0) { sprintf(str, loc("Cannot open file %s"), file_name); show_error(str); return 0; } lseek(fh, 0, SEEK_END); size = TELL(fh); lseek(fh, 0, SEEK_SET); buf = malloc(size+1); read(fh, buf, size); 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, user) == 0) { if (new_user) { sprintf(str, "%s \"%s\" %s", loc("Login name"), user, loc("exists already")); show_error(str); free(buf); close(fh); return 0; } break; } pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; } if (new_user) { lseek(fh, 0, SEEK_END); if (strlen(buf) != 0 && (buf[strlen(buf)-1] != '\r' && buf[strlen(buf)-1] != '\n')) write(fh, "\n", 2); if (activate) sprintf(str, "%s:%s:%s:%s:%s\n", getparam("new_user_name"), getparam("encpwd"), getparam("new_full_name"), getparam("new_user_email"), getparam("email_notify")); else sprintf(str, "%s:%s:%s:%s:%s\n", getparam("new_user_name"), new_pwd, getparam("new_full_name"), getparam("new_user_email"), getparam("email_notify")); write(fh, str, strlen(str)); } else { /* replace line */ lseek(fh, 0, SEEK_SET); write(fh, buf, pl-buf); sprintf(str, "%s:%s:%s:%s:%s\n", getparam("new_user_name"), new_pwd, getparam("new_full_name"), getparam("new_user_email"), getparam("email_notify")); write(fh, str, strlen(str)); pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; write(fh, pl, strlen(pl)); #ifdef _MSC_VER chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif } free(buf); close(fh); } /* if requested, send notification email to admin user */ if (new_user && (self_register == 2 || self_register == 3) && !isparam("admin")) { if (!getcfg("global", "SMTP host", smtp_host)) { show_error(loc("No SMTP host defined in [global] section of configuration file")); return 0; } /* try to get URL from referer */ if (!getcfg("global", "URL", url)) { if (referer[0]) strcpy(url, referer); else { if (tcp_port == 80) sprintf(url, "http://%s/", host_name); else sprintf(url, "http://%s:%d/", host_name, tcp_port); } } else { strcat(url, lbs->name); strcat(url, "/"); } if (!getcfg(lbs->name, "Use Email from", mail_from)) sprintf(mail_from, "ELog@%s", host_name); if (activate) { sprintf(subject, loc("Your ELOG account has been activated")); sprintf(mail_text, loc("Your ELOG account has been activated on host %s"), host_name); sprintf(mail_text+strlen(mail_text), ".\r\n\r\n"); sprintf(url+strlen(url), "?cmd=Login&unm=%s", getparam("new_user_name")); sprintf(mail_text+strlen(mail_text), "%s %s\r\n", loc("You can access it at"), url); sendmail(smtp_host, mail_from, getparam("new_user_email"), subject, mail_text); } else { if (getcfg(lbs->name, "Admin user", admin_user)) { pl = strtok(admin_user, " ,"); while (pl) { get_user_line(lbs->name, pl, NULL, NULL, email_addr, NULL); if (email_addr[0]) { /* compose subject */ if (self_register == 3) { sprintf(subject, loc("Registration request on logbook \"%s\""), lbs->name); sprintf(mail_text, loc("A new ELOG user wants to register on %s"), host_name); } else { sprintf(subject, loc("User \"%s\" registered on logbook \"%s\""), getparam("new_user_name"), lbs->name); sprintf(mail_text, loc("A new ELOG user has been registered on %s"), host_name); } sprintf(mail_text+strlen(mail_text), "\r\n\r\n"); sprintf(mail_text+strlen(mail_text), "%s : %s\r\n", loc("Logbook"), lbs->name); sprintf(mail_text+strlen(mail_text), "%s : %s\r\n", loc("Login name"), getparam("new_user_name")); sprintf(mail_text+strlen(mail_text), "%s : %s\r\n", loc("Full name"), getparam("new_full_name")); sprintf(mail_text+strlen(mail_text), "%s : %s\r\n", loc("Email"), getparam("new_user_email")); if (self_register == 3) { sprintf(mail_text+strlen(mail_text), "\r\n%s:\r\n", loc("Hit following URL to activate that account")); sprintf(mail_text+strlen(mail_text), "\r\nURL : %s", url); strcpy(str, getparam("new_full_name")); url_encode(str); do_crypt(getparam("newpwd"), enc_pwd); url_encode(enc_pwd); sprintf(mail_text+strlen(mail_text), "?cmd=Activate&new_user_name=%s&new_full_name=%s&new_user_email=%s&email_notify=%s&encpwd=%s&unm=%s\r\n", getparam("new_user_name"), str, getparam("new_user_email"), getparam("email_notify"), enc_pwd, pl); } else { sprintf(mail_text+strlen(mail_text), "\r\n%s URL : %s?cmd=Config&cfg_user=%s&unm=%s\r\n", loc("Logbook"), url, getparam("new_user_name"), pl); } sendmail(smtp_host, mail_from, email_addr, subject, mail_text); } pl = strtok(NULL, " ,"); } } if (self_register == 3) { redirect("?cmd=Requested"); return 0; } } } /* if user name changed, set cookie */ if (strcmp(user, getparam("new_user_name")) != 0 && strcmp(user, getparam("unm")) == 0) { set_login_cookies(lbs, getparam("new_user_name"), new_pwd); return 0; } /* if new user, login as this user */ if (new_user && !*getparam("unm")) { set_login_cookies(lbs, getparam("new_user_name"), new_pwd); return 0; } return 1; } /*------------------------------------------------------------------*/ int remove_user(LOGBOOK *lbs, char *user) { char file_name[256], str[256], line[256], *buf, *pl; int i, fh, size; getcfg(lbs->name, "Password file", str); if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } fh = open(file_name, O_RDWR | O_BINARY, 0644); if (fh < 0) { sprintf(str, loc("Cannot open file %s"), file_name); strcat(str, ": "); strcat(str, strerror(errno)); show_error(str); return 0; } lseek(fh, 0, SEEK_END); size = TELL(fh); lseek(fh, 0, SEEK_SET); buf = malloc(size+1); read(fh, buf, size); 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, user) == 0) break; pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; } /* remove line */ lseek(fh, 0, SEEK_SET); write(fh, buf, pl-buf); pl += strlen(line); while (*pl && (*pl == '\r' || *pl == '\n')) pl++; write(fh, pl, strlen(pl)); #ifdef _MSC_VER chsize(fh, TELL(fh)); #else ftruncate(fh, TELL(fh)); #endif free(buf); close(fh); return 1; } /*------------------------------------------------------------------*/ void show_config_page(LOGBOOK *lbs) { char str[256], user[80], password[80], full_name[80], user_email[80], email_notify[256]; int i; /*---- header ----*/ show_standard_header(loc("ElOG user config"), "."); /*---- title ----*/ show_standard_title(lbs->name, "", 0); /* get user */ strcpy(user, getparam("unm")); if (isparam("cfg_user")) strcpy(user, getparam("cfg_user")); /*---- menu buttons ----*/ rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf("\n", user); // for select javascript rsprintf("\n", loc("Save")); rsprintf("\n", loc("Cancel")); rsprintf("\n", user); rsprintf("
\n\n"); /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); /*---- if admin user, show user list ----*/ if (getcfg(lbs->name, "Admin user", str) && strstr(str, getparam("unm")) != 0) { rsprintf("\n"); rsprintf("\n", gt("Categories bgcolor1"), loc("Select user")); rsprintf("\n", loc("Go")); } /*---- entry form ----*/ rsprintf("\n", gt("Categories bgcolor1"), loc("Login name")); if (get_user_line(lbs->name, user, password, full_name, user_email, email_notify) != 1) sprintf(str, loc("User [%s] has been deleted"), user); else strcpy(str, user); rsprintf("\n", gt("Categories bgcolor2"), str); rsprintf("\n", gt("Categories bgcolor1"), loc("Full name")); rsprintf("\n", gt("Categories bgcolor2"), full_name); rsprintf("\n", gt("Categories bgcolor1")); rsprintf("\n"); else rsprintf("\n"); rsprintf("
%s:\n"); rsprintf("
%s:
%s:
Email:    \n", gt("Categories bgcolor2"), user_email); rsprintf("%s:\n", loc("Automatic email notifications")); if (email_notify[0]) rsprintf("
", gt("Categories bgcolor2")); rsprintf("\n", loc("Change password")); rsprintf("\n", loc("Remove user")); if (getcfg(lbs->name, "Admin user", str) && strstr(str, getparam("unm")) != 0) { rsprintf("\n", loc("New user")); } /* hidden field for password */ rsprintf("\n", password); rsprintf("
\n"); rsprintf("\n\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_new_user_page(LOGBOOK *lbs) { /*---- header ----*/ show_standard_header(loc("ElOG new user"), ""); /*---- title ----*/ if (lbs) show_standard_title(lbs->name, "", 0); else show_standard_title("ELOG", "", 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"); /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); /*---- entry form ----*/ rsprintf("\n", gt("Categories bgcolor1"), loc("Login name")); rsprintf("\n", gt("Categories bgcolor2"), loc("name may not contain blanks")); rsprintf("\n", gt("Categories bgcolor1"), loc("Full name")); rsprintf("\n", gt("Categories bgcolor2")); rsprintf("\n", gt("Categories bgcolor1")); rsprintf("\n", gt("Categories bgcolor2")); rsprintf("\n", gt("Categories bgcolor1"), loc("Automatic email notifications")); rsprintf("\n", gt("Categories bgcolor2")); rsprintf("\n", gt("Categories bgcolor1"), loc("Password")); rsprintf("\n", gt("Categories bgcolor1"), loc("Retype password")); rsprintf("
%s: (%s)
%s:
Email:
%s:
%s:\n", gt("Categories bgcolor2")); rsprintf("
%s:\n", gt("Categories bgcolor2")); rsprintf("
\n"); rsprintf("\n\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ void show_elog_delete(LOGBOOK *lbs, int message_id) { int i, status, reply, next; char str[256], in_reply_to[80], reply_to[256]; /* redirect if confirm = NO */ if (getparam("confirm") && *getparam("confirm") && strcmp(getparam("confirm"), loc("No")) == 0) { if (message_id) { sprintf(str, "%d", message_id); redirect(str); } else { strcpy(str, getparam("lastcmd")); url_decode(str); redirect(str); } return; } if (getparam("confirm") && *getparam("confirm")) { if (strcmp(getparam("confirm"), loc("Yes")) == 0) { if (message_id) { /* delete message */ status = el_delete_message(lbs, message_id, TRUE, NULL, TRUE, TRUE); if (status != EL_SUCCESS) { sprintf(str, "%s = %d", loc("Error deleting message: status"), status); show_error(str); return; } else { strcpy(str, getparam("nextmsg")); if (atoi(str) == 0) sprintf(str, "%d", el_search_message(lbs, EL_LAST, 0, TRUE)); if (atoi(str) == 0) redirect(""); else redirect(str); return; } } else { for (i=reply=0 ; i

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); /* define hidden field for command */ rsprintf("\n", loc("Delete")); rsprintf("\n", gt("Title fontcolor"), loc("Are you sure to delete these messages?")); rsprintf("\n"); if (reply) rsprintf("\n", gt("Cell BGColor"), loc("and all its replies")); } else { rsprintf("%s\n", gt("Title fontcolor"), loc("Are you sure to delete this message?")); /* check for replies */ /* retrieve original message */ el_retrieve(lbs, message_id, NULL, attr_list, NULL, 0, NULL, NULL, in_reply_to, reply_to, NULL, NULL); if (reply_to[0]) rsprintf("\n", gt("Cell BGColor"), message_id, loc("and all its replies")); else rsprintf("\n", gt("Cell BGColor"), message_id); /* put link to next message */ next = el_search_message(lbs, EL_NEXT, message_id, TRUE); rsprintf("\n", next); } rsprintf("\n\n"); } rsprintf("
", gt("Title bgcolor")); if (!message_id) { rsprintf("%s
\n", gt("Cell BGColor")); rsprintf("\n", getparam("nsel")); if (isparam("lastcmd")) { strcpy(str, getparam("lastcmd")); rsprintf("\n", str); } for (i=reply=0 ; i\n", str, getparam(str)); } if (!reply) { el_retrieve(lbs, atoi(getparam(str)), NULL, attr_list, NULL, 0, NULL, NULL, in_reply_to, reply_to, NULL, NULL); if (reply_to[0]) reply = TRUE; } } rsprintf("
%s
%d
%s
%d
\n", gt("Cell BGColor"), loc("Yes")); rsprintf("\n", loc("No")); rsprintf("
\n"); rsprintf("\r\n"); } /*------------------------------------------------------------------*/ int show_download_page(LOGBOOK *lbs, char *path) { char file_name[256], str[256]; int index, message_id, fh, i, size; char message[TEXT_SIZE+1000], *p; time_t now; struct tm *gmt; message_id = atoi(path); for (index = 0 ; index < *lbs->n_el_index ; index++) if (lbs->el_index[index].message_id == message_id) break; if (index == *lbs->n_el_index) return EL_NO_MSG; sprintf(file_name, "%s%s", lbs->data_dir, lbs->el_index[index].file_name); fh = open(file_name, O_RDWR | O_BINARY, 0644); if (fh < 0) return EL_FILE_ERROR; lseek(fh, lbs->el_index[index].offset, SEEK_SET); i = read(fh, message, sizeof(message)-1); if (i <= 0) { close(fh); return EL_FILE_ERROR; } message[i] = 0; close(fh); /* decode message size */ p = strstr(message+8, "$@MID@$:"); if (p == NULL) size = strlen(message); else size = (int) p - (int) message; message[size] = 0; /* header */ 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"); } rsprintf("Content-Type: text/plain\r\n"); rsprintf("Content-Length: %d\r\n\r\n", size); /* return if file too big */ if (size > (int) (sizeof(return_buffer) - strlen(return_buffer))) { printf("return buffer too small\n"); return EL_MEM_ERROR; } return_length = strlen(return_buffer)+size; strcat(return_buffer, message); return EL_SUCCESS; } /*------------------------------------------------------------------*/ void display_line(LOGBOOK *lbs, int message_id, int number, char *mode, int level, BOOL printable, int n_line, int show_attachments, char *date, char *reply_to, int n_attr_disp, char disp_attr[MAX_N_ATTR+4][NAME_LENGTH], char attrib[MAX_N_ATTR][NAME_LENGTH], int n_attr, char *text, char attachment[MAX_ATTACHMENTS][256], char *encoding, BOOL select, int *n_display) { char str[256], ref[256], *nowrap, col[80], format[256], file_name[256]; char slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; char display[256], attr_icon[80], align[32]; int i, j, size, i_line, index, colspan; BOOL link_displayed, skip_comma; FILE *f; sprintf(ref, "../%s/%d", lbs->name_enc, message_id); if (equal_ustring(mode, "Summary")) { if (number % 2 == 1) strcpy(col, gt("List bgcolor1")); else strcpy(col, gt("List bgcolor2")); } else if (equal_ustring(mode, "Full")) strcpy(col, gt("List bgcolor1")); else if (equal_ustring(mode, "Threaded")) { if (level == 0) strcpy(col, gt("List bgcolor1")); else strcpy(col, gt("List bgcolor2")); } rsprintf(""); /* only single cell for threaded display */ if (equal_ustring(mode, "Threaded")) { rsprintf("", col); /* show select box */ if (select) rsprintf("\n", (*n_display)++, message_id); for (i=0 ; iname, "Table align", str)) strcpy(align, str); if (equal_ustring(mode, "Threaded") && getcfg(lbs->name, "Thread display", display)) { /* check if to use icon from attributes */ attr_icon[0] = 0; if (getcfg(lbs->name, "Thread icon", attr_icon)) { for (i=0 ; i ", ref, attr_icon); else { /* if top level only, display reply icon if message has a reply */ if (getcfg(lbs->name, "Top level only", str) && atoi(str) == 1 && reply_to[0]) { if (*gt("Thread reply image")) rsprintf(" ", ref, gt("Thread reply image")); else rsprintf(" %d > ", size, ref, message_id); } else { /* display standard icons */ if (level == 0) { if (*gt("Thread image")) rsprintf(" ", ref, gt("Thread image")); else rsprintf(" %d ", size, ref, message_id); } else { if (*gt("Thread reply image")) rsprintf(" ", ref, gt("Thread reply image")); else rsprintf(" %d ", size, ref, message_id); } } } j = build_subst_list(lbs, slist, svalue, attrib); /* add message id and entry date */ strcpy(slist[j], "Message ID"); sprintf(svalue[j++], "%d", message_id); strcpy(slist[j], "entry date"); if (getcfg(lbs->name, "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; ts.tm_isdst = -1; /* let mktime compute DST */ mktime(&ts); strftime(svalue[j++], sizeof(str), format, &ts); } else strcpy(svalue[j++], date); strsubst(display, slist, svalue, j); rsputs2(display); } else { /* show select box */ if (select && !equal_ustring(mode, "Threaded")) rsprintf("\n", col, (*n_display)++, message_id); for (index=0 ; index ", ref, gt("Thread image")); else rsprintf(" %d ", size, ref, message_id); } else { if (*gt("Thread reply image")) rsprintf(" ", ref, gt("Thread reply image")); else rsprintf(" %d ", size, ref, message_id); } skip_comma = TRUE; } else rsprintf("  %d  ", col, size, ref, message_id); link_displayed = TRUE; } if (equal_ustring(disp_attr[index], "Logbook")) { if (equal_ustring(mode, "Threaded")) { if (!link_displayed) { rsprintf("%s", size, ref, lbs->name); link_displayed = TRUE; } else if (skip_comma) { rsprintf("%s", size, lbs->name); skip_comma = FALSE; } else rsprintf(", %s", size, lbs->name); } else { if (!link_displayed) { rsprintf("%s", align, nowrap, col, size, ref, lbs->name); link_displayed = TRUE; } else rsprintf("%s", align, nowrap, col, size, lbs->name); } } if (equal_ustring(disp_attr[index], "Date")) { if (getcfg(lbs->name, "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; ts.tm_isdst = -1; /* let mktime compute DST */ mktime(&ts); strftime(str, sizeof(str), format, &ts); } else strcpy(str, date); if (equal_ustring(mode, "Threaded")) { if (!link_displayed) { rsprintf("%s", size, ref, str); link_displayed = TRUE; } else if (skip_comma) { rsprintf(" %s", size, str); skip_comma = FALSE; } else rsprintf(", %s", size, str); } else { if (!link_displayed) { rsprintf("%s", align, nowrap, col, size, ref, str); link_displayed = TRUE; } else rsprintf("%s", align, nowrap, col, size, str); } } for (i=0 ; i", size); if (!link_displayed) { rsprintf("", ref); rsputs2(attr_list[i]); rsprintf(""); link_displayed = TRUE; } else { if (skip_comma) { rsprintf(" "); skip_comma = FALSE; } else rsprintf(", "); rsputs2(attrib[i]); } rsprintf(" "); } } else if (attr_flags[i] & AF_ICON) { if (attrib[i][0]) rsprintf("  ", attrib[i]); } else { rsprintf("", size); if (!link_displayed) { rsprintf("", ref); rsputs2(attrib[i]); rsprintf(""); link_displayed = TRUE; } else { if (skip_comma) { rsprintf(" "); skip_comma = FALSE; } else rsprintf(", "); rsputs2(attrib[i]); } rsprintf(""); } } else { if (equal_ustring(attr_options[i][0], "boolean")) { if (atoi(attrib[i]) == 1) rsprintf("\n", col); else rsprintf("\n", col); } else if (attr_flags[i] & AF_ICON) { rsprintf("", col); if (attrib[i][0]) rsprintf("", attrib[i]); rsprintf(" "); } else { rsprintf("", align, col, size); if (!link_displayed) { rsprintf("", ref); rsputs2(attrib[i]); rsprintf(""); link_displayed = TRUE; } else rsputs2(attrib[i]); rsprintf(" "); } } } } } if (equal_ustring(mode, "Threaded")) rsprintf("\n"); if (equal_ustring(mode, "Summary") && n_line > 0) { rsprintf("", col, size); for (i=i_line=0 ; i\n"); } rsprintf("\n"); colspan = n_attr_disp; if (select) colspan++; if (equal_ustring(mode, "Full")) { if (!getcfg(lbs->name, "Show text", str) || atoi(str) == 1) { rsprintf("", colspan, size); if (equal_ustring(encoding, "plain")) { rsputs("

");
        rsputs2(text);
        rsputs("
"); } else rsputs(text); rsprintf("\n"); } if (!show_attachments && attachment[0][0]) { 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", lbs->name_enc, 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("", colspan, ref); } else { 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, lbs->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("
\n"); } } } } if (!show_attachments && attachment[0][0]) rsprintf("
\n"); } } /*------------------------------------------------------------------*/ void display_reply(LOGBOOK *lbs, int message_id, int printable, int n_attr_disp, char disp_attr[MAX_N_ATTR+4][NAME_LENGTH], int level) { char date[80], *text, in_reply_to[80], reply_to[256], encoding[80], attachment[MAX_ATTACHMENTS][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH]; int status, size; char *p; text = malloc(TEXT_SIZE); reply_to[0] = 0; size = TEXT_SIZE; status = el_retrieve(lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, in_reply_to, reply_to, attachment, encoding); if (status != EL_SUCCESS) { free(text); return; } display_line(lbs, message_id, 0, "threaded", level, printable, 0, FALSE, date, reply_to, n_attr_disp, disp_attr, attrib, lbs->n_attr, NULL, NULL, encoding, 0, NULL); if (reply_to[0]) { p = reply_to; do { display_reply(lbs, atoi(p), printable, n_attr_disp, disp_attr, level+1); while (*p && isdigit(*p)) p++; while (*p && (*p == ',' || *p == ' ')) p++; } while(*p); } free(text); } /*------------------------------------------------------------------*/ int msg_compare(const void *m1, const void *m2) { return strcmp(((MSG_LIST *)m1)->string, ((MSG_LIST *)m2)->string); } int msg_compare_reverse(const void *m1, const void *m2) { return strcmp(((MSG_LIST *)m2)->string, ((MSG_LIST *)m1)->string); } /*------------------------------------------------------------------*/ void build_ref(char *ref) { char *p1, *p2; if (strchr(getparam("cmdline"), '?')) strcat(ref, strchr(getparam("cmdline"), '?')); /* eliminate old search */ if (strstr(ref, "cmd=Search&")) strcpy(strstr(ref, "cmd=Search&"), strstr(ref, "cmd=Search&")+11); if (isparam("last")) { /* eliminate old last= */ if ((p1 = strstr(ref, "last=")) != NULL) { for (p2 = p1+5 ; *p2 && isdigit(*p2) ; p2++); strcpy(p1-1, p2); } sprintf(ref+strlen(ref), "&last=%s", getparam("last")); } /* replace first '&' by '?' if not present */ if (!strchr(ref, '?') && strchr(ref, '&')) *strchr(ref, '&') = '?'; } void show_page_navigation(int n_msg, int page_n, int n_page, BOOL top) { int i; char ref[256]; if (!(page_n && n_msg > n_page) && !top) return; rsprintf("\n"); rsprintf("
\n", gt("Border width"), gt("Categories cellpadding")); rsprintf("
\n", gt("Menu1 BGColor")); rsprintf(""); if (n_msg > n_page) rsprintf("%s \n", loc("Goto page")); if (page_n > 1) { sprintf(ref, "page%d", page_n - 1); build_ref(ref); rsprintf("%s  ", ref, loc("Previous")); } if (page_n && n_msg > n_page) { for (i=0 ; i<(n_msg-1)/n_page+1 ; i++) { sprintf(ref, "page%d", i+1); build_ref(ref); if (i == (n_msg-1)/n_page) { if (page_n == i+1) rsprintf("%d  ", i+1); else rsprintf("%d  \n", ref, i+1); } else { if (page_n == i+1) rsprintf("%d, ", i+1); else rsprintf("%d, \n", ref, i+1); } } } if (page_n != -1 && page_n * n_page < n_msg) { sprintf(ref, "page%d", page_n + 1); build_ref(ref); rsprintf("%s  ", ref, loc("Next")); } if (page_n != -1 && n_page < n_msg) { sprintf(ref, "page"); build_ref(ref); rsprintf("%s\n", ref, loc("All")); } rsprintf("\n", gt("Menu1 BGColor")); if (top) { i = atoi(getparam("last")); rsprintf(" \n", loc("Show last")); rsprintf("\n"); } rsprintf("
\n\n"); } /*------------------------------------------------------------------*/ void show_select_navigation(LOGBOOK *lbs) { int i, n_log; char str[256]; char lbk_list[MAX_N_LIST][NAME_LENGTH]; rsprintf("\n", gt("Border width"), gt("Categories cellpadding")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); rsprintf(" \n"); rsprintf("Selected entries: \n"); rsprintf("\n", loc("Toggle all")); if (!getcfg(lbs->name, "Menu commands", str) || strstr(str, "Delete")) { rsprintf("\n", loc("Delete")); } if (getcfg(lbs->name, "Menu commands", str) && strstr(str, "Copy to")) { rsprintf("\n", loc("Copy to")); rsprintf("\n"); } if (getcfg(lbs->name, "Menu commands", str) && strstr(str, "Move to")) { rsprintf("\n", loc("Move to")); rsprintf("\n"); } rsprintf("
\n\n"); } /*------------------------------------------------------------------*/ void show_elog_submit_find(LOGBOOK *lbs, INT past_n, INT last_n, INT page_n) { int i, j, n, index, size, status, d1, m1, y1, d2, m2, y2, n_line; int current_year, current_month, current_day, printable, n_logbook, n_display, reverse, n_attr_disp, n_msg, search_all, message_id, n_page, i_start, i_stop; char date[80], attrib[MAX_N_ATTR][NAME_LENGTH], disp_attr[MAX_N_ATTR+4][NAME_LENGTH], list[10000], text[TEXT_SIZE], text1[TEXT_SIZE], text2[TEXT_SIZE], in_reply_to[80], reply_to[256], attachment[MAX_ATTACHMENTS][256], encoding[80]; char str[256], col[80], ref[256], img[80]; char mode[80]; char menu_str[1000], menu_item[MAX_N_LIST][NAME_LENGTH]; char *p , *pt, *pt1, *pt2; BOOL show_attachments, threaded; time_t ltime, ltime_start, ltime_end, now; struct tm tms, *ptms; MSG_LIST *msg_list; char slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; /* redirect if enpty parameters */ if (strstr(_cmdline, "=&")) { while (pt1 = strstr(_cmdline, "=&")) { pt2 = pt1+2; while (*pt1 != '&' && *pt1 != '?') pt1--; strcpy(pt1+1, pt2); } if (_cmdline[strlen(_cmdline)-1] == '=') { pt1 = _cmdline+strlen(_cmdline)-1; while (*pt1 != '&' && *pt1 != '?') *pt1-- = 0; *pt1 = 0; } /* add reverse=0 if not present */ if (strstr(_cmdline, "reverse=") == NULL && getcfg(lbs->name, "Reverse sort", str) && atoi(str) == 1) { if (strchr(_cmdline, '?')) strcat(_cmdline, "&reverse=0"); else strcat(_cmdline, "?reverse=0"); } redirect(_cmdline); return; } /* redirect go command */ if (isparam("lastcmd")) //## and not copy to / move to / delete ... { strcpy(str, getparam("lastcmd")); url_decode(str); /* strip previous "last" */ if (strstr(str, "last=")) *(strstr(str, "last=")-1) = 0; /* add new "last" */ if (strchr(str, '?')) sprintf(str+strlen(str), "&last=%s", getparam("last")); else sprintf(str+strlen(str), "?last=%s", getparam("last")); redirect(str); return; } printable = atoi(getparam("Printable")); if (*getparam("Reverse")) reverse = atoi(getparam("Reverse")); else { reverse = 0; if (getcfg(lbs->name, "Reverse sort", str)) reverse = atoi(str); } /* default mode */ strcpy(mode, "Summary"); /* for page display, get mode from config file */ if (past_n || last_n || page_n) { if (getcfg(lbs->name, "Display Mode", str)) strcpy(mode, str); if (*getparam("mode")) strcpy(mode, getparam("mode")); show_attachments = FALSE; } else { /* for find result, get mode from find form */ strcpy(mode, getparam("mode")); if (mode[0] == 0) strcpy(mode, "Full"); show_attachments = (*getparam("attach") > 0); } threaded = equal_ustring(mode, "threaded"); /*---- convert dates to ltime ----*/ time(&now); ptms = localtime(&now); current_year = ptms->tm_year+1900; current_month = ptms->tm_mon+1; current_day = ptms->tm_mday; 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; } /*---- assemble message list ----*/ /* check for search all */ search_all = atoi(getparam("all")); if (getcfg(lbs->name, "Search all logbooks", str) && atoi(str) == 0) search_all = 0; n_msg = 0; n_display = 0; if (search_all) { /* count logbooks */ for (n_logbook=0 ; ; n_logbook++) { if (!lb_list[n_logbook].name[0]) break; n_msg += *lb_list[n_logbook].n_el_index; } } else { n_logbook = 1; n_msg = *lbs->n_el_index; } msg_list = malloc(sizeof(MSG_LIST)*n_msg); for (i=n=0 ; in_el_index ; j++) { msg_list[n].lbs = lbs; msg_list[n].index = j; sprintf(msg_list[n].string, "%010d", lbs->el_index[j].file_time); n++; } } /*---- apply start/end date cut ----*/ if (past_n) ltime_start = now-3600*24*past_n; if (last_n && last_n < n_msg) { for (i=n_msg-last_n-1 ; i>=0 ; i--) msg_list[i].lbs = NULL; } if (ltime_start) { for (i=0 ; iel_index[msg_list[i].index].file_time < ltime_start) msg_list[i].lbs = NULL; } if (ltime_end) { for (i=0 ; iel_index[msg_list[i].index].file_time > ltime_end) msg_list[i].lbs = NULL; } if (isparam("last")) { n = atoi(getparam("last")); if (n > 0) { for (i=0 ; iel_index[msg_list[i].index].file_time < now-3600*24*n) msg_list[i].lbs = NULL; } } /*---- filter message list ----*/ for (i=0 ; in_attr ; i++) if (*getparam(attr_list[i])) break; /* do filtering */ for (index=0 ; indexel_index[msg_list[index].index].message_id; status = el_retrieve(msg_list[index].lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, in_reply_to, reply_to, attachment, encoding); if (status != EL_SUCCESS) break; for (i=0 ; in_attr ; i++) { if (*getparam(attr_list[i])) { strcpy(str, getparam(attr_list[i])); /* if value starts with '$', substitute it */ if (str[0] == '$') { j = build_subst_list(lbs, slist, svalue, attrib); strsubst(str, slist, svalue, j); setparam(attr_list[i], str); } for (j=0 ; j<(int)strlen(str) ; j++) str[j] = toupper(str[j]); str[j] = 0; for (j=0 ; j<(int)strlen(attrib[i]) ; j++) text1[j] = toupper(attrib[i][j]); text1[j] = 0; if (strstr(text1, str) == NULL) break; } } if (i < lbs->n_attr) { msg_list[index].lbs = NULL; continue; } if (*getparam("subtext")) { strcpy(str, getparam("subtext")); for (i=0 ; i<(int)strlen(str) ; i++) str[i] = toupper(str[i]); str[i] = 0; for (i=0 ; i<(int)strlen(text) ; i++) text1[i] = toupper(text[i]); text1[i] = 0; if (strstr(text1, str) == NULL) { msg_list[index].lbs = NULL; continue; } } /* in threaded mode, find message head */ if (threaded && in_reply_to[0]) { do { message_id = atoi(in_reply_to); size = sizeof(text); status = el_retrieve(msg_list[index].lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, in_reply_to, reply_to, attachment, encoding); if (status != EL_SUCCESS) break; } while (in_reply_to[0]); /* search index of message head */ for (i=0 ; i < *msg_list[index].lbs->n_el_index ; i++) if (msg_list[index].lbs->el_index[i].message_id == message_id) break; /* check if message head already in list */ for (j=0 ; jn_attr ; i++) { if (equal_ustring(getparam("sort"), attr_list[i]) || equal_ustring(getparam("rsort"), attr_list[i])) { strncpy(msg_list[index].string, attrib[i], 255); msg_list[index].string[255] = 0; } if (equal_ustring(getparam("sort"), "#") || equal_ustring(getparam("rsort"), "#")) { sprintf(msg_list[index].string, "%08d", message_id); } } if (isparam("rsort")) reverse = 1; if (isparam("sort")) reverse = 0; } /*---- compact messasges ----*/ for (i=j=0 ; iname, "Entries per page", str)) n_page = atoi(str); else n_page = 20; if (isparam("npp")) n_page = atoi(getparam("npp")); if (page_n != -1) { i_start = (page_n - 1) * n_page; i_stop = i_start + n_page - 1; if (i_start >= n_msg && n_msg > 0) { page_n = 1; i_start = 0; } if (i_stop >= n_msg) i_stop = n_msg-1; } } /*---- 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); else if (page_n == -1) sprintf(str+strlen(str), loc("all entries")); else if (page_n) sprintf(str+strlen(str), loc("Page %d of %d"), page_n, (n_msg-1)/n_page+1); if (strlen(str) == 2) str[0] = 0; if (printable) show_standard_title(lbs->name, str, 1); else show_standard_title(lbs->name, str, 0); /*---- menu buttons ----*/ if (!printable) { rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); /* current command line for select command */ strcpy(str, getparam("cmdline")); /* remove select switch */ if (strstr(str, "select=1")) { *strstr(str, "select=1") = 0; if (strlen(str) > 1 && (str[strlen(str)-1] == '&' || str[strlen(str)-1] == '?')) str[strlen(str)-1] = 0; } /* store current command line as hidden parameter for page navigation */ if (str[0] && !equal_ustring(str, "?")) { url_encode(str); rsprintf("\n", str); } if (!getcfg(lbs->name, "Guest Find menu commands", menu_str) || *getparam("unm") != 0) getcfg(lbs->name, "Find menu commands", menu_str); /* default menu commands */ if (menu_str[0] == 0) { strcpy(menu_str, "New, Find, Select, "); if (getcfg(lbs->name, "Password file", str)) strcat(menu_str, "Admin, Config, Logout, "); else strcat(menu_str, "Config, "); strcat(menu_str, "Last x, Help"); } n = strbreak(menu_str, menu_item, MAX_N_LIST); if (atoi(gt("Use buttons")) == 1) { for (i=0 ; i\n", mode); 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); } } else rsprintf("\n", loc(menu_item[i])); } } } else { rsprintf("\n"); for (i=0 ; i%s |\n", past_n*2, mode, str); } if (last_n) { sprintf(str, loc("Last %d entries"), last_n*2); rsprintf(" %s |\n", last_n*2, mode, str); } } else if (equal_ustring(menu_item[i], "Select")) { strcpy(str, getparam("cmdline")); if (atoi(getparam("select")) == 1) { /* remove select switch */ if (strstr(str, "select=1")) { *strstr(str, "select=1") = 0; if (strlen(str) > 1 && (str[strlen(str)-1] == '&' || str[strlen(str)-1] == '?')) str[strlen(str)-1] = 0; } } else { /* add select switch */ if (strchr(str, '?')) strcat(str, "&select=1"); else strcat(str, "?select=1"); } rsprintf(" %s |\n", str, loc("Select")); } 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"); } rsprintf("
\n\n"); } /*---- find menu text ----*/ if (getcfg(lbs->name, "find menu text", str) && !printable) { FILE *f; char file_name[256], *buf; rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); /* check if file starts with an absolute directory */ 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, "rb"); 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 rsprintf("
Error: file \"%s\" not found
", file_name); rsprintf("
"); } /*---- 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 ; in_attr ; i++) { if (*getparam(attr_list[i])) rsprintf("", 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(lbs->name, "Summary lines", str)) n_line = atoi(str); /*---- page navigation ----*/ if (!printable) show_page_navigation(n_msg, page_n, n_page, TRUE); /*---- select navigation ----*/ if (atoi(getparam("select")) == 1) show_select_navigation(lbs); /*---- table titles ----*/ rsprintf("\n", printable ? "1" : gt("Border width"), gt("Categories cellpadding"), gt("Frame color")); strcpy(col, gt("Categories bgcolor1")); size = printable ? 2 : 3; if (getcfg(lbs->name, "Display search", list)) n_attr_disp = strbreak(list, disp_attr, MAX_N_ATTR); else { if (search_all) { n_attr_disp = lbs->n_attr + 3; strcpy(disp_attr[0], "#"); strcpy(disp_attr[1], "Logbook"); strcpy(disp_attr[2], "Date"); memcpy(disp_attr+3, attr_list, sizeof(attr_list)); } else { n_attr_disp = lbs->n_attr + 2; strcpy(disp_attr[0], "#"); strcpy(disp_attr[1], "Date"); memcpy(disp_attr+2, attr_list, sizeof(attr_list)); } } if (threaded) { } else { rsprintf("\n"); if (atoi(getparam("select")) == 1) rsprintf("\n", col); for (i=0 ; i"); else if (strcmp(getparam("rsort"), disp_attr[i]) == 0) strcpy(img, ""); rsprintf("\n", col, size, ref, disp_attr[i], img); } if (!equal_ustring(mode, "Full") && n_line > 0) rsprintf("\n", col, size); rsprintf("\n\n"); } /*---- display message list ----*/ for (index=i_start ; index<=i_stop ; index++) { size = sizeof(text); message_id = msg_list[index].lbs->el_index[msg_list[index].index].message_id; status = el_retrieve(msg_list[index].lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, in_reply_to, reply_to, attachment, encoding); if (status != EL_SUCCESS) break; /*---- add highlighting for searched subtext ----*/ if (*getparam("subtext")) { strcpy(str, getparam("subtext")); for (i=0 ; i<(int)strlen(str) ; i++) str[i] = toupper(str[i]); for (i=0 ; i<(int)strlen(text) ; i++) text1[i] = toupper(text[i]); text1[i] = 0; text2[0] = 0; pt = text; /* original text */ pt1 = text1; /* upper-case text */ pt2 = text2; /* text with inserted coloring */ do { p = strstr(pt1, str); size = (int)(p - pt1); if (p != NULL) { pt1 = p+strlen(str); /* copy first part original text */ memcpy(pt2, pt, size); pt2 += size; pt += size; /* add coloring 1st part */ /* here: \001='<', \002='>', /003='"', and \004=' ' */ /* see also rsputs2(char* ) */ if (equal_ustring(encoding, "plain") || !equal_ustring(mode, "Full")) strcpy(pt2, "\001B\004style=\003color:black;background-color:#ffff66\003\002"); else strcpy(pt2, ""); 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") || !equal_ustring(mode, "Full")) strcpy(pt2, "\001/B\002"); else strcpy(pt2, ""); pt2 += strlen(pt2); } } while (p != NULL); strcpy(pt2, pt); strcpy(text, text2); } /*---- display line ----*/ display_line(msg_list[index].lbs, message_id, index, mode, 0, printable, n_line, show_attachments, date, reply_to, n_attr_disp, disp_attr, attrib, lbs->n_attr, text, attachment, encoding, atoi(getparam("select")), &n_display); if (threaded) { if (reply_to[0] && (!getcfg(msg_list[index].lbs->name, "Top level only", str) || atoi(str) == 0)) { p = reply_to; do { display_reply(msg_list[index].lbs, atoi(p), printable, n_attr_disp, disp_attr, 1); while (*p && isdigit(*p)) p++; while (*p && (*p == ',' || *p == ' ')) p++; } while(*p); } } } if (n_display) rsprintf("\n", n_display); rsprintf("
%s%sText
\n"); if (n_msg == 0) { rsprintf("\n", printable ? "1" : gt("Border width"), gt("Categories cellpadding"), gt("Frame color")); rsprintf("", loc("No entries found")); rsprintf("
%s
\n"); } /*---- select navigation ----*/ if (atoi(getparam("select")) == 1) show_select_navigation(lbs); /*---- page navigation ----*/ if (!printable) show_page_navigation(n_msg, page_n, n_page, FALSE); rsprintf("\n"); /*---- bottom text ----*/ if (getcfg(lbs->name, "bottom text", str)) { FILE *f; char file_name[256], *buf; /* check if file starts with an absolute directory */ 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, "rb"); 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 rsprintf("
Error: file \"%s\" not found
", file_name); } else /* add little logo */ rsprintf("
ELOG V%s
", VERSION); rsprintf("\r\n"); free(msg_list); } /*------------------------------------------------------------------*/ int compose_mail(LOGBOOK *lbs, char *mail_to, int message_id, char attrib[MAX_N_ATTR][NAME_LENGTH], char *mail_param, int *n_mail, int old_mail) { int j; char str[256], mail_from[256], mail_text[TEXT_SIZE+1000], smtp_host[256], subject[256]; char slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH]; if (!getcfg("global", "SMTP host", smtp_host)) { show_error(loc("No SMTP host defined in [global] section of configuration file")); return 0; } if (getcfg(lbs->name, "Use Email from", mail_from)) { j = build_subst_list(lbs, slist, svalue, attrib); strsubst(mail_from, slist, svalue, j); } else sprintf(mail_from, "ELog@%s", host_name); if (old_mail) sprintf(mail_text, loc("A old entry has been updated on %s"), host_name); else sprintf(mail_text, loc("A new entry has been submitted on %s"), host_name); sprintf(mail_text+strlen(mail_text), "\r\n\r\n"); sprintf(mail_text+strlen(mail_text), "%s : %s\r\n", loc("Logbook"), lbs->name); for (j=0 ; jn_attr ; j++) { strcpy(str, " "); memcpy(str, attr_list[j], strlen(attr_list[j])); sprintf(str+20, ": %s\r\n", attrib[j]); strcpy(mail_text+strlen(mail_text), str); } /* compose subject from attributes */ if (getcfg(lbs->name, "Use Email Subject", subject)) { j = build_subst_list(lbs, slist, svalue, attrib); strsubst(subject, slist, svalue, j); } else { if (old_mail) strcpy(subject, "Updated ELOG entry"); else strcpy(subject, "New ELOG entry"); } /* try to get URL from referer */ if (!getcfg("global", "URL", str)) { if (referer[0]) strcpy(str, referer); else { if (tcp_port == 80) sprintf(str, "http://%s/", host_name); else sprintf(str, "http://%s:%d/", host_name, tcp_port); } } else { strcat(str, lbs->name); strcat(str, "/"); } sprintf(mail_text+strlen(mail_text), "\r\n%s URL : %s%d\r\n", loc("Logbook"), str, message_id); if (getcfg(lbs->name, "Email message body", str) && atoi(str) == 1) { sprintf(mail_text+strlen(mail_text), "\r\n=================================\r\n\r\n%s", getparam("text")); } sendmail(smtp_host, mail_from, mail_to, subject, mail_text); if (!getcfg(lbs->name, "Display email recipients", str) || atoi(str) == 1) { if (mail_param[0] == 0) strcpy(mail_param, "?"); else strcat(mail_param, "&"); sprintf(mail_param+strlen(mail_param), "mail%d=%s", (*n_mail)++, mail_to); } return 1; } /*------------------------------------------------------------------*/ void submit_elog(LOGBOOK *lbs) { char str[256], file_name[256], error[1000], date[80], mail_list[MAX_N_LIST][NAME_LENGTH], list[10000], attrib[MAX_N_ATTR][NAME_LENGTH], subst_str[256], in_reply_to[80], reply_to[256], user[256], user_email[256], email_notify[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_mail, suppress, message_id, resubmit_orig; /* check for required attributs */ missing = 0; for (i=0 ; in_attr ; i++) if (attr_flags[i] & AF_REQUIRED) { if ((attr_flags[i] & AF_MULTI) == 0 && *getparam(attr_list[i]) == 0) { missing = 1; break; } if ((attr_flags[i] & AF_MULTI)) { for (j=0 ; j"); 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(lbs, slist, svalue, NULL); /* retrieve attributes */ for (i=0 ; in_attr ; i++) { if (attr_flags[i] & AF_MULTI) { attrib[i][0] = 0; first = 1; for (j=0 ; jname, str, subst_str)) { strsubst(subst_str, slist, svalue, n); strcpy(attrib[i], subst_str); } } } message_id = 0; reply_to[0] = 0; in_reply_to[0] = 0; date[0] = 0; resubmit_orig = 0; if (*getparam("edit") && *getparam("resubmit") && atoi(getparam("resubmit")) == 1) { resubmit_orig = atoi(getparam("orig")); /* get old links */ el_retrieve(lbs, resubmit_orig, NULL, NULL, NULL, 0, NULL, 0, in_reply_to, reply_to, NULL, NULL); /* if not message head, move all preceeding messages */ if (in_reply_to[0]) { do { resubmit_orig = atoi(in_reply_to); el_retrieve(lbs, resubmit_orig, NULL, NULL, NULL, 0, NULL, 0, in_reply_to, reply_to, NULL, NULL); } while (in_reply_to[0]); } message_id = atoi(getparam("orig")); strcpy(in_reply_to, ""); strcpy(reply_to, ""); date[0] = 0; } else { if (*getparam("edit")) { message_id = atoi(getparam("orig")); strcpy(in_reply_to, ""); strcpy(reply_to, ""); strcpy(date, ""); } else strcpy(in_reply_to, getparam("orig")); } message_id = el_submit(lbs, message_id, date, attr_list, attrib, lbs->n_attr, getparam("text"), in_reply_to, reply_to, *getparam("html") ? "HTML" : "plain", att_file, _attachment_buffer, _attachment_size, TRUE); if (message_id <= 0) { sprintf(str, loc("New message cannot be written to directory \"%s\""), lbs->data_dir); strcat(str, "\n

"); strcat(str, loc("Please check that it exists and elogd has write access")); show_error(str); return; } /* resubmit thread if requested */ if (resubmit_orig) message_id = el_move_message_thread(lbs, resubmit_orig); /*---- email notifications ----*/ suppress = atoi(getparam("suppress")); /* check for mail submissions */ mail_param[0] = 0; n_mail = 0; if (suppress) { strcpy(mail_param, "?suppress=1"); } else { if (!(*getparam("edit") && getcfg(lbs->name, "Suppress Email on edit", str) && atoi(str) == 1)) { /* go throuch "Email xxx" in configuration file */ for (index=0 ; index <= lbs->n_attr ; index++) { if (index < lbs->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(lbs->name, str, list)) { n = strbreak(list, mail_list, MAX_N_LIST); if (verbose) printf("\n%s to %s\n\n", str, list); for (i=0 ; iname, user, NULL, NULL, user_email, email_notify); if (email_notify[0]) if (!compose_mail(lbs, user_email, message_id, attrib, mail_param, &n_mail, *getparam("edit"))) return; } } } for (i=0 ; iname, "Submit page", str)) { /* check if file starts with an absolute directory */ if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } send_file(file_name); 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"); } /* bug for Konqueror */ if (strstr(browser, "Konqueror")) rsprintf("Location: %s/%d%s\r\n\r\nredir\r\n", lbs->name_enc, message_id, mail_param); else rsprintf("Location: %d%s\r\n\r\nredir\r\n", message_id, mail_param); } /*------------------------------------------------------------------*/ void copy_to(LOGBOOK *lbs, int src_id, char *dest_logbook, int move) { int size, i, n, n_done, index, status, fh, source_id, message_id; char str[256], file_name[256], attrib[MAX_N_ATTR][NAME_LENGTH]; char date[80], text[TEXT_SIZE], msg_str[32], in_reply_to[80], reply_to[256], attachment[MAX_ATTACHMENTS][256], encoding[80]; LOGBOOK *lbs_dest; for (i=0 ; lb_list[i].name[0] ; i++) if (equal_ustring(lb_list[i].name, dest_logbook)) break; if (!lb_list[i].name[0]) return; lbs_dest = &lb_list[i]; if (src_id) n = 1; else n = atoi(getparam("nsel")); n_done = 0; for (index=0 ; indexn_attr, text, &size, in_reply_to, reply_to, attachment, encoding); if (status != EL_SUCCESS) { sprintf(msg_str, "%d", source_id); sprintf(str, loc("Message %s cannot be read from logbook \"%s\""), msg_str, lbs->name); show_error(str); return; } /* read attachments */ for (i=0 ; idata_dir); strcat(file_name, attachment[i]); fh = open(file_name, O_RDONLY | O_BINARY); if (fh > 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); } /* submit in destination logbook without links, submit all attributes from the source logbook even if the destination has a differnt number of attributes */ message_id = el_submit(lbs_dest, 0, date, attr_list, attrib, lbs->n_attr, text, "", "", encoding, attachment, _attachment_buffer, _attachment_size, TRUE); for (i=0 ; idata_dir); strcat(str, "\n

"); strcat(str, loc("Please check that it exists and elogd has write access")); show_error(str); return; } n_done++; /* delete original message for move */ if (move) { el_delete_message(lbs, source_id, TRUE, NULL, TRUE, TRUE); /* check if this was the last message */ source_id = el_search_message(lbs, EL_NEXT, source_id, FALSE); /* if yes, force display of new last message */ if (source_id <= 0) source_id = el_search_message(lbs, EL_LAST, 0, FALSE); } } /* display status message */ sprintf(str, "%d", source_id); show_standard_header(loc("Copy ELog entry"), str); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); rsprintf("\n"); if (src_id) rsprintf("\n", gt("Cell BGColor"), loc("Go to"), lbs->name, source_id, lbs->name); else { strcpy(str, getparam("lastcmd")); url_decode(str); rsprintf("\n", gt("Cell BGColor"), loc("Go to"), lbs->name, str, lbs->name); } rsprintf("\n", gt("Cell BGColor"), loc("Go to"), lbs_dest->name, lbs_dest->name); rsprintf("
"); if (n>1) { if (n_done == 0) rsprintf(loc("No message selected")); else if (move) rsprintf(loc("%d messages moved successfully from \"%s\" to \"%s\""), n_done, lbs->name, lbs_dest->name); else rsprintf(loc("%d messages copied successfully from \"%s\" to \"%s\""), n_done, lbs->name, lbs_dest->name); } else { if (move) rsprintf(loc("Message moved successfully from \"%s\" to \"%s\""), lbs->name, lbs_dest->name); else rsprintf(loc("Message copied successfully from \"%s\" to \"%s\""), lbs->name, lbs_dest->name); } rsprintf("
%s %s
%s %s
%s %s
\n"); rsprintf("\r\n"); return; } /*------------------------------------------------------------------*/ void show_elog_page(LOGBOOK *lbs, char *dec_path, char *command) { int size, i, j, n, n_log, status, fh, length, message_error, index; int message_id, orig_message_id; char str[1000], 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], admin_user[80], slist[MAX_N_ATTR+10][NAME_LENGTH], svalue[MAX_N_ATTR+10][NAME_LENGTH], *p; char lbk_list[MAX_N_LIST][NAME_LENGTH]; FILE *f; BOOL first; message_id = atoi(dec_path); message_error = EL_SUCCESS; /* check for guest access */ if (!getcfg(lbs->name, "Guest Menu commands", menu_str) || *getparam("unm") != 0) getcfg(lbs->name, "Menu commands", menu_str); /* default menu commands */ if (menu_str[0] == 0) { strcpy(menu_str, "Back, New, Edit, Delete, Reply, Find, "); if (getcfg(lbs->name, "Password file", str)) { if (getcfg(lbs->name, "Admin user", str) && strstr(str, getparam("unm")) != 0) { strcat(menu_str, "Admin, "); } strcat(menu_str, "Config, Logout, "); } else { strcat(menu_str, "Config, "); } strcat(menu_str, "Help"); } else { /* check for admin command */ n = strbreak(menu_str, menu_item, MAX_N_LIST); menu_str[0] = 0; admin_user[0] = 0; getcfg(lbs->name, "Admin user", admin_user); for (i=0 ; iname, "Admin user", str) && *getparam("unm") && strstr(str, getparam("unm")) != 0) { strcat(other_str, "Remove user, New user, Activate, "); } else if (getcfg(lbs->name, "Self register", str) && atoi(str) > 0) { strcat(other_str, "Remove user, New user, "); } /* allow change password if "config" possible */ if (equal_ustring(command, loc("Change password")) && strstr(menu_str, "Config")) { } /* check if command is present in the menu list, exclude non-localized submit for elog */ else if (command[0] && !equal_ustring(command, "Submit")) { n = strbreak(menu_str, menu_item, MAX_N_LIST); for (i=0 ; i%s\" not allowed"), command); show_error(str); return; } } } /*---- check next/previous message -------------------------------*/ if (equal_ustring(command, loc("Next")) || equal_ustring(command, loc("Previous")) || equal_ustring(command, loc("Last")) || equal_ustring(command, loc("First"))) { orig_message_id = message_id; if (equal_ustring(command, loc("Last"))) message_id = el_search_message(lbs, EL_LAST, 0, FALSE); if (equal_ustring(command, loc("First"))) message_id = el_search_message(lbs, EL_FIRST, 0, FALSE); if (!message_id) { redirect(""); return; } first = TRUE; do { if (equal_ustring(command, loc("Next"))) message_id = el_search_message(lbs, EL_NEXT, message_id, FALSE); if (equal_ustring(command, loc("Previous"))) message_id = el_search_message(lbs, EL_PREV, message_id, FALSE); if (!first) { if (equal_ustring(command, loc("First"))) message_id = el_search_message(lbs, EL_NEXT, message_id, FALSE); if (equal_ustring(command, loc("Last"))) message_id = el_search_message(lbs, EL_PREV, message_id, FALSE); } else first = FALSE; if (message_id == 0) { if (equal_ustring(command, loc("Next"))) message_error = EL_LAST_MSG; else message_error = EL_FIRST_MSG; message_id = orig_message_id; break; } size = sizeof(text); el_retrieve(lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); /* check for locked attributes */ for (i=0 ; in_attr ; i++) { sprintf(lattr, "l%s", attr_list[i]); if (*getparam(lattr) == '1' && !equal_ustring(getparam(attr_list[i]), attrib[i])) break; } if (i < lbs->n_attr) continue; /* check for attribute filter if not browsing */ if (!*getparam("browsing")) { for (i=0 ; in_attr ; i++) { if (*getparam(attr_list[i]) && !equal_ustring(getparam(attr_list[i]), attrib[i])) break; } if (i < lbs->n_attr) continue; } sprintf(str, "%d", message_id); for (i=0 ; in_attr ; i++) { sprintf(lattr, "l%s", attr_list[i]); if (*getparam(lattr) == '1') { if (strchr(str, '?') == NULL) sprintf(str+strlen(str), "?%s=1", lattr); else sprintf(str+strlen(str), "&%s=1", lattr); } } redirect(str); return; } while (TRUE); } /*---- check for valid URL ---------------------------------------*/ if (dec_path[0] && atoi(dec_path) == 0) { sprintf(str, "Invalid URL: %s", dec_path); show_error(str); return; } /*---- get current message ---------------------------------------*/ if (message_id == 0) message_id = el_search_message(lbs, EL_LAST, 0, FALSE); if (message_id) { size = sizeof(text); status = el_retrieve(lbs, message_id, date, attr_list, attrib, lbs->n_attr, text, &size, orig_tag, reply_tag, attachment, encoding); if (status != EL_SUCCESS) message_error = status; } else message_error = EL_EMPTY; /*---- header ----*/ /* header */ if (status == EL_SUCCESS && message_error != EL_EMPTY) { str[0] = 0; if (getcfg(lbs->name, "Page Title", str)) { i = build_subst_list(lbs, slist, svalue, attrib); strsubst(str, slist, svalue, i); } else strcpy(str, "ELOG"); sprintf(ref, "%d", message_id); if (str[0]) show_standard_header(str, ref); else show_standard_header(lbs->name, ref); } else show_standard_header("", ""); /*---- title ----*/ show_standard_title(lbs->name, "", 0); /*---- menu buttons ----*/ rsprintf("\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"))) { getcfg(lbs->name, "Copy to", str); rsprintf("\n"); } if (str[0]) { n_log = strbreak(str, lbk_list, MAX_N_LIST); for (j=0 ; j%s\n", lbk_list[j], lbk_list[j]); } else { for (j=0 ; ; j++) { if (!enumgrp(j, str)) break; if (equal_ustring(str, "global")) continue; if (equal_ustring(str, lbs->name)) continue; rsprintf("
\n\n"); } /*---- next/previous buttons ----*/ if (!getcfg(lbs->name, "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"); /*---- menu text ----*/ if (getcfg(lbs->name, "menu text", str)) { FILE *f; char file_name[256], *buf; rsprintf("\n", gt("Menu1 cellpadding"), gt("Frame color")); rsprintf("
\n", gt("Menu1 Align"), gt("Menu1 BGColor")); /* check if file starts with an absolute directory */ 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, "rb"); 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 rsprintf("
Error: file \"%s\" not found
", file_name); rsprintf("
"); } /*---- message ----*/ /* overall table for message giving blue frame */ rsprintf("\n", gt("Categories border"), gt("Categories cellpadding"), gt("Frame color")); if (message_error == EL_EMPTY) rsprintf("\n", loc("Logbook is empty")); else if (message_error == EL_NO_MSG) rsprintf("\n", loc("This message has been deleted")); else { /* check for locked attributes */ for (i=0 ; in_attr ; i++) { sprintf(lattr, "l%s", attr_list[i]); if (*getparam(lattr) == '1') break; } if (i < lbs->n_attr) sprintf(str, " %s \"%s = %s\"", loc("with"), attr_list[i], getparam(attr_list[i])); else str[0] = 0; if (message_error == EL_LAST_MSG) rsprintf("\n", loc("This is the last entry"), str); if (message_error == EL_FIRST_MSG) rsprintf("\n", loc("This is the first entry"), str); /* check for mail submissions */ if (*getparam("suppress")) { if (getcfg(lbs->name, "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 message ID ----*/ rsprintf("\n\n", gt("Categories bgcolor1"), loc("Message ID"), gt("Categories bgcolor2"), message_id); /*---- display date ----*/ if (getcfg(lbs->name, "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; ts.tm_isdst = -1; /* let mktime compute DST */ mktime(&ts); strftime(str, sizeof(str), format, &ts); rsprintf("\n\n"); /*---- link to original message or reply ----*/ if (message_error != EL_FILE_ERROR && (reply_tag[0] || orig_tag[0])) { if (orig_tag[0]) { rsprintf("\n", ref, orig_tag); } if (reply_tag[0]) { rsprintf("\n"); } } /*---- display attributes ----*/ for (i=0 ; in_attr ; i++) { sprintf(lattr, "l%s", attr_list[i]); rsprintf("\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
%s
"); rsprintf("%s %s
\n", loc("Mail sent to"), getparam(str)); } else break; } } if (i>0) rsprintf("
%s:%d
%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 ; in_attr ; i++) rsprintf("\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")); rsprintf("%s:", loc("Reply to this"), gt("Menu2 bgcolor")); p = strtok(reply_tag, ","); do { rsprintf("%s\n", p, p); p = strtok(NULL, ","); if (p) rsprintf("  \n"); } while (p); rsprintf("
", gt("Categories bgcolor1")); if (!getcfg(lbs->name, "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(lbs->name, "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, lbs->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(lbs->name, "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, lbs->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(lbs->name, "bottom text", str)) { FILE *f; char file_name[256], *buf; /* check if file starts with an absolute directory */ 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, "rb"); 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(LOGBOOK *lbs, char *name, char *password, char *redir) { char str[256]; /* get password from configuration file */ if (getcfg(lbs->name, 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] && !password[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; } /*------------------------------------------------------------------*/ int get_user_line(char *logbook_name, char *user, char *password, char *full_name, char *email, char *email_notify) { char str[256], line[256], file_name[256], *p; FILE *f; int i; if (password) password[0] = 0; if (full_name) full_name[0] = 0; if (email) email[0] = 0; if (email_notify) email_notify[0] = 0; getcfg(logbook_name, "Password file", str); if (!str[0]) return 1; 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) { if (!user[0]) { fclose(f); return 1; } 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 (strcmp(str, user) != 0) return 2; /* if user found, retrieve other info */ p = line; for (i=0 ; i<4 ; i++) { if (strchr(p, ':') == NULL) break; p = strchr(p, ':')+1; while (*p && *p == ' ') p++; strncpy(str, p, sizeof(str)-1); if (strchr(str, ':')) *strchr(str, ':') = 0; while (str[strlen(str)-1] == ' ' || str[strlen(str)-1] == '\r' || str[strlen(str)-1] == '\n') str[strlen(str)-1] = 0; if (i==0 && password) strcpy(password, str); else if (i==1 && full_name) strcpy(full_name, str); else if (i==2 && email) strcpy(email, str); else if (i==3 && email_notify) strcpy(email_notify, str); } return 1; } else { if (user[0]) return 3; else return 1; } } /*------------------------------------------------------------------*/ BOOL enum_user_line(LOGBOOK *lbs, int n, char *user) { char str[256], line[256], file_name[256]; FILE *f; int i; getcfg(lbs->name, "Password file", str); if (!str[0]) return FALSE; 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"); i = 0; if (f != NULL) { while (!feof(f)) { line[0] = 0; fgets(line, sizeof(line), f); if (line[0] == ';' || line[0] == '#' || line[0] == 0) continue; if (strchr(line, ':') == NULL) continue; strcpy(str, line); if (strchr(str, ':')) *strchr(str, ':') = 0; if (i == n) { strcpy(user, str); fclose(f); return TRUE; } i++; } fclose(f); } return FALSE; } /*------------------------------------------------------------------*/ BOOL check_user_password(char *logbook_name, char *user, char *password, char *redir) { char status, str[256], upwd[256], full_name[256], email[256]; status = get_user_line(logbook_name, user, upwd, full_name, email, NULL); if (status == 1) { if (user[0] && strcmp(password, upwd) == 0) { setparam("full_name", full_name); setparam("user_email", email); return TRUE; } /* show login password page */ show_standard_header("ELOG login", NULL); /* define hidden fields for current destination */ 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"), getparam("unm")); rsprintf("\n", gt("Cell BGColor"), loc("Password")); if (getcfg(logbook_name, "Self register", str) && atoi(str) > 0) rsprintf("", gt("Cell BGColor"), loc("Register as new user")); rsprintf("", gt("Cell BGColor"), loc("Submit")); rsprintf("
%s!
\n", gt("Title bgcolor")); rsprintf("%s
%s:   
%s:   
%s
\n"); rsprintf("\r\n"); return FALSE; } else { if (status == 2) sprintf(full_name, loc("Invalid user name %s"), user); else { getcfg(logbook_name, "Password file", str); sprintf(full_name, loc("Cannot open file %s"), str); } show_error(full_name); return FALSE; } } /*------------------------------------------------------------------*/ void show_selection_page() { int i; char str[10000]; show_http_header(); 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 (!lb_list[i].name[0]) break; rsprintf("", lb_list[i].name_enc, lb_list[i].name); str[0] = 0; getcfg(lb_list[i].name, "Comment", str); rsprintf("\n", str); rsprintf("\n"); } 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 "); rsprintf(loc("%d entries"), *lb_list[i].n_el_index); rsprintf("
\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); } /*------------------------------------------------------------------*/ int do_self_register(LOGBOOK *lbs, char *command) /* evaluate self-registration commands */ { char str[256]; /* display new user page if "self register" is clicked */ if (equal_ustring(command, "New user")) { show_new_user_page(lbs); return 0; } /* save user info if "save" is pressed */ if (equal_ustring(command, loc("Save")) && isparam("new_user_name") && !isparam("config")) { if (!save_user_config(lbs, getparam("new_user_name"), TRUE, FALSE)) return 0; sprintf(str, "../%s/", lbs->name_enc); redirect(str); return 0; } /* display account request notification */ if (equal_ustring(command, "Requested")) { show_standard_header(loc("ELOG registration"), ""); rsprintf("

", gt("Border width"), gt("Frame color")); rsprintf("
\n", gt("Frame color")); rsprintf("\n
"); rsprintf(loc("Your request has been forward the the administrator. You will be notified by email upon activation of your new account.")); rsprintf("
\n"); rsprintf("\n"); return 0; } /* indicate continue */ return 1; } /*------------------------------------------------------------------*/ void interprete(char *lbook, char *path) /********************************************************************\ Routine: interprete Purpose: Interprete parametersand generate HTML output. Input: char *path Message path _param/_value array accessible via getparam() \********************************************************************/ { int i, j, n, index, lb_index, message_id; double exp; char str[256], enc_pwd[80], file_name[256], command[80], ref[256]; char enc_path[256], dec_path[256], logbook[256], logbook_enc[256]; char *experiment, *value, *group; time_t now; struct tm *gmt; LOGBOOK *lbs; FILE *f; /* encode path for further usage */ strcpy(dec_path, path); url_decode(dec_path); strcpy(enc_path, dec_path); url_encode(enc_path); strcpy(command, getparam("cmd")); experiment = getparam("exp"); 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); } else { strcpy(logbook_enc, lbook); strcpy(logbook, lbook); url_decode(logbook); } /* check if new logbook */ for (i=j=0 ; ; i++) { if (!enumgrp(i, str)) break; if (!equal_ustring(str, "global")) { /* redo index if logbooks in cfg file do not match lb_list */ if (!equal_ustring(str, lb_list[j++].name)) { el_index_logbooks(TRUE); break; } } } /* check for deleted logbook */ if (lb_list[j].name[0] != 0) el_index_logbooks(TRUE); /* check for global selection page if no logbook given */ if (!logbook[0] && getcfg("global", "Selection page", str)) { /* check if file starts with an absolute directory */ if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } send_file(file_name); return; } /* count logbooks */ for (n=0 ; lb_list[n].name[0] ; n++); /* if no logbook given, display logbook selection page */ if (!logbook[0]) { if (n > 1) { /* if password file is given in global section, protect also logbook selection page */ if (getcfg("global", "password file", str)) { if (getcfg("global", "Self register", str) && atoi(str) > 0) { if (!do_self_register(NULL, command)) return; } /* if data from login screen, evaluate it and set cookies */ 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 selection page", getparam("uname")); if (isparam("redir")) strcpy(str, getparam("redir")); else strcpy(str, getparam("cmdline")); if (!check_user_password(NULL, getparam("uname"), enc_pwd, str)) return; logf("Login of user \"%s\" (successful)", getparam("uname")); /* set cookies */ set_login_cookies(NULL, getparam("uname"), enc_pwd); return; } if (!check_user_password(NULL, getparam("unm"), getparam("upwd"), "")) return; } show_selection_page(); return; } strcpy(logbook_enc, logbook); url_encode(logbook_enc); } /* get logbook from list */ for (i=0 ; lb_list[i].name[0] ; i++) if (equal_ustring(logbook, lb_list[i].name)) break; lbs = &lb_list[i]; /* get theme for logbook */ if (getcfg(logbook, "Theme", str)) loadtheme(str); else loadtheme(NULL); /* get default values */ lb_index = i; lbs = lb_list+i; lbs->n_attr = scan_attributes(lbs->name); if (*getparam("wpassword")) { /* check if password correct */ do_crypt(getparam("wpassword"), enc_pwd); if (!check_password(lbs, "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]) sprintf(str, "../%s/", logbook_enc); 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(lbs, "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]) sprintf(str, "../%s/", logbook_enc); 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 (isparam("redir")) strcpy(str, getparam("redir")); else strcpy(str, getparam("cmdline")); if (!check_user_password(lbs->name, getparam("uname"), enc_pwd, str)) return; logf("Login of user \"%s\" (successful)", getparam("uname")); /* set cookies */ set_login_cookies(lbs, getparam("uname"), enc_pwd); return; } /* if password file given, check password and user name */ if (getcfg(logbook, "Password file", str)) { /* check if guest access */ if (getcfg(lbs->name, "Guest menu commands", str) && *getparam("unm") == 0) logf("Guest access"); else { /* if no guest menu commands but self register, evaluate new user commands */ if (getcfg(lbs->name, "Self register", str) && atoi(str) > 0) { if (!do_self_register(lbs, command)) return; } logf("Connection of user \"%s\"",getparam("unm")); if (!check_user_password(lbs->name, getparam("unm"), getparam("upwd"), getparam("cmdline"))) return; } } if (equal_ustring(command, loc("Login"))) { check_user_password(lbs->name, "", "", path); return; } if (equal_ustring(command, loc("New")) || equal_ustring(command, loc("Edit")) || equal_ustring(command, loc("Reply")) || equal_ustring(command, loc("Delete")) || equal_ustring(command, loc("Submit"))) { sprintf(str, "%s?cmd=%s", path, command); if (!check_password(lbs, "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(lbs, "Admin password", getparam("apwd"), str)) return; } /* check for "Back" button */ if (equal_ustring(command, loc("Back")) && getcfg(lbs->name, "Back to main", str) && atoi(str) == 1) { redirect("../"); return; } if (equal_ustring(command, loc("Back"))) { if (isparam("orig")) sprintf(str, "../%s/%s", logbook_enc, getparam("orig")); else sprintf(str, "../%s/", logbook_enc); redirect(str); return; } /* check for "Cancel" button */ if (equal_ustring(command, loc("Cancel"))) { sprintf(str, "../%s/%s", logbook_enc, path); redirect(str); return; } /* check for "Last n*2 Entries" */ strcpy(str, getparam("last")); if (strchr(str, ' ')) { i = atoi(strchr(str, ' ')); sprintf(str, "last%d", i); if (isparam("mode")) sprintf(str+strlen(str), "?mode=%s", getparam("mode")); redirect(str); return; } strcpy(str, getparam("past")); if (strchr(str, ' ')) { i = atoi(strchr(str, ' ')); sprintf(str, "past%d", i); redirect(str); return; } /* check for lastxx and pastxx and listxx */ if (strncmp(path, "past", 4) == 0 && *getparam("cmd") == 0) { show_elog_submit_find(lbs, atoi(path+4), 0, 0); return; } if (strncmp(path, "last", 4) == 0 && strstr(path, ".gif") == NULL && (!isparam("cmd") || equal_ustring(getparam("cmd"), loc("Select"))) && !isparam("newpwd")) { show_elog_submit_find(lbs, 0, atoi(path+4), 0); return; } if (strncmp(path, "page", 4) == 0 && *getparam("cmd") == 0) { if (!path[4]) show_elog_submit_find(lbs, 0, 0, -1); else show_elog_submit_find(lbs, 0, 0, atoi(path+4)); return; } /*---- check if file requested -----------------------------------*/ if ((strlen(dec_path) > 13 && dec_path[6] == '_' && dec_path[13] == '_') || (strlen(dec_path) > 13 && dec_path[6] == '_' && dec_path[13] == '/') || strstr(dec_path, ".gif") || strstr(dec_path, ".jpg") || strstr(dec_path, ".jpeg") || strstr(dec_path, ".png")) { if ((strlen(dec_path) > 13 && dec_path[6] == '_' && dec_path[13] == '_') || (strlen(dec_path) > 13 && dec_path[6] == '_' && dec_path[13] == '/')) { if (dec_path[13] == '/') dec_path[13] = '_'; /* file from data directory requested */ strcpy(file_name, lbs->data_dir); strcat(file_name, dec_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, dec_path); } send_file(file_name); return; } /* check for new syntax in elogd.cfg */ if (getcfg(lbs->name, "Types", str)) { show_upgrade_page(lbs); return; } /* 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(lbs, command)) { sprintf(str, loc("Error: Command \"%s\" is not allowed for user \"%s\""), command, getparam("full_name")); show_error(str); return; } /*---- check for various commands --------------------------------*/ if (equal_ustring(command, loc("Help"))) { if (getcfg(lbs->name, "Help URL", str)) { /* if file is given, add '/' to make absolute path */ if (strchr(str, '/') == NULL) sprintf(ref, "/%s", str); else strcpy(ref, str); redirect(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) redirect("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(lbs, 0, FALSE); return; } message_id = atoi(dec_path); if (equal_ustring(command, loc("Edit"))) { if (message_id) { show_elog_new(lbs, message_id, TRUE); return; } } if (equal_ustring(command, loc("Reply"))) { show_elog_new(lbs, message_id, FALSE); return; } if (equal_ustring(command, loc("Submit")) || equal_ustring(command, "Submit")) { submit_elog(lbs); return; } if (equal_ustring(command, loc("Find"))) { /* stip message id */ if (dec_path[0]) { sprintf(str, "../%s/?cmd=%s", lbs->name_enc, loc("Find")); redirect(str); return; } show_elog_find(lbs); return; } if (equal_ustring(command, loc("Search"))) { if (dec_path[0] && atoi(dec_path) == 0 && strchr(dec_path, '/') != NULL) { sprintf(str, "Invalid URL: %s", dec_path); show_error(str); return; } show_elog_submit_find(lbs, 0, 0, 1); 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(lbs, message_id, getparam("destc"), 0); return; } if (equal_ustring(command, loc("Move to"))) { copy_to(lbs, message_id, getparam("destm"), 1); return; } if (equal_ustring(command, loc("Admin"))) { show_admin_page(lbs); return; } if (equal_ustring(command, loc("Change password")) || (isparam("newpwd") && !equal_ustring(command, loc("Cancel")) && !equal_ustring(command, loc("Save")))) { show_change_pwd_page(lbs); return; } if (equal_ustring(command, loc("Save"))) { if (isparam("config")) { /* change existing user */ if (!save_user_config(lbs, getparam("config"), FALSE, FALSE)) return; } else if (isparam("new_user_name")) { /* new user */ if (!save_user_config(lbs, getparam("new_user_name"), TRUE, FALSE)) return; } else if (!save_admin_config()) /* save cfg file */ return; sprintf(str, "../%s/", lbs->name_enc); redirect(str); return; } if (equal_ustring(command, "Activate")) { if (!save_user_config(lbs, getparam("new_user_name"), TRUE, TRUE)) return; setparam("cfg_user", getparam("new_user_name")); show_config_page(lbs); return; } if (equal_ustring(command, loc("Remove user"))) { remove_user(lbs, getparam("config")); /* if removed user is current user, do logout */ if (equal_ustring(getparam("config"), getparam("unm"))) { /* log activity */ logf("Logout of user \"%s\" from logbook \"%s\"", getparam("unm"), lbs->name); /* set cookies */ set_login_cookies(lbs, "", ""); } /* continue configuration as administrator */ unsetparam("cfg_user"); show_config_page(lbs); return; } if (equal_ustring(command, loc("New user"))) { show_new_user_page(lbs); return; } if (equal_ustring(command, loc("Config"))) { if (!getcfg(lbs->name, "Password file", str)) show_admin_page(lbs); else show_config_page(lbs); return; } if (equal_ustring(command, loc("Download"))) { show_download_page(lbs, dec_path); return; } if (equal_ustring(command, loc("Logout"))) { /* log activity */ logf("Logout of user \"%s\" from logbook \"%s\"", getparam("unm"), lbs->name); if (getcfg(lbs->name, "Logout to main", str) && atoi(str) == 1) setparam("redir", "../"); set_login_cookies(lbs, "", ""); return; } if (equal_ustring(command, loc("Delete"))) { show_elog_delete(lbs, message_id); return; } /* check for welcome page */ if (!_cmdline[0] && getcfg(lbs->name, "Welcome page", str) && str[0]) { /* check if file starts with an absolute directory */ if (str[0] == DIR_SEPARATOR || str[1] == ':') strcpy(file_name, str); else { strcpy(file_name, cfg_dir); strcat(file_name, str); } send_file(file_name); return; } /* check for start page */ if (!_cmdline[0] && getcfg(lbs->name, "Start page", str) && str[0]) { redirect(str); return; } /* show page listing or display single entry */ if (dec_path[0] == 0) show_elog_submit_find(lbs, 0, 0, 1); else show_elog_page(lbs, dec_path, command); return; } /*------------------------------------------------------------------*/ void decode_get(char *logbook, char *string) { char path[256]; char *p, *pitem; setparam("cmdline", string); 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(logbook, path); } /*------------------------------------------------------------------*/ void decode_post(char *logbook, 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); signal(SIGPIPE, SIG_IGN); /* give up root privilege */ if (geteuid() == 0) { struct group *gr; struct passwd *pw; if (getcfg("global", "Group", str)) { gr = getgrnam(str); if (gr == NULL) printf("Group \"%s\" not found\n", str); else 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 (pw == NULL) printf("User \"%s\" not found\n", str); else 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 ; ih_name); else strcpy(remote_host[i_conn], (char *)inet_ntoa(rem_addr)); strcpy(rem_host, remote_host[i_conn]); #ifdef DEBUG_CONN printf("## open new connection %d\n", i_conn); #endif } else { /* check if open connection received data */ 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)); strcpy(rem_host, remote_host[i_conn]); #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; } /* extract browser */ browser[0] = 0; if ((p = strstr(net_buffer, "User-Agent:")) != NULL) { p += 11; while (*p && *p == ' ') p++; strncpy(browser, p, sizeof(browser)); if (strchr(browser, '\r')) *strchr(browser, '\r') = 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 for trailing '/' after logbook */ if (strstr(net_buffer, "POST") == NULL) // fix for konqueror { if (logbook[0] && *p == ' ') { sprintf(str, "%s/", logbook_enc); redirect(str); goto redir; } } /* check for trailing '/' after logbook/ID */ if (logbook[0] && *p == '/' && *(p+1) != ' ') { sprintf(url, "%s", logbook_enc); pd = url+strlen(url); while (*p && *p != ' ') *pd++ = *p++; *pd = 0; if (*(p-1) == '/') { sprintf(str, "Invalid URL: %s", url); show_error(str); send(_sock, return_buffer, strlen_retbuf+1, 0); keep_alive = 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 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; } } /*---- check "hosts deny" ----*/ authorized = 1; if (getcfg(logbook, "Hosts deny", list)) { 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+strlen(rem_host)-strlen(host_list[i]))) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts deny\". Access denied.\n", rem_host, 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)) { 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+strlen(rem_host)-strlen(host_list[i]))) { if (verbose) printf("Remote host \"%s\" matches \"%s\" in \"Hosts allow\". Access granted.\n", rem_host, 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; /* strip 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(logbook, p); } else if (strncmp(net_buffer, "POST", 4) == 0) { if (verbose) printf("%s\n", net_buffer+header_length); decode_post(logbook, net_buffer+header_length, boundary, content_length); } else { net_buffer[50] = 0; sprintf(str, "Unknown request:

%s", net_buffer); show_error(str); } } redir: 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, tcp_port_cl; int daemon = FALSE; char read_pwd[80], write_pwd[80], admin_pwd[80], str[80], logbook[256]; time_t now; struct tm *tms; tzset(); read_pwd[0] = write_pwd[0] = admin_pwd[0] = logbook[0] = 0; tcp_port_cl = 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_cl = 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); /* build logbook indices */ if (el_index_logbooks(FALSE) != EL_SUCCESS) return 1; /* get port from configuration file */ if (tcp_port_cl != 0) tcp_port = tcp_port_cl; else { if (getcfg("global", "Port", str)) tcp_port = atoi(str); } server_loop(tcp_port, daemon); #ifdef OS_UNIX unlink("/var/run/elogd.pid"); #endif return 0; }