#define VERSION ( "1.003 " __DATE__ " " __TIME__ )
#include <winsock2.h>
#include <string.h>
#include <stdio.h>
#include <direct.h>
#include <time.h>
#include "conf.h"
#include "ap.h"
#ifdef strftime
#undef strftime
#endif
#define AP_WIN32ERROR 1
HINSTANCE hInstance = NULL;
static char *szLogFilename = NULL;
static FILE *fpLog = NULL;
void LogMessage(char *fmt, ...)
{
char buf[4000];
va_list ap;
struct tm *tms;
time_t nowtime;
char *bp = buf;
int rv;
int free = sizeof(buf);
if (!fpLog) {
return;
}
nowtime = time(NULL);
tms = localtime(&nowtime);
rv = strftime(bp, free, "%c", tms);
bp += rv;
free -= rv;
if (free) {
*bp++ = ' ';
free--;
}
va_start(ap, fmt);
rv = ap_vsnprintf(bp, free, fmt, ap);
va_end(ap);
free -= rv;
fprintf(fpLog, "%s\n", buf);
}
int MessageBox_error(HWND hWnd, int opt, char *title,
int mb_opt, char *fmt, ...)
{
char buf[1000];
va_list ap;
int free = sizeof(buf);
int rv;
char *p;
va_start(ap, fmt);
rv = ap_vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
free -= rv;
if (opt & AP_WIN32ERROR && free > 3) {
p = buf + strlen(buf);
*p++ = '\r';
*p++ = '\r';
*p++ = '(';
free -= 3;
rv = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
0,
p,
free,
NULL);
if (rv == 0) {
p -= 3;
*p = '\0';
free += 3;
} else {
free -= rv;
p += rv;
while (*(p-1) == '\r' || *(p-1) == '\n')
p--, free++;
*p = '\0';
if (free >= 1) {
*p++ = ')';
*p++ = '\0';
}
}
}
for (p = buf; *p; p++) {
if (*p == '\n' || *p == '\r') {
*p = ' ';
}
}
LogMessage("MSG %s", buf);
return MessageBox(hWnd, buf, title, mb_opt);
}
int OpenLog(HWND hwnd, char *dir, char *fn)
{
szLogFilename = malloc(strlen(dir) + 1 + strlen(fn) + 1);
sprintf(szLogFilename, "%s\\%s", dir, fn);
if ((fpLog = fopen(szLogFilename, "a+")) == NULL) {
MessageBox_error(hwnd,
AP_WIN32ERROR,
"Installation Problem",
MB_OK | MB_ICONSTOP,
"Cannot open log file %s", szLogFilename);
return -1;
}
return 0;
}
void CloseLog(void)
{
if (fpLog) {
fclose(fpLog);
}
}
typedef struct {
char *tmpl;
char *value;
} REPLACEITEM;
typedef REPLACEITEM *REPLACETABLE;
REPLACEITEM replaceHttpd[] = {
{ "@@ServerRoot@@", NULL },
{ NULL, NULL }
};
int appendText(char **ppBuf, int *pnPos, int *pnSize, char *pSrc, int nToCopy)
{
char *pBuf = *ppBuf;
int nPos = *pnPos;
int nSize = *pnSize;
while (nPos + nToCopy >= nSize) {
char *pBufNew;
pBufNew = realloc(pBuf, nSize * 2);
if (!pBufNew)
return -1;
nSize *= 2;
*pnSize = nSize;
*ppBuf = pBuf = pBufNew;
}
strncpy(pBuf+nPos, pSrc, nToCopy);
nPos += nToCopy;
*pnPos = nPos;
pBuf[nPos] = '\0';
return 0;
}
char *expandLine(char *in, REPLACETABLE replaceTable)
{
REPLACEITEM *item;
char *pos;
char *outbuf;
int outbuf_size;
int outbuf_position;
char *start;
outbuf_size = strlen(in) * 2;
outbuf_position = 0;
outbuf = malloc(outbuf_size);
if (!outbuf)
return NULL;
start = in;
pos = in;
while (1) {
if (*pos && !(*pos == '@' && *(pos+1) == '@')) {
pos++;
continue;
}
if (!*pos) {
if (appendText(&outbuf, &outbuf_position, &outbuf_size,
start, pos-start) < 0) {
return NULL;
}
break;
}
for (item = replaceTable; item->tmpl; ++item) {
if (!strncmp(pos, item->tmpl, strlen(item->tmpl)))
break;
}
if (item->tmpl) {
if (appendText(&outbuf, &outbuf_position, &outbuf_size,
start, pos-start) < 0) {
return NULL;
}
if (appendText(&outbuf, &outbuf_position, &outbuf_size,
item->value, strlen(item->value)) < 0) {
return NULL;
}
pos += strlen(item->tmpl);
start = pos;
}
else {
pos++;
}
}
return outbuf;
}
typedef enum {
OPT_NONE = 0,
OPT_OVERWRITE = 1,
OPT_EXPAND = 2,
OPT_DELETESOURCE = 4,
OPT_SILENT = 8,
} options_t;
#define MAX_INPUT_LINE 2000
int WINAPI ExpandConfFile(HWND hwnd, LPSTR szInst, LPSTR szinFile, LPSTR szoutFile, REPLACETABLE replaceTable, options_t options)
{
char inFile[_MAX_PATH];
char outFile[_MAX_PATH];
char inbuf[MAX_INPUT_LINE];
FILE *infp;
FILE *outfp;
ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, szinFile);
ap_snprintf(outFile, sizeof(outFile), "%s\\%s", szInst, szoutFile);
if (!(infp = fopen(inFile, "r"))) {
MessageBox_error(hwnd,
AP_WIN32ERROR,
"Installation Problem",
MB_OK | MB_ICONSTOP,
"Cannot read file %s", inFile);
return -1;
}
if (! (options & OPT_OVERWRITE)) {
if ((outfp = fopen(outFile, "r"))) {
if (! (options & OPT_SILENT)) {
MessageBox_error(hwnd,
0,
"File not overwritten",
MB_OK | MB_ICONWARNING,
"Preserving existing file %s.\r\r"
"The new version of this file has been left in %s",
outFile, inFile);
}
fclose(outfp);
fclose(infp);
return 0;
}
}
if (!(outfp = fopen(outFile, "w"))) {
MessageBox_error(hwnd,
AP_WIN32ERROR,
"Installation Problem",
MB_OK | MB_ICONSTOP,
"Cannot write to file %s", outFile);
fclose(infp);
return -1;
}
while (fgets(inbuf, MAX_INPUT_LINE, infp)) {
char *pos;
char *outbuf;
if (options & OPT_EXPAND) {
for (pos = inbuf; *pos; ++pos)
if (*pos == '@' && *(pos+1) == '@')
break;
}
if (options & OPT_EXPAND && *pos) {
outbuf = expandLine(inbuf, replaceTable);
if (outbuf == NULL) {
fclose(infp);
fclose(outfp);
MessageBox_error(hwnd,
0,
"Installation Problem",
MB_OK|MB_ICONSTOP,
"An error occurred during installation");
return -1;
}
}
else {
outbuf = NULL;
}
fwrite(outbuf ? outbuf : inbuf, 1,
strlen(outbuf ? outbuf : inbuf), outfp);
if (outbuf)
free(outbuf);
}
fclose(infp);
fclose(outfp);
LogMessage("COPY: expanded %s to %s", inFile, outFile);
if (options & OPT_DELETESOURCE) {
unlink(inFile);
LogMessage("COPY: deleted file %s", inFile);
}
return 0;
}
int FillInReplaceTable(HWND hwnd, REPLACETABLE table, char *szInst)
{
REPLACEITEM *item;
for (item = table; item->tmpl; ++item) {
if (!strcmp(item->tmpl, "@@ServerRoot@@")) {
char *p;
#if NEED_SHORT_PATHS
int len;
len = GetShortPathName(szInst, NULL, 0);
if (len > 0) {
item->value = (char*)malloc(len+1);
GetShortPathName(szInst, item->value, len);
}
#else
if ((item->value = strdup(szInst)) == NULL)
return -1;
#endif
for (p = item->value; *p; p++)
if (*p == '\\') *p = '/';
LogMessage("FillInReplaceTable tmpl=%s value=%s", item->tmpl, item->value);
continue;
}
#if NEED_FQDN
if (!strcmp(item->tmpl, "FQDN")) {
item->value = GetHostName(hwnd);
continue;
}
#endif
}
return 0;
}
typedef enum {
CMD_COPY = 0,
CMD_RMDIR,
CMD_RM,
CMD_END
} cmd_t;
typedef struct {
cmd_t command;
char *in;
char *out;
options_t options;
} ACTIONITEM;
typedef ACTIONITEM *ACTIONTABLE;
ACTIONITEM actionTable[] = {
{ CMD_COPY, ".tmp\\mime.types", "conf\\mime.types.default",
OPT_OVERWRITE|OPT_DELETESOURCE },
{ CMD_COPY, ".tmp\\magic", "conf\\magic.default",
OPT_OVERWRITE|OPT_DELETESOURCE },
{ CMD_COPY, ".tmp\\httpd.conf-dist-win", "conf\\httpd.conf.default",
OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE },
{ CMD_COPY, ".tmp\\srm.conf-dist-win", "conf\\srm.conf.default",
OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE },
{ CMD_COPY, ".tmp\\access.conf-dist-win", "conf\\access.conf.default",
OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE },
{ CMD_COPY, "conf\\httpd.conf.default", "conf\\httpd.conf", OPT_NONE },
{ CMD_COPY, "conf\\srm.conf.default", "conf\\srm.conf", OPT_NONE },
{ CMD_COPY, "conf\\access.conf.default", "conf\\access.conf", OPT_NONE },
{ CMD_COPY, "conf\\magic.default", "conf\\magic", OPT_NONE },
{ CMD_COPY, "conf\\mime.types.default", "conf\\mime.types", OPT_NONE },
{ CMD_COPY, ".tmp\\highperformance.conf-dist", "conf\\highperformance.conf-dist",
OPT_EXPAND|OPT_OVERWRITE|OPT_DELETESOURCE },
{ CMD_RMDIR, ".tmp", NULL },
{ CMD_END, NULL, NULL, OPT_NONE }
};
CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst, LPSTR szRes)
{
ACTIONITEM *pactionItem;
int end = 0;
OpenLog(hwnd, szInst, "install.log");
LogMessage("STARTED %s", VERSION);
LogMessage("src=%s support=%s inst=%s",
szSrcDir, szSupport, szInst);
FillInReplaceTable(hwnd, replaceHttpd, szInst);
pactionItem = actionTable;
while (!end) {
LogMessage("command=%d 1in=%s out=%s options=%d",
pactionItem->command,
pactionItem->in ? pactionItem->in : "NULL",
pactionItem->out ? pactionItem->out : "NULL",
pactionItem->options);
switch(pactionItem->command) {
case CMD_END:
end = 1;
break;
case CMD_COPY:
if (ExpandConfFile(hwnd, szInst,
pactionItem->in,
pactionItem->out,
replaceHttpd,
pactionItem->options) < 0) {
return 0;
}
break;
case CMD_RM: {
char inFile[MAX_INPUT_LINE];
ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in);
if (unlink(inFile) < 0 && !(pactionItem->options & OPT_SILENT)) {
MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration",
MB_ICONHAND,
"Could not remove file %s",
inFile);
return 0;
}
LogMessage("RM: deleted file %s", inFile);
break;
}
case CMD_RMDIR: {
char inFile[MAX_INPUT_LINE];
ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in);
if (rmdir(inFile) < 0) {
MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration",
MB_ICONHAND,
"Could not delete temporary directory %s",
inFile);
return 0;
}
LogMessage("RMDIR: deleted directory %s", inFile);
break;
}
default:
MessageBox_error(hwnd, 0, "Error during configuration",
MB_ICONHAND,
"An error has occurred during configuration\r"
"(Error: unknown command %d)", (int)pactionItem->command);
end = 1;
break;
}
pactionItem++;
}
LogMessage("FINISHED OK");
CloseLog();
return 1;
}
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
hInstance = hInstDLL;
return TRUE;
}