/********************************************************************\
Name: elogd.c
Created by: Stefan Ritt
Contents: Web server program for Electronic Logbook ELOG
$Log$
Revision 1.31 2002/06/03 09:55:08 midas
Added 'start page=' option
Revision 1.30 2002/06/03 09:37:47 midas
Fixed bug with MOptions in Email notification
Revision 1.29 2002/06/03 08:30:44 midas
Add
for replies in HTML format
Revision 1.28 2002/06/03 08:12:24 midas
Reversed setuid() and creation of elogd.pid
Revision 1.27 2002/06/03 08:07:47 midas
elogd.pid is now created from child
Revision 1.26 2002/06/03 07:32:27 midas
Added 'Title image URL' in theme file
Revision 1.25 2002/05/31 14:20:50 midas
Added 'user' and 'group' statements in configuration file
Revision 1.24 2002/05/31 13:24:18 midas
Use Referer for mail notification URL
Revision 1.23 2002/05/31 12:51:58 midas
First version with truely relative paths
Revision 1.22 2002/05/13 20:50:53 midas
Fixed problem with daylight savings time
Revision 1.21 2002/05/03 07:39:16 midas
Fixed bug with "Content-Length"
Revision 1.20 2002/05/02 15:42:06 midas
Removed lingering and do a REUSEADDR by default
Revision 1.19 2002/05/02 14:45:10 midas
Evaluage 'HEAD' request (for wget)
Revision 1.18 2002/04/30 13:40:33 midas
Version 1.3.5
Revision 1.17 2002/04/29 08:11:38 midas
Added icons via IOptions configuration
Revision 1.16 2002/04/22 10:32:35 midas
Version 1.3.4
Revision 1.15 2002/04/22 10:31:58 midas
Added "logfile", fixed hightlighting problems, thanks to
Heiko.Schleit@mpi-hd.mpg.de
Revision 1.14 2002/03/14 11:48:43 midas
Added .jpeg file extension
Revision 1.13 2002/02/25 16:12:26 midas
Added BGImage and BDTImage in themes
Revision 1.12 2002/02/25 15:31:04 midas
Made "move to", "copy to" and "submit" (from elog) work in other languages
Revision 1.11 2002/02/12 16:06:10 midas
Fixed small bug
Revision 1.10 2002/01/31 00:51:41 midas
Small patch to make elogd run under Mac OS X (Darwin), thanks to Dominik Westner
Revision 1.9 2002/01/30 04:26:05 midas
Added flag 'restrict edit = 0/1'
Revision 1.8 2002/01/29 10:06:23 midas
Fixed various bugs with fixed attributes
Revision 1.7 2002/01/23 08:41:42 midas
Added "Search all logbooks" flag
Revision 1.6 2002/01/15 10:23:59 midas
- Remove "back" button from error display (NS4.7 does not support it)
- Fixed wrong URL in email notification
- Submission of new messages possible even if cookie expired during editing
Revision 1.5 2002/01/14 13:05:41 midas
- Check for JavaScript in error display
- Improved decoding of POST message (needed for lynx)
Revision 1.4 2001/12/21 16:03:23 midas
Moved themes directories under "themes/"
Revision 1.3 2001/12/21 15:28:51 midas
Initial version as separate package, corresponds to V1.3.2
\********************************************************************/
/* Version of ELOG */
#define VERSION "1.3.6"
#include
#include
#include
#include
#include
#include
#ifdef _MSC_VER
#define OS_WINNT
#define DIR_SEPARATOR '\\'
#define DIR_SEPARATOR_STR "\\"
#define snprintf _snprintf
#include
#include
#include
#else
#define OS_UNIX
#define TRUE 1
#define FALSE 0
#define DIR_SEPARATOR '/'
#define DIR_SEPARATOR_STR "/"
#define __USE_XOPEN /* needed for crypt() */
typedef int BOOL;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define closesocket(s) close(s)
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif
typedef int INT;
#define TELL(fh) lseek(fh, 0, SEEK_CUR)
#define NAME_LENGTH 256
#define SUCCESS 1
#define EL_SUCCESS 1
#define EL_FIRST_MSG 2
#define EL_LAST_MSG 3
#define EL_NO_MSG 4
#define EL_FILE_ERROR 5
#define WEB_BUFFER_SIZE 2000000
char return_buffer[WEB_BUFFER_SIZE];
int strlen_retbuf;
int keep_alive;
char header_buffer[1000];
int return_length;
char host_name[256];
char referer[256];
char logbook[256];
char logbook_enc[256];
char data_dir[256];
char cfg_file[256];
char cfg_dir[256];
char tcp_hostname[256];
int tcp_port = 80;
#define MAX_GROUPS 32
#define MAX_PARAM 100
#define MAX_ATTACHMENTS 10
#define MAX_N_LIST 100
#define MAX_N_ATTR 50
#define VALUE_SIZE 256
#define PARAM_LENGTH 256
#define TEXT_SIZE 50000
#define MAX_PATH_LENGTH 256
char _param[MAX_PARAM][PARAM_LENGTH];
char _value[MAX_PARAM][VALUE_SIZE];
char _text[TEXT_SIZE];
char *_attachment_buffer[MAX_ATTACHMENTS];
INT _attachment_size[MAX_ATTACHMENTS];
struct in_addr rem_addr;
INT _sock;
BOOL verbose, use_keepalive;
char *mname[] = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
char type_list[MAX_N_LIST][NAME_LENGTH] = {
"Routine",
"Other"
};
char category_list[MAX_N_LIST][NAME_LENGTH] = {
"General",
"Other",
};
char author_list[MAX_N_LIST][NAME_LENGTH] = {
""
};
/* attribute flags */
#define AF_REQUIRED (1<<0)
#define AF_LOCKED (1<<1)
#define AF_MULTI (1<<2)
#define AF_FIXED (1<<3)
#define AF_ICON (1<<4)
char attr_list[MAX_N_ATTR][NAME_LENGTH];
char attr_options[MAX_N_ATTR][MAX_N_LIST][NAME_LENGTH];
int attr_flags[MAX_N_ATTR];
char attr_list_default[][NAME_LENGTH] = {
"Author",
"Type",
"Category",
"Subject",
""
};
char attr_options_default[][MAX_N_LIST][NAME_LENGTH] = {
{ "" },
{ "Routine", "Other" },
{ "General", "Other" },
{ "" }
};
int attr_flags_default[] = {
AF_REQUIRED,
0,
0,
0
};
struct {
char ext[32];
char type[32];
} filetype[] = {
{ ".JPG", "image/jpeg" },
{ ".JPEG", "image/jpeg" },
{ ".GIF", "image/gif" },
{ ".PNG", "image/png" },
{ ".PS", "application/postscript" },
{ ".EPS", "application/postscript" },
{ ".HTML", "text/html" },
{ ".HTM", "text/html" },
{ ".XLS", "application/x-msexcel" },
{ ".DOC", "application/msword" },
{ ".PDF", "application/pdf" },
{ ".TXT", "text/plain" },
{ ".ASC", "text/plain" },
{ ".ZIP", "application/x-zip-compressed" },
{ "" },
};
int scan_attributes(char *logbook);
void show_error(char *error);
/*---- Funcions from the MIDAS library -----------------------------*/
BOOL equal_ustring(char *str1, char *str2)
{
if (str1 == NULL && str2 != NULL)
return FALSE;
if (str1 != NULL && str2 == NULL)
return FALSE;
if (str1 == NULL && str2 == NULL)
return TRUE;
while (*str1)
if (toupper(*str1++) != toupper(*str2++))
return FALSE;
if (*str2)
return FALSE;
return TRUE;
}
/*-------------------------------------------------------------------*/
void strsubst(char *string, char name[][NAME_LENGTH], char value[][NAME_LENGTH], int n)
/* subsitute "$name" with value corresponding to name */
{
int i, j;
char tmp[1000], str[256], uattr[256], *ps, *pt, *p;
pt = tmp;
ps = string;
for (p = strchr(ps, '$') ; p != NULL ; p = strchr(ps, '$'))
{
/* copy leading characters */
j = (int)(p-ps);
memcpy(pt, ps, j);
pt += j;
p++;
/* extract name */
strcpy(str, p);
for (j=0 ; j<(int)strlen(str) ; j++)
str[j] = toupper(str[j]);
/* search name */
for (i=0 ; i>= 8;
*(d+1) = (char) (t & 0xFF);
t >>= 8;
*d = (char) (t & 0xFF);
d += 3;
}
*d = 0;
}
void base64_encode(char *s, char *d)
{
unsigned int t, pad;
pad = 3 - strlen(s) % 3;
while (*s)
{
t = (*s++) << 16;
if (*s)
t |= (*s++) << 8;
if (*s)
t |= (*s++) << 0;
*(d+3) = map[t & 63];
t >>= 6;
*(d+2) = map[t & 63];
t >>= 6;
*(d+1) = map[t & 63];
t >>= 6;
*(d+0) = map[t & 63];
d += 4;
}
*d = 0;
while (pad--)
*(--d) = '=';
}
void do_crypt(char *s, char *d)
{
#ifdef USE_CRYPT
strcpy(d, crypt(s, "el"));
#else
base64_encode(s, d);
#endif
}
/*-------------------------------------------------------------------*/
INT recv_string(int sock, char *buffer, INT buffer_size, INT millisec)
{
INT i, n;
fd_set readfds;
struct timeval timeout;
n = 0;
memset(buffer, 0, buffer_size);
do
{
if (millisec > 0)
{
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
timeout.tv_sec = millisec / 1000;
timeout.tv_usec = (millisec % 1000) * 1000;
select(FD_SETSIZE, (void *) &readfds, NULL, NULL, (void *) &timeout);
if (!FD_ISSET(sock, &readfds))
break;
}
i = recv(sock, buffer+n, 1, 0);
if (i<=0)
break;
n++;
if (n >= buffer_size)
break;
} while (buffer[n-1] && buffer[n-1] != 10);
return n-1;
}
INT sendmail(char *smtp_host, char *from, char *to, char *subject, char *text)
{
struct sockaddr_in bind_addr;
struct hostent *phe;
int s, offset;
char buf[80];
char str[10000];
time_t now;
struct tm *ts;
if (verbose)
printf("\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host);
/* create a new socket for connecting to remote server */
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1)
return -1;
/* connect to remote node port 25 */
memset(&bind_addr, 0, sizeof(bind_addr));
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons((short) 25);
phe = gethostbyname(smtp_host);
if (phe == NULL)
return -1;
memcpy((char *)&(bind_addr.sin_addr), phe->h_addr, phe->h_length);
if (connect(s, (void *) &bind_addr, sizeof(bind_addr)) < 0)
{
closesocket(s);
return -1;
}
recv_string(s, str, sizeof(str), 10000);
if (verbose) puts(str);
/* drain server messages */
do
{
str[0] = 0;
recv_string(s, str, sizeof(str), 300);
if (verbose) puts(str);
} while (str[0]);
snprintf(str, sizeof(str) - 1, "HELO %s\r\n", host_name);
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "MAIL FROM: <%s>\r\n", from);
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "RCPT TO: <%s>\r\n", to);
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "DATA\r\n");
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject);
send(s, str, strlen(str), 0);
if (verbose) puts(str);
time(&now);
ts = localtime(&now);
strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S", ts);
offset = (-(int)timezone);
if (daylight)
offset += 3600;
snprintf(str, sizeof(str) - 1, "Date: %s %+03d%02d\r\n\r\n", buf,
(int) (offset/3600), (int) ((abs((int)offset)/60) % 60));
send(s, str, strlen(str), 0);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "%s\r\n.\r\n", text);
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
snprintf(str, sizeof(str) - 1, "QUIT\r\n");
send(s, str, strlen(str), 0);
if (verbose) puts(str);
recv_string(s, str, sizeof(str), 3000);
if (verbose) puts(str);
closesocket(s);
return 1;
}
/*-------------------------------------------------------------------*/
INT ss_daemon_init()
{
#ifdef OS_UNIX
/* only implemented for UNIX */
int i, fd, pid;
if ( (pid = fork()) < 0)
return 0;
else if (pid != 0)
exit(0); /* parent finished */
/* child continues here */
/* try and use up stdin, stdout and stderr, so other
routines writing to stdout etc won't cause havoc. Copied from smbd */
for (i=0 ; i<3 ; i++)
{
close(i);
fd = open("/dev/null", O_RDWR, 0);
if (fd < 0)
fd = open("/dev/null", O_WRONLY, 0);
if (fd < 0)
{
printf("Can't open /dev/null");
return 0;
}
if (fd != i)
{
printf("Did not get file descriptor");
return 0;
}
}
setsid(); /* become session leader */
chdir("/"); /* change working direcotry (not on NFS!) */
umask(0); /* clear our file mode creation mask */
#endif
return SUCCESS;
}
/*------------------------------------------------------------------*/
/* Parameter extraction from configuration file similar to win.ini */
char *cfgbuffer;
int getcfg(char *group, char *param, char *value)
{
char str[10000], *p, *pstr;
int length;
int fh;
value[0] = 0;
/* read configuration file on init */
if (!cfgbuffer)
{
fh = open(cfg_file, O_RDONLY | O_BINARY);
if (fh < 0)
return 0;
length = lseek(fh, 0, SEEK_END);
lseek(fh, 0, SEEK_SET);
cfgbuffer = malloc(length+1);
if (cfgbuffer == NULL)
{
close(fh);
return 0;
}
read(fh, cfgbuffer, length);
cfgbuffer[length] = 0;
close(fh);
}
/* search group */
p = cfgbuffer;
do
{
if (*p == '[')
{
p++;
pstr = str;
while (*p && *p != ']' && *p != '\n')
*pstr++ = *p++;
*pstr = 0;
if (equal_ustring(str, group))
{
/* search parameter */
p = strchr(p, '\n');
if (p)
p++;
while (p && *p && *p != '[')
{
pstr = str;
while (*p && *p != '=' && *p != '\n')
*pstr++ = *p++;
*pstr-- = 0;
while (pstr > str && (*pstr == ' ' || *pstr == '=' || *pstr == '\t'))
*pstr-- = 0;
if (equal_ustring(str, param))
{
if (*p == '=')
{
p++;
while (*p == ' ' || *p == '\t')
p++;
pstr = str;
while (*p && *p != '\n' && *p != '\r')
*pstr++ = *p++;
*pstr-- = 0;
while (*pstr == ' ' || *pstr == '\t')
*pstr-- = 0;
strcpy(value, str);
return 1;
}
}
if (p)
p = strchr(p, '\n');
if (p)
p++;
}
}
}
if (p)
p = strchr(p, '\n');
if (p)
p++;
} while (p);
/* if parameter not found in logbook, look in [global] section */
if (!equal_ustring(group, "global"))
return getcfg("global", param, value);
return 0;
}
/*------------------------------------------------------------------*/
int enumcfg(char *group, char *param, char *value, int index)
{
char str[10000], *p, *pstr;
int i;
/* open configuration file */
if (!cfgbuffer)
getcfg("dummy", "dummy", str);
if (!cfgbuffer)
return 0;
/* search group */
p = cfgbuffer;
do
{
if (*p == '[')
{
p++;
pstr = str;
while (*p && *p != ']' && *p != '\n' && *p != '\r')
*pstr++ = *p++;
*pstr = 0;
if (equal_ustring(str, group))
{
/* enumerate parameters */
i = 0;
p = strchr(p, '\n');
if (p)
p++;
while (p && *p && *p != '[')
{
pstr = str;
while (*p && *p != '=' && *p != '\n' && *p != '\r')
*pstr++ = *p++;
*pstr-- = 0;
while (pstr > str && (*pstr == ' ' || *pstr == '='))
*pstr-- = 0;
if (i == index)
{
strcpy(param, str);
if (*p == '=')
{
p++;
while (*p == ' ')
p++;
pstr = str;
while (*p && *p != '\n' && *p != '\r')
*pstr++ = *p++;
*pstr-- = 0;
while (*pstr == ' ')
*pstr-- = 0;
if (value)
strcpy(value, str);
}
return 1;
}
if (p)
p = strchr(p, '\n');
if (p)
p++;
i++;
}
}
}
if (p)
p = strchr(p, '\n');
if (p)
p++;
} while (p);
return 0;
}
/*------------------------------------------------------------------*/
int enumgrp(int index, char *group)
{
char str[10000], *p, *pstr;
int i;
/* open configuration file */
if (!cfgbuffer)
getcfg("dummy", "dummy", str);
if (!cfgbuffer)
return 0;
/* search group */
p = cfgbuffer;
i = 0;
do
{
if (*p == '[')
{
p++;
pstr = str;
while (*p && *p != ']' && *p != '\n' && *p != '\r')
*pstr++ = *p++;
*pstr = 0;
if (i == index)
{
strcpy(group, str);
return 1;
}
i++;
}
while (*p && *p != '\r' && *p != '\n')
p++;
while (*p && (*p == '\r' || *p == '\n'))
p++;
} while (*p);
return 0;
}
/*-------------------------------------------------------------------*/
char *locbuffer = NULL;
char **porig, **ptrans;
/* localization support */
char *loc(char *orig)
{
char language[256], file_name[256], *p;
int fh, length, n;
static char old_language[256];
getcfg("global", "Language", language);
if (!equal_ustring(language, old_language))
{
if (equal_ustring(language, "english") ||
language[0] == 0)
{
if (locbuffer)
{
free(locbuffer);
locbuffer = NULL;
}
}
else
{
strcpy(file_name, cfg_dir);
strcat(file_name, "eloglang.");
strcat(file_name, language);
fh = open(file_name, O_RDONLY | O_BINARY);
if (fh < 0)
return orig;
length = lseek(fh, 0, SEEK_END);
lseek(fh, 0, SEEK_SET);
locbuffer = malloc(length+1);
if (locbuffer == NULL)
{
close(fh);
return orig;
}
read(fh, locbuffer, length);
locbuffer[length] = 0;
close(fh);
/* scan lines, setup orig-translated pointers */
p = locbuffer;
n = 0;
do
{
while (*p && (*p == '\r' || *p == '\n'))
p++;
if (*p && (*p == ';' || *p == '#' || *p == ' ' || *p == '\t'))
{
while (*p && *p != '\n' && *p != '\r')
p++;
continue;
}
if (n == 0)
{
porig = malloc(sizeof(char *) * 2);
ptrans = malloc(sizeof(char *) * 2);
}
else
{
porig = realloc(porig, sizeof(char *) * (n + 2));
ptrans = realloc(ptrans, sizeof(char *) * (n + 2));
}
porig[n] = p;
while (*p && (*p != '=' && *p != '\r' && *p != '\n'))
p++;
if (*p && *p != '=')
continue;
ptrans[n] = p + 1;
while (*ptrans[n] == ' ')
ptrans[n] ++;
/* remove '=' and surrounding blanks */
while (*p == '=' || *p == ' ')
*p-- = 0;
p = ptrans[n];
while (*p && *p != '\n' && *p != '\r')
p++;
if (p)
*p++ = 0;
n++;
} while (p && *p);
porig[n] = NULL;
}
strcpy(old_language, language);
}
if (!locbuffer)
return orig;
/* search string and return translation */
for (n = 0; porig[n] ; n++)
if (strcmp(orig, porig[n]) == 0)
{
if (*ptrans[n])
return ptrans[n];
return orig;
}
return orig;
}
/*------------------------------------------------------------------*/
/* Parameter extraction from themes file */
typedef struct {
char name[32];
char value[256];
} THEME;
THEME default_theme [] = {
{ "Table width", "100%" },
{ "Frame color", "#486090" },
{ "Cell BGColor", "#E6E6E6" },
{ "Border width", "0" },
{ "Title BGColor", "#486090" },
{ "Title Fontcolor", "#FFFFFF" },
{ "Title Cellpadding", "0" },
{ "Title Image", "" },
{ "Title Image URL", "" },
{ "Merge menus", "1" },
{ "Use buttons", "0" },
{ "Menu1 BGColor", "#E0E0E0" },
{ "Menu1 Align", "left" },
{ "Menu1 Cellpadding", "0" },
{ "Menu2 BGColor", "#FFFFB0" },
{ "Menu2 Align", "center" },
{ "Menu2 Cellpadding", "0" },
{ "Menu2 use images", "0" },
{ "Categories cellpadding", "3" },
{ "Categories border", "0" },
{ "Categories BGColor1", "#CCCCFF" },
{ "Categories BGColor2", "#DDEEBB" },
{ "Text BGColor", "#FFFFFF" },
{ "List bgcolor1", "#DDEEBB" },
{ "List bgcolor2", "#FFFFB0" },
{ "BGImage", "" },
{ "BGTImage", "" },
{ "" }
};
THEME *theme = NULL;
char theme_name[80];
/*------------------------------------------------------------------*/
void loadtheme(char *tn)
{
FILE *f;
char *p, line[256], item[256], value[256], file_name[256];
int i;
if (theme == NULL)
theme = malloc(sizeof(default_theme));
/* copy default theme */
memcpy(theme, default_theme, sizeof(default_theme));
/* use default if no name is given */
if (tn == NULL)
return;
memset(file_name, 0, sizeof(file_name));
strcpy(file_name, cfg_dir);
strcat(file_name, "themes");
strcat(file_name, DIR_SEPARATOR_STR);
strcat(file_name, tn);
strcat(file_name, DIR_SEPARATOR_STR);
strcat(file_name, "theme.cfg");
f = fopen(file_name, "r");
if (f == NULL)
return;
strcpy(theme_name, tn);
do
{
line[0] = 0;
fgets(line, sizeof(line), f);
/* ignore comments */
if (line[0] == ';' || line[0] == '#')
continue;
if (strchr(line, '='))
{
/* split line into item and value, strop blanks */
strcpy(item, line);
p = strchr(item, '=');
while ((*p == '=' || *p == ' ') && p > item)
*p-- = 0;
p = strchr(line, '=');
while (*p && (*p == '=' || *p == ' '))
p++;
strcpy(value, p);
if (strlen(value) > 0)
{
p = value+strlen(value)-1;
while (p >= value && (*p == ' ' || *p == '\r' || *p == '\n'))
*(p--) = 0;
}
/* find field in _theme and set it */
for (i=0 ; theme[i].name[0] ; i++)
if (equal_ustring(item, theme[i].name))
{
strcpy(theme[i].value, value);
break;
}
}
} while (!feof(f));
fclose(f);
return;
}
/*------------------------------------------------------------------*/
/* get a certain theme attribute from currently loaded file */
char *gt(char *name)
{
int i;
if (theme == NULL)
loadtheme(NULL);
for (i=0 ; theme[i].name[0] ; i++)
if (equal_ustring(theme[i].name, name))
return theme[i].value;
return "";
}
/*------------------------------------------------------------------*/
void el_decode(char *message, char *key, char *result)
{
char *pc;
if (result == NULL)
return;
*result = 0;
if (strstr(message, key))
{
for (pc=strstr(message, key)+strlen(key) ; *pc != '\n' && *pc != '\r' ; )
*result++ = *pc++;
*result = 0;
}
}
/*------------------------------------------------------------------*/
/* Simplified copy of fnmatch() for Cygwin where fnmatch is not defined */
#define EOS '\0'
int fnmatch1(const char *pattern, const char *string)
{
const char *stringstart;
char c, test;
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
return (*string == EOS ? 0 : 1);
case '?':
if (*string == EOS)
return (1);
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*')
c = *++pattern;
/* Optimize for pattern with * at end or before /. */
if (c == EOS)
return (0);
/* General case, use recursion. */
while ((test = *string) != EOS)
{
if (!fnmatch1(pattern, string))
return (0);
++string;
}
return (1);
/* FALLTHROUGH */
default:
if (c != *string)
return (1);
string++;
break;
}
}
/*------------------------------------------------------------------*/
INT ss_file_find(char * path, char * pattern, char **plist)
/********************************************************************\
Routine: ss_file_find
Purpose: Return list of files matching 'pattern' from the 'path' location
Input:
char *path Name of a file in file system to check
char *pattern pattern string (wildcard allowed)
Output:
char **plist pointer to the lfile list
Function value:
int Number of files matching request
\********************************************************************/
{
int i;
#ifdef OS_UNIX
DIR *dir_pointer;
struct dirent *dp;
if ((dir_pointer = opendir(path)) == NULL)
return 0;
*plist = (char *) malloc(MAX_PATH_LENGTH);
i = 0;
for (dp = readdir(dir_pointer); dp != NULL; dp = readdir(dir_pointer))
{
if (fnmatch1(pattern, dp->d_name) == 0)
{
*plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH);
strncpy(*plist+(i*MAX_PATH_LENGTH), dp->d_name, strlen(dp->d_name));
*(*plist+(i*MAX_PATH_LENGTH)+strlen(dp->d_name)) = '\0';
i++;
seekdir(dir_pointer, telldir(dir_pointer));
}
}
closedir(dir_pointer);
#endif
#ifdef OS_WINNT
HANDLE pffile;
LPWIN32_FIND_DATA lpfdata;
char str[255];
int first;
strcpy(str,path);
strcat(str,"\\");
strcat(str,pattern);
first = 1;
i = 0;
lpfdata = malloc(sizeof(WIN32_FIND_DATA));
*plist = (char *) malloc(MAX_PATH_LENGTH);
pffile = FindFirstFile(str, lpfdata);
if (pffile == INVALID_HANDLE_VALUE)
return 0;
first = 0;
*plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH);
strncpy(*plist+(i*MAX_PATH_LENGTH), lpfdata->cFileName, strlen(lpfdata->cFileName));
*(*plist+(i*MAX_PATH_LENGTH)+strlen(lpfdata->cFileName)) = '\0';
i++;
while (FindNextFile(pffile, lpfdata))
{
*plist = (char *)realloc(*plist, (i+1)*MAX_PATH_LENGTH);
strncpy(*plist+(i*MAX_PATH_LENGTH), lpfdata->cFileName, strlen(lpfdata->cFileName));
*(*plist+(i*MAX_PATH_LENGTH)+strlen(lpfdata->cFileName)) = '\0';
i++;
}
free(lpfdata);
#endif
return i;
}
/*------------------------------------------------------------------*/
INT el_search_message(char *tag, int *fh, BOOL walk, BOOL first)
{
int lfh, i, n, d, min, max, size, offset, direction, last, status, did_walk;
struct tm *tms, ltms;
time_t lt, ltime, lact;
char str[256], file_name[256], dir[256];
char *file_list;
did_walk = 0;
ltime = lfh = 0;
/* get data directory */
strcpy(dir, data_dir);
/* check tag for direction */
direction = 0;
if (strpbrk(tag, "+-"))
{
direction = atoi(strpbrk(tag, "+-"));
*strpbrk(tag, "+-") = 0;
}
/* if tag is given, open file directly */
if (tag[0])
{
/* extract time structure from tag */
tms = <ms;
memset(tms, 0, sizeof(struct tm));
tms->tm_year = (tag[0]-'0')*10 + (tag[1]-'0');
tms->tm_mon = (tag[2]-'0')*10 + (tag[3]-'0') -1;
tms->tm_mday = (tag[4]-'0')*10 + (tag[5]-'0');
tms->tm_hour = 12;
if (tms->tm_year < 90)
tms->tm_year += 100;
ltime = lt = mktime(tms);
if (ltime < 0)
return -1;
strcpy(str, tag);
if (strchr(str, '.'))
{
offset = atoi(strchr(str, '.')+1);
*strchr(str, '.') = 0;
}
else
return -1;
do
{
tms = localtime(<ime);
sprintf(file_name, "%s%02d%02d%02d.log", dir,
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday);
lfh = open(file_name, O_RDWR | O_BINARY, 0644);
if (lfh < 0)
{
if (!walk)
return EL_FILE_ERROR;
did_walk = 1;
if (direction == -1)
ltime -= 3600*24; /* one day back */
else
ltime += 3600*24; /* go forward one day */
/* set new tag */
tms = localtime(<ime);
sprintf(tag, "%02d%02d%02d.0", tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday);
}
/* in forward direction, stop today */
if (direction != -1 && ltime > (time_t)(time(NULL)+3600*24))
break;
/* in backward direction, go back 10 years */
if (direction == -1 && abs((int)(lt-ltime)) > 3600*24*365*10)
break;
} while (lfh < 0);
if (lfh < 0)
return EL_FILE_ERROR;
if (direction == -1 && did_walk)
lseek(lfh, 0, SEEK_END);
else
lseek(lfh, offset, SEEK_SET);
}
/* open most recent file if no tag given */
if (tag[0] == 0)
{
if (first)
{
/* go through whole directory, find first file */
file_list = NULL;
n = ss_file_find(dir, "??????.log", &file_list);
if (n == 0)
{
if (file_list)
free(file_list);
return EL_FILE_ERROR;
}
for (i=0,min=9999999 ; i max)
max = d;
}
free(file_list);
sprintf(file_name, "%s%06d.log", dir, max % 1000000);
lfh = open(file_name, O_RDWR | O_BINARY, 0644);
if (lfh < 0)
return EL_FILE_ERROR;
lseek(lfh, 0, SEEK_END);
/* remember tag */
sprintf(tag, "%06d.%d", (int) (max % 1000000), (int) (TELL(lfh)));
}
}
if (direction == -1)
{
/* seek previous message */
if (TELL(lfh) == 0)
{
/* go back one day */
close(lfh);
lt = ltime;
do
{
lt -= 3600*24;
tms = localtime(<);
sprintf(str, "%02d%02d%02d.0",
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday);
status = el_search_message(str, &lfh, FALSE, FALSE);
} while (status != SUCCESS &&
(INT)ltime-(INT)lt < 3600*24*365);
if (status != EL_SUCCESS)
{
if (fh)
*fh = lfh;
else
close(lfh);
return EL_FIRST_MSG;
}
/* adjust tag */
strcpy(tag, str);
/* go to end of current file */
lseek(lfh, 0, SEEK_END);
}
/* read previous message size */
lseek(lfh, -17, SEEK_CUR);
i = read(lfh, str, 17);
if (i <= 0)
{
close(lfh);
return EL_FILE_ERROR;
}
if (strncmp(str, "$End$: ", 7) == 0)
{
size = atoi(str+7);
lseek(lfh, -size, SEEK_CUR);
}
else
{
close(lfh);
return EL_FILE_ERROR;
}
/* adjust tag */
sprintf(strchr(tag, '.')+1, "%d", (int) (TELL(lfh)));
}
if (direction == 1)
{
/* seek next message */
/* read current message size */
last = TELL(lfh);
i = read(lfh, str, 15);
if (i <= 0)
{
close(lfh);
return EL_FILE_ERROR;
}
lseek(lfh, -15, SEEK_CUR);
if (strncmp(str, "$Start$: ", 9) == 0)
{
size = atoi(str+9);
lseek(lfh, size, SEEK_CUR);
}
else
{
close(lfh);
return EL_FILE_ERROR;
}
/* if EOF, goto next day */
i = read(lfh, str, 15);
if (i < 15)
{
close(lfh);
time(&lact);
lt = ltime;
do
{
lt += 3600*24;
tms = localtime(<);
sprintf(str, "%02d%02d%02d.0",
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday);
status = el_search_message(str, &lfh, FALSE, FALSE);
} while (status != EL_SUCCESS &&
(INT)lt-(INT)lact < 3600*24);
if (status != EL_SUCCESS)
{
if (fh)
*fh = lfh;
else
close(lfh);
return EL_LAST_MSG;
}
/* adjust tag */
strcpy(tag, str);
/* go to beginning of current file */
lseek(lfh, 0, SEEK_SET);
}
else
lseek(lfh, -15, SEEK_CUR);
/* adjust tag */
sprintf(strchr(tag, '.')+1, "%d", (int) (TELL(lfh)));
}
if (fh)
*fh = lfh;
else
close(lfh);
return EL_SUCCESS;
}
/*------------------------------------------------------------------*/
INT el_submit(char attr_name[MAX_N_ATTR][NAME_LENGTH],
char attr_value[MAX_N_ATTR][NAME_LENGTH],
int n_attr, char *text, char *reply_to, char *encoding,
char afilename[MAX_ATTACHMENTS][256],
char *buffer[MAX_ATTACHMENTS],
INT buffer_size[MAX_ATTACHMENTS],
char *tag, INT tag_size)
/********************************************************************\
Routine: el_submit
Purpose: Submit an ELog entry
Input:
char attr_name[][] Name of attributes
char attr_value[][] Value of attributes
int n_attr Number of attributes
char *text Message text
char *reply_to In reply to this message
char *encoding Text encoding, either HTML or plain
char *afilename[] File name of attachments
char *buffer[] Attachment contents
INT *buffer_size[] Size of attachment in bytes
char *tag If given, edit existing message
INT *tag_size Maximum size of tag
Output:
char *tag Message tag in the form YYMMDD.offset
INT *tag_size Size of returned tag
Function value:
EL_SUCCESS Successful completion
\********************************************************************/
{
INT n, i, size, fh, status, index, offset, tail_size;
struct tm *tms;
char file_name[256], afile_name[MAX_ATTACHMENTS][256], dir[256], str[256],
start_str[80], end_str[80], last[80], date[80], thread[80], attachment_all[64*MAX_ATTACHMENTS];
time_t now;
char message[TEXT_SIZE+100], *p;
BOOL bedit;
bedit = (tag[0] != 0);
for (index = 0 ; index < MAX_ATTACHMENTS ; index++)
{
/* generate filename for attachment */
afile_name[index][0] = file_name[0] = 0;
if (equal_ustring(afilename[index], loc("")))
{
strcpy(afile_name[index], loc(""));
}
else if (afilename[index][0] && buffer_size[index] == 0)
{
/* resubmission of existing attachment */
strcpy(afile_name[index], afilename[index]);
}
else
{
if (afilename[index][0])
{
/* strip directory, add date and time to filename */
strcpy(file_name, afilename[index]);
p = file_name;
while (strchr(p, ':'))
p = strchr(p, ':')+1;
while (strchr(p, '\\'))
p = strchr(p, '\\')+1; /* NT */
while (strchr(p, '/'))
p = strchr(p, '/')+1; /* Unix */
/* assemble ELog filename */
if (p[0])
{
strcpy(dir, data_dir);
time(&now);
tms = localtime(&now);
strcpy(str, p);
sprintf(afile_name[index], "%02d%02d%02d_%02d%02d%02d_%s",
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday,
tms->tm_hour, tms->tm_min, tms->tm_sec, str);
sprintf(file_name, "%s%02d%02d%02d_%02d%02d%02d_%s", dir,
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday,
tms->tm_hour, tms->tm_min, tms->tm_sec, str);
/* save attachment */
fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
if (fh < 0)
{
printf("Cannot write attachment file \"%s\"", file_name);
}
else
{
write(fh, buffer[index], buffer_size[index]);
close(fh);
}
}
}
}
}
/* generate new file name YYMMDD.log in data directory */
strcpy(dir, data_dir);
if (bedit)
{
/* edit existing message */
strcpy(str, tag);
if (strchr(str, '.'))
{
offset = atoi(strchr(str, '.')+1);
*strchr(str, '.') = 0;
}
sprintf(file_name, "%s%s.log", dir, str);
fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
if (fh < 0)
return -1;
lseek(fh, offset, SEEK_SET);
read(fh, str, 16);
size = atoi(str+9);
read(fh, message, size);
el_decode(message, "Date: ", date);
el_decode(message, "Thread: ", thread);
el_decode(message, "Attachment: ", attachment_all);
/* buffer tail of logfile */
lseek(fh, 0, SEEK_END);
tail_size = TELL(fh) - (offset+size);
if (tail_size > 0)
{
buffer = malloc(tail_size);
if (buffer == NULL)
{
close(fh);
return -1;
}
lseek(fh, offset+size, SEEK_SET);
n = read(fh, buffer, tail_size);
}
lseek(fh, offset, SEEK_SET);
}
else
{
/* create new message */
time(&now);
tms = localtime(&now);
sprintf(file_name, "%s%02d%02d%02d.log", dir,
tms->tm_year % 100, tms->tm_mon+1, tms->tm_mday);
fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
if (fh < 0)
return -1;
strcpy(date, ctime(&now));
date[24] = 0;
if (reply_to[0])
sprintf(thread, "%16s %16s", reply_to, "0");
else
sprintf(thread, "%16s %16s", "0", "0");
lseek(fh, 0, SEEK_END);
}
/* compose message */
sprintf(message, "Date: %s\n", date);
sprintf(message+strlen(message), "Thread: %s\n", thread);
for (i=0 ; i"))))
{
/* delete old attachment */
strcpy(str, data_dir);
strcat(str, p);
remove(str);
}
if (afile_name[i][0] && !equal_ustring(afile_name[i], loc("")))
{
if (n == 0)
{
sprintf(message+strlen(message), "Attachment: %s", afile_name[i]);
n++;
}
else
sprintf(message+strlen(message), ",%s", afile_name[i]);
}
else if (p && !equal_ustring(afile_name[i], loc("")))
{
if (n == 0)
{
sprintf(message+strlen(message), "Attachment: %s", p);
n++;
}
else
sprintf(message+strlen(message), ",%s", p);
}
}
}
else
{
sprintf(message+strlen(message), "Attachment: %s", afile_name[0]);
for (i=1 ; itm_year % 100, tms->tm_mon+1, tms->tm_mday, (int) (TELL(fh)));
sprintf(start_str, "$Start$: %6d\n", size);
sprintf(end_str, "$End$: %6d\n\f", size);
write(fh, start_str, strlen(start_str));
write(fh, message, strlen(message));
write(fh, end_str, strlen(end_str));
if (bedit)
{
if (tail_size > 0)
{
n = write(fh, buffer, tail_size);
free(buffer);
}
/* truncate file here */
#ifdef _MSC_VER
chsize(fh, TELL(fh));
#else
ftruncate(fh, TELL(fh));
#endif
}
close(fh);
/* if reply, mark original message */
if (reply_to[0] && !bedit)
{
strcpy(last, reply_to);
do
{
status = el_search_message(last, &fh, FALSE, FALSE);
if (status == EL_SUCCESS)
{
/* position to next thread location */
lseek(fh, 72, SEEK_CUR);
memset(str, 0, sizeof(str));
read(fh, str, 16);
lseek(fh, -16, SEEK_CUR);
/* if no reply yet, set it */
if (atoi(str) == 0)
{
sprintf(str, "%16s", tag);
write(fh, str, 16);
close(fh);
break;
}
else
{
/* if reply set, find last one in chain */
strcpy(last, strtok(str, " "));
close(fh);
}
}
else
/* stop on error */
break;
} while (TRUE);
}
return EL_SUCCESS;
}
/*------------------------------------------------------------------*/
INT el_retrieve(char *tag, char *date, char attr_list[MAX_N_ATTR][NAME_LENGTH],
char attrib[MAX_N_ATTR][NAME_LENGTH], int n_attr,
char *text, int *textsize,
char *orig_tag, char *reply_tag,
char attachment[MAX_ATTACHMENTS][256],
char *encoding)
/********************************************************************\
Routine: el_retrieve
Purpose: Retrieve an ELog entry by its message tab
Input:
char *tag tag in the form YYMMDD.offset
int *size Size of text buffer
Output:
char *tag tag of retrieved message
char *date Date/time of message recording
char attr_list Names of attributes
char attrib Values of attributes
int n_attr Number of attributes
char *text Message text
char *orig_tag Original message if this one is a reply
char *reply_tag Reply for current message
char *attachment[] File attachments
char *encoding Encoding of message
int *size Actual message text size
Function value:
EL_SUCCESS Successful completion
EL_NO_MSG No message in log
EL_LAST_MSG Last message in log
EL_FILE_ERROR Internal error
\********************************************************************/
{
int i, size, fh, offset, search_status;
char str[256], *p;
char message[TEXT_SIZE+1000], thread[256], attachment_all[64*MAX_ATTACHMENTS];
if (tag[0])
{
search_status = el_search_message(tag, &fh, TRUE, FALSE);
if (search_status != EL_SUCCESS)
return search_status;
}
else
{
/* open most recent message */
strcpy(tag, "-1");
search_status = el_search_message(tag, &fh, TRUE, FALSE);
if (search_status != EL_SUCCESS)
return search_status;
}
/* extract message size */
offset = TELL(fh);
i = read(fh, str, 16);
if (i <= 0)
{
close(fh);
return EL_FILE_ERROR;
}
if (strncmp(str, "$Start$: ", 9) == 0)
size = atoi(str+9);
else
{
close(fh);
return EL_FILE_ERROR;
}
/* read message */
memset(message, 0, sizeof(message));
read(fh, message, size);
close(fh);
/* decode message */
el_decode(message, "Date: ", date);
el_decode(message, "Thread: ", thread);
for (i=0 ; i \r conversion (e.g. zipping/unzipping) */
if (p == NULL)
p = strstr(message, "========================================\r");
if (text != NULL)
{
if (p != NULL)
{
p += 41;
if ((int) strlen(p) >= *textsize)
{
strncpy(text, p, *textsize-1);
text[*textsize-1] = 0;
show_error("Message too long to display. Please increase TEXT_SIZE and recompile elogd.");
return EL_FILE_ERROR;
}
else
{
strcpy(text, p);
/* strip end tag */
if (strstr(text, "$End$"))
*strstr(text, "$End$") = 0;
*textsize = strlen(text);
}
}
else
{
text[0] = 0;
*textsize = 0;
}
}
if (search_status == EL_LAST_MSG)
return EL_LAST_MSG;
return EL_SUCCESS;
}
/*------------------------------------------------------------------*/
INT el_delete_message(char *tag)
/********************************************************************\
Routine: el_delete_message
Purpose: Delete an ELog entry including attachments
Input:
char *tag Message tage
Output:
Function value:
EL_SUCCESS Successful completion
\********************************************************************/
{
INT i, n, size, fh, offset, tail_size, status, n_attr;
char dir[256], str[256], file_name[256];
char *buffer, attrib[MAX_N_ATTR][NAME_LENGTH];
char date[80], text[TEXT_SIZE], orig_tag[80], reply_tag[80],
attachment[MAX_ATTACHMENTS][256], encoding[80];
n_attr = scan_attributes(logbook);
/* get attachments */
size = sizeof(text);
status = el_retrieve(tag, date, attr_list, attrib, n_attr,
text, &size, orig_tag, reply_tag,
attachment,
encoding);
if (status != SUCCESS)
return EL_FILE_ERROR;
for (i=0 ; i 0)
{
buffer = malloc(tail_size);
if (buffer == NULL)
{
close(fh);
return EL_FILE_ERROR;
}
lseek(fh, offset+size, SEEK_SET);
n = read(fh, buffer, tail_size);
}
lseek(fh, offset, SEEK_SET);
if (tail_size > 0)
{
n = write(fh, buffer, tail_size);
free(buffer);
}
/* truncate file here */
#ifdef OS_WINNT
chsize(fh, TELL(fh));
#else
ftruncate(fh, TELL(fh));
#endif
/* if file length gets zero, delete file */
tail_size = lseek(fh, 0, SEEK_END);
close(fh);
if (tail_size == 0)
remove(file_name);
return EL_SUCCESS;
}
/*------------------------------------------------------------------*/
INT el_delete_message_only(char *tag, char afilename[MAX_ATTACHMENTS][256])
/********************************************************************\
Routine: el_delete_message_only
Purpose: Delete an ELog entry, but keeping (and returning) attachments
Input:
char *tag Message tage
Output:
Function value:
EL_SUCCESS Successful completion
\********************************************************************/
{
INT i, n, size, fh, offset, tail_size, status, n_attr;
char dir[256], str[256], file_name[256];
char *buffer, attrib[MAX_N_ATTR][NAME_LENGTH];
char date[80], text[TEXT_SIZE], orig_tag[80], reply_tag[80],
attachment[MAX_ATTACHMENTS][256], encoding[80];
n_attr = scan_attributes(logbook);
/* get attachments */
size = sizeof(text);
status = el_retrieve(tag, date, attr_list, attrib, n_attr,
text, &size, orig_tag, reply_tag,
attachment,
encoding);
if (status != SUCCESS)
return EL_FILE_ERROR;
for (i=0 ; i 0)
{
buffer = malloc(tail_size);
if (buffer == NULL)
{
close(fh);
return EL_FILE_ERROR;
}
lseek(fh, offset+size, SEEK_SET);
n = read(fh, buffer, tail_size);
}
lseek(fh, offset, SEEK_SET);
if (tail_size > 0)
{
n = write(fh, buffer, tail_size);
free(buffer);
}
/* truncate file here */
#ifdef OS_WINNT
chsize(fh, TELL(fh));
#else
ftruncate(fh, TELL(fh));
#endif
/* if file length gets zero, delete file */
tail_size = lseek(fh, 0, SEEK_END);
close(fh);
if (tail_size == 0)
remove(file_name);
return EL_SUCCESS;
}
/*------------------------------------------------------------------*/
void logf(const char *format, ...)
{
char fname[2000];
va_list argptr;
char str[10000];
FILE* f;
time_t now;
char buf[256];
if (!getcfg("global", "logfile", fname))
return;
va_start(argptr, format);
vsprintf(str, (char *) format, argptr);
va_end(argptr);
f=fopen(fname,"a");
if (!f)
return;
now=time(0);
strftime(buf, sizeof(buf), "%d-%b-%Y %H:%M:%S", localtime(&now));
fprintf(f,"%s: %s",buf,str);
if (str[strlen(str)-1] != '\n')
fprintf(f,"\n");
fclose(f);
}
/*------------------------------------------------------------------*/
void rsputs(const char *str)
{
if (strlen_retbuf + strlen(str) > sizeof(return_buffer))
strcpy(return_buffer, "Error: return buffer too small
");
else
strcpy(return_buffer+strlen_retbuf, str);
strlen_retbuf += strlen(str);
}
/*------------------------------------------------------------------*/
void rsputs2(const char *str)
{
int i, j, k;
char *p, link[256];
if (strlen_retbuf + strlen(str) > sizeof(return_buffer))
strcpy(return_buffer, "Error: return buffer too small
");
else
{
j = strlen_retbuf;
for (i=0 ; i<(int)strlen(str) ; i++)
{
if (strncmp(str+i, "http://", 7) == 0)
{
p = (char *) (str+i+7);
i += 7;
for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++)
link[k] = *p++;
link[k] = 0;
i--;
sprintf(return_buffer+j, "http://%s", link, link);
j += strlen(return_buffer+j);
}
else if (strncmp(str+i, "https://", 8) == 0)
{
p = (char *) (str+i+8);
i += 8;
for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++)
link[k] = *p++;
link[k] = 0;
i--;
sprintf(return_buffer+j, "https://%s", link, link);
j += strlen(return_buffer+j);
}
else if (strncmp(str+i, "ftp://", 6) == 0)
{
p = (char *) (str+i+6);
i += 6;
for (k=0 ; *p && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++)
link[k] = *p++;
link[k] = 0;
i--;
sprintf(return_buffer+j, "ftp://%s", link, link);
j += strlen(return_buffer+j);
}
else if (strncmp(str+i, "mailto:", 7) == 0)
{
p = (char *) (str+i+7);
i += 7;
for (k=0 ; *p && *p != '>' && *p != ' ' && *p != ',' && *p != '\t' && *p != '\n' && *p != '\r'; k++,i++)
link[k] = *p++;
link[k] = 0;
i--;
sprintf(return_buffer+j, "%s", link, link);
j += strlen(return_buffer+j);
}
else
switch (str[i])
{
case '<': strcat(return_buffer, "<"); j+=4; break;
case '>': strcat(return_buffer, ">"); j+=4; break;
/* the translation for the search highliting */
case '\001' : strcat(return_buffer, "<"); j++; break;
case '\002' : strcat(return_buffer, ">"); j++; break;
case '\003' : strcat(return_buffer, "\""); j++; break;
case '\004' : strcat(return_buffer, " "); j++; break;
default: return_buffer[j++] = str[i];
}
}
return_buffer[j] = 0;
strlen_retbuf = j;
}
}
/*------------------------------------------------------------------*/
void rsprintf(const char *format, ...)
{
va_list argptr;
char str[10000];
va_start(argptr, format);
vsprintf(str, (char *) format, argptr);
va_end(argptr);
if (strlen_retbuf + strlen(str) > sizeof(return_buffer))
strcpy(return_buffer, "Error: return buffer too small
");
else
strcpy(return_buffer+strlen_retbuf, str);
strlen_retbuf += strlen(str);
}
/*------------------------------------------------------------------*/
/* Parameter handling functions similar to setenv/getenv */
void initparam()
{
memset(_param, 0, sizeof(_param));
memset(_value, 0, sizeof(_value));
_text[0] = 0;
}
int setparam(char *param, char *value)
{
int i;
char str[256];
if (equal_ustring(param, "text"))
{
if (strlen(value) >= TEXT_SIZE)
{
sprintf(str, "Error: Message text too big (%d bytes). Please increase TEXT_SIZE and recompile elogd\n",
strlen(value));
show_error(str);
return 0;
}
strncpy(_text, value, TEXT_SIZE);
_text[TEXT_SIZE-1] = 0;
return 1;
}
for (i=0 ; i= VALUE_SIZE)
{
show_error("Error: Parameter value too big. Please increase VALUE_SIZE and recompile elogd\n");
return 0;
}
strncpy(_value[i], value, VALUE_SIZE);
_value[i][VALUE_SIZE-1] = 0;
}
else
{
printf("Error: parameter array too small\n");
}
return 1;
}
char *getparam(char *param)
{
int i;
if (equal_ustring(param, "text"))
return _text;
for (i=0 ; iredir