📄 main.c
字号:
/*
* main.c -- Main program for the GoAhead WebServer
*
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*
* $Id: main.c,v 1.3 2002/07/29 15:28:33 bporter Exp $
*/
/******************************** Description *********************************/
/*
* Main program for the GoAhead WebServer. This is a demonstration
* program to initialize and configure the web server.
*/
/********************************* Includes ***********************************/
#include <direct.h>
#include <windows.h>
#include <winuser.h>
#include <process.h>
#include "../wsIntrn.h"
#ifdef WEBS_SSL_SUPPORT
#include "../websSSL.h"
#endif
#ifdef USER_MANAGEMENT_SUPPORT
#include "../um.h"
void formDefineUserMgmt(void);
#endif
/********************************** Defines ***********************************/
#define IDM_ABOUTBOX 0xF200
#define IDS_ABOUTBOX "AboutBox"
#define IDC_VERSION 101
#define IDC_BUILDDATE 102
#define IDC_DISMISS 103
#define SOCK_DFT_SVC_TIME 20
/*********************************** Locals ***********************************/
/*
* Change configuration here
*/
static HWND hwnd; /* Main Window handle */
static HWND hwndAbout; /* About Window handle */
static char_t *title = T("GoAhead WebServer");/* Window title */
static char_t *name = T("gowebs"); /* Window name */
static char_t *rootWeb = T("web"); /* Root web directory */
static char_t *password = T(""); /* Security password */
static int port = 80; /* Server port */
static int retries = 5; /* Server port retries */
static int finished; /* Finished flag */
static int sockServiceTime; /* in milliseconds */
/****************************** Forward Declarations **************************/
static int initWebs();
static long CALLBACK websWindProc(HWND hwnd, unsigned int msg,
unsigned int wp, long lp);
static long CALLBACK websAboutProc(HWND hwnd, unsigned int msg,
unsigned int wp, long lp);
static int registerAboutBox(HINSTANCE hInstance);
static int createAboutBox(HINSTANCE hInstance, HWND hwnd);
static int aspTest(int eid, webs_t wp, int argc, char_t **argv);
static WPARAM checkWindowsMsgLoop();
static void formTest(webs_t wp, char_t *path, char_t *query);
static int windowsInit(HINSTANCE hinstance);
static int windowsClose(HINSTANCE hinstance);
static int websHomePageHandler(webs_t wp, char_t *urlPrefix,
char_t *webDir, int arg, char_t *url, char_t *path,
char_t *query);
extern void defaultErrorHandler(int etype, char_t *msg);
extern void defaultTraceHandler(int level, char_t *buf);
static void printMemStats(int handle, char_t *fmt, ...);
static void memLeaks();
static LPWORD lpwAlign(LPWORD);
static int nCopyAnsiToWideChar(LPWORD, LPSTR);
static void centerWindowOnDisplay(HWND hwndCenter);
static unsigned char *tableToBlock(char **table);
/*********************************** Code *************************************/
/*
* WinMain -- entry point from Windows
*/
int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,
char *args, int cmd_show)
{
WPARAM rc;
/*
* Initialize the memory allocator. Allow use of malloc and start
* with a 60K heap. For each page request approx 8KB is allocated.
* 60KB allows for several concurrent page requests. If more space
* is required, malloc will be used for the overflow.
*/
bopen(NULL, (60 * 1024), B_USE_MALLOC);
/*
* Store the instance handle (used in socket.c)
*/
if (windowsInit(hinstance) < 0) {
return FALSE;
}
/*
* Initialize the web server
*/
if (initWebs() < 0) {
return FALSE;
}
#ifdef WEBS_SSL_SUPPORT
websSSLOpen();
#endif
/*
* Basic event loop. SocketReady returns true when a socket is ready for
* service. SocketSelect will block until an event occurs. SocketProcess
* will actually do the servicing.
*/
while (!finished) {
if (socketReady(-1) || socketSelect(-1, sockServiceTime)) {
socketProcess(-1);
}
emfSchedProcess();
websCgiCleanup();
if ((rc = checkWindowsMsgLoop()) != 0) {
break;
}
}
#ifdef WEBS_SSL_SUPPORT
websSSLClose();
#endif
/*
* Close the User Management database
*/
#ifdef USER_MANAGEMENT_SUPPORT
umClose();
#endif
/*
* Close the socket module, report memory leaks and close the memory allocator
*/
websCloseServer();
socketClose();
/*
* Free up Windows resources
*/
windowsClose(hinstance);
#ifdef B_STATS
memLeaks();
#endif
bclose();
return rc;
}
/******************************************************************************/
/*
* Initialize the web server.
*/
static int initWebs()
{
struct hostent *hp;
struct in_addr intaddr;
char *cp;
char host[64], dir[128];
char_t dir_t[128];
char_t wbuf[256];
/*
* Initialize the socket subsystem
*/
socketOpen();
/*
* Initialize the User Management database
*/
#ifdef USER_MANAGEMENT_SUPPORT
umOpen();
umRestore(T("umconfig.txt"));
#endif
/*
* Define the local Ip address, host name, default home page and the
* root web directory.
*/
if (gethostname(host, sizeof(host)) < 0) {
error(E_L, E_LOG, T("Can't get hostname"));
return -1;
}
if ((hp = gethostbyname(host)) == NULL) {
error(E_L, E_LOG, T("Can't get host address"));
return -1;
}
memcpy((void *) &intaddr, (void *) hp->h_addr_list[0],
(size_t) hp->h_length);
/*
* Set ../web as the root web. Modify this to suit your needs
*/
getcwd(dir, sizeof(dir));
for (cp = dir; *cp; cp++) {
if (*cp == '\\')
*cp = '/';
}
if (cp = strrchr(dir, '/')) {
*cp = '\0';
}
ascToUni(dir_t, dir, sizeof(dir_t));
gsprintf(wbuf, T("%s/%s"), dir_t, rootWeb);
websSetDefaultDir(wbuf);
cp = inet_ntoa(intaddr);
ascToUni(wbuf, cp, min(strlen(cp) + 1, sizeof(wbuf)));
websSetIpaddr(wbuf);
ascToUni(wbuf, hp->h_name, min(strlen(hp->h_name) + 1, sizeof(wbuf)));
websSetHost(wbuf);
/*
* Configure the web server options before opening the web server
*/
websSetDefaultPage(T("default.asp"));
websSetPassword(password);
/*
* Open the web server on the given port. If that port is taken, try
* the next sequential port for up to "retries" attempts.
*/
websOpenServer(port, retries);
/*
* First create the URL handlers. Note: handlers are called in sorted order
* with the longest path handler examined first. Here we define the security
* handler, forms handler and the default web page handler.
*/
websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler,
WEBS_HANDLER_FIRST);
websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
websUrlHandlerDefine(T("/cgi-bin"), NULL, 0, websCgiHandler, 0);
websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler,
WEBS_HANDLER_LAST);
/*
* Now define two test procedures. Replace these with your application
* relevant ASP script procedures and form functions.
*/
websAspDefine(T("aspTest"), aspTest);
websFormDefine(T("formTest"), formTest);
/*
* Create the Form handlers for the User Management pages
*/
#ifdef USER_MANAGEMENT_SUPPORT
formDefineUserMgmt();
#endif
/*
* Create a handler for the default home page
*/
websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0);
/*
* Set the socket service timeout to the default
*/
sockServiceTime = SOCK_DFT_SVC_TIME;
return 0;
}
/******************************************************************************/
/*
* Create a taskbar entry. Register the window class and create a window
*/
static int windowsInit(HINSTANCE hinstance)
{
WNDCLASS wc; /* Window class */
HMENU hSysMenu;
emfInstSet((int) hinstance);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = NULL;
wc.lpfnWndProc = (WNDPROC) websWindProc;
wc.lpszMenuName = wc.lpszClassName = name;
if (! RegisterClass(&wc)) {
return -1;
}
/*
* Create a window just so we can have a taskbar to close this web server
*/
hwnd = CreateWindow(name, title, WS_MINIMIZE | WS_POPUPWINDOW,
CW_USEDEFAULT, 0, 0, 0, NULL, NULL, hinstance, NULL);
if (hwnd == NULL) {
return -1;
}
/*
* Add the about box menu item to the system menu
* a_assert: IDM_ABOUTBOX must be in the system command range.
*/
hSysMenu = GetSystemMenu(hwnd, FALSE);
if (hSysMenu != NULL)
{
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, IDM_ABOUTBOX, T("About WebServer"));
}
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
hwndAbout = NULL;
return 0;
}
/******************************************************************************/
/*
* Close windows resources
*/
static int windowsClose(HINSTANCE hInstance)
{
int nReturn;
nReturn = UnregisterClass(name, hInstance);
if (hwndAbout) {
DestroyWindow(hwndAbout);
}
return nReturn;
}
/******************************************************************************/
/*
* Main menu window message handler.
*/
static long CALLBACK websWindProc(HWND hwnd, unsigned int msg,
unsigned int wp, long lp)
{
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
finished++;
return 0;
case WM_SYSCOMMAND:
if (wp == IDM_ABOUTBOX) {
if (!hwndAbout) {
createAboutBox((HINSTANCE) emfInstGet(), hwnd);
}
if (hwndAbout) {
ShowWindow(hwndAbout, SW_SHOWNORMAL);
}
}
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
/******************************************************************************/
/*
* Check for Windows Messages
*/
WPARAM checkWindowsMsgLoop()
{
MSG msg; /* Message block */
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (!GetMessage(&msg, NULL, 0, 0) || msg.message == WM_QUIT) {
return msg.wParam;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
/******************************************************************************/
/*
* Windows message handler for the About Box
*/
static long CALLBACK websAboutProc(HWND hwndDlg, unsigned int msg,
unsigned int wp, long lp)
{
long lResult;
HWND hwnd;
lResult = DefWindowProc(hwndDlg, msg, wp, lp);
switch (msg) {
case WM_CREATE:
hwndAbout = hwndDlg;
break;
case WM_DESTROY:
hwndAbout = NULL;
break;
case WM_COMMAND:
if (wp == IDOK) {
EndDialog(hwndDlg, 0);
PostMessage(hwndDlg, WM_CLOSE, 0, 0);
}
break;
case WM_INITDIALOG:
/*
* Set the version and build date values
*/
hwnd = GetDlgItem(hwndDlg, IDC_VERSION);
if (hwnd) {
SetWindowText(hwnd, WEBS_VERSION);
}
hwnd = GetDlgItem(hwndDlg, IDC_BUILDDATE);
if (hwnd) {
SetWindowText(hwnd, __DATE__);
}
SetWindowText(hwndDlg, T("GoAhead WebServer"));
centerWindowOnDisplay(hwndDlg);
hwndAbout = hwndDlg;
lResult = FALSE;
break;
}
return lResult;
}
/******************************************************************************/
/*
* Registers the About Box class
*/
static int registerAboutBox(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)websAboutProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = IDS_ABOUTBOX;
if (!RegisterClass(&wc)) {
return 0;
}
return 1;
}
/******************************************************************************/
/*
* Helper routine. Take an input pointer, return closest
* pointer that is aligned on a DWORD (4 byte) boundary.
*/
static LPWORD lpwAlign(LPWORD lpIn)
{
ULONG ul;
ul = (ULONG) lpIn;
ul +=3;
ul >>=2;
ul <<=2;
return (LPWORD) ul;
}
/******************************************************************************/
/*
* Helper routine. Takes second parameter as Ansi string, copies
* it to first parameter as wide character (16-bits / char) string,
* and returns integer number of wide characters (words) in string
* (including the trailing wide char NULL).
*/
static int nCopyAnsiToWideChar(LPWORD lpWCStr, LPSTR lpAnsiIn)
{
int cchAnsi = lstrlen(lpAnsiIn);
return MultiByteToWideChar(GetACP(),
MB_PRECOMPOSED, lpAnsiIn, cchAnsi, lpWCStr, cchAnsi) + 1;
}
/******************************************************************************/
/*
* Creates an About Box Window
*/
static int createAboutBox(HINSTANCE hInstance, HWND hwnd)
{
WORD *p, *pdlgtemplate;
int nchar;
DWORD lStyle;
HWND hwndReturn;
/*
* Allocate some memory to play with
*/
pdlgtemplate = p = (PWORD) LocalAlloc(LPTR, 1000);
/*
* Start to fill in the dlgtemplate information. addressing by WORDs
*/
lStyle = WS_DLGFRAME | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | DS_SETFONT;
*p++ = LOWORD(lStyle);
*p++ = HIWORD(lStyle);
*p++ = 0; /* LOWORD (lExtendedStyle) */
*p++ = 0; /* HIWORD (lExtendedStyle) */
*p++ = 7; /* Number Of Items */
*p++ = 210; /* x */
*p++ = 10; /* y */
*p++ = 200; /* cx */
*p++ = 100; /* cy */
*p++ = 0; /* Menu */
*p++ = 0; /* Class */
/*
* Copy the title of the dialog
*/
nchar = nCopyAnsiToWideChar(p, "GoAhead WebServer");
p += nchar;
/*
* Font information because of DS_SETFONT
*/
*p++ = 11; /* point size */
nchar = nCopyAnsiToWideChar(p, T("Arial Bold"));
p += nchar;
/*
* Make sure the first item starts on a DWORD boundary
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -