|
|
#include <windows.h>
#include "common.h"
#include "App.h"
#include "resource.h"
#include "Request.h"
#include "HttpRequest.h"
#include "Socket.h"
#include "ConfigInfo.h"
#include "Install.h"
const char* szClassName ="jWebServerClass";// The main window's class
LRESULT WINAPI App::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch(msg)
{
case WM_CREATE: web.OnWinCreate(); return 0;
case WM_ACTIVATE: web.OnWinActivate(wparam); return 0;
case WM_CLOSE: web.OnWinClose(); return 0;
case WM_PAINT: web.OnPaint(); return 0;
case WM_USER:
switch(WSAGETSELECTEVENT(lparam))
{
case FD_CLOSE: web.OnWinSocketClose(wparam); break;
case FD_ACCEPT: web.OnWinSocketAccept(wparam); break;
}
break;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}
LRESULT WINAPI App::MainDlgProc(HWND hd, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch(msg)
{
case WM_INITDIALOG: web.OnInitDialog(hd); return FALSE;
case WM_CLOSE: web.OnCloseDialog(); return FALSE;
case WM_COMMAND:
{
switch( LOWORD(wparam) )
{
case IDOK: web.OnClickOk(); return TRUE;
case IDCANCEL: web.OnClickCancel(); return TRUE;
case IDC_CONFIG: web.OnClickConfig(); return TRUE;
case IDC_ABOUT: web.OnClickAbout(); return TRUE;
case IDC_START: web.OnClickStart(); return TRUE;
case IDC_STOP: web.OnClickStop(); return TRUE;
}
}
break;
case WM_USER:
{
switch(lparam)
{
case WM_LBUTTONUP: web.ShowDialogWindow(); break;
}
}
break;
}
return FALSE;
}
void App::Create(HINSTANCE hInst)
{
RegisterWindowClass(hInst);
CreateMainWindow();
CreateMainDialog();
}
void App::OnWinCreate()
{
*mText=0;
if (gConfigInfo.m_error)
{
Install inst(mInstance, mDlg);
inst.Run();
return;
}
if (!Socket::InitEnvironment())
SetWinTitle("WinSock(TCP/IP) is not installed on this machine.");
}
void App::SetNonBlockingMode(Socket& sock)
{
sock.SetNonBlockingMode(mHwnd);
}
void App::OnWinSocketAccept(WPARAM wparam)
{
Socket s(wparam);
if (mWebKnown.Compare(s) )
mWebKnown.Accept();
else if( mWebServer.Compare(s) )
mWebServer.Accept();
}
void App::OnWinSocketClose(WPARAM wparam)
{
Socket s(wparam);
s.Close();
}
void App::OnWinActivate(WPARAM wparam)
{
if(LOWORD(wparam)==WA_INACTIVE )
ShowWindow(mHwnd,SW_HIDE);
}
void App::OnWinClose()
{
PostQuitMessage(1);
}
void App::OnInitDialog(HWND hwnd)
{
mDlg = hwnd;
ServerEvent(0, 2);
for(int i=0;i<HTTP_CONNECTIONS;i++)
{
mWebServer.m_connections[i]=new Request();
mWebKnown.m_connections[i]=new Request();
}
mWebServer.StartServer(gConfigInfo.m_port);
}
void App::OnCloseDialog()
{
Socket::TermEnvironment();
}
void App::OnClickOk()
{
HideDialogWindow();
}
void App::OnClickCancel()
{
if( MessageBox(NULL,"Are you sure you want to stop jWebServer and quit?",szAppName,MB_YESNO) == IDYES )
PostQuitMessage(1);
}
void App::OnClickConfig()
{
mWebKnown.m_autoFindPort=true;
mWebKnown.StartServer(30001);
if (mWebKnown.IsRunning())
{
char str[1024];
wsprintf(str,"http://127.0.0.1:%d/admin/index.html", GetPort());
LaunchBrowser(str);
}
}
void App::OnClickAbout()
{
mWebKnown.m_autoFindPort=true;
mWebKnown.StartServer(30001);
if (mWebKnown.IsRunning())
{
char str[1024];
wsprintf(str,"http://127.0.0.1:%d/admin/about.html", GetPort());
LaunchBrowser(str);
}
}
void App::OnClickStart()
{
mWebServer.StartServer(gConfigInfo.m_port);
}
void App::OnClickStop()
{
mWebServer.StopServer();
}
int App::GetPort()
{
return mWebKnown.GetPort();
}
void App::TaskNotify(int action,int icon,char *tip)
{
NOTIFYICONDATA nid;
memset(&nid,0,sizeof(NOTIFYICONDATA));
nid.cbSize=sizeof(NOTIFYICONDATA);
nid.hWnd=mDlg;
nid.uID=0;
nid.uFlags=NIF_ICON|NIF_MESSAGE |NIF_TIP;
nid.uCallbackMessage=WM_USER;
nid.hIcon=LoadIcon(mInstance,MAKEINTRESOURCE(icon));
strncpy(nid.szTip,tip,sizeof(nid.szTip));
Shell_NotifyIcon(action,&nid);
}
void App::LaunchBrowser(char *url)
{
char str[1024],str2[1024],*ptr;
long dw;
dw=1024;
if( RegQueryValue( HKEY_CLASSES_ROOT,".html",str,&dw)!=ERROR_SUCCESS )
{
if( RegQueryValue( HKEY_CLASSES_ROOT,".htm",str,&dw)!=ERROR_SUCCESS )
{
MessageBox(NULL,"Error: Can't locate a browser.","Error",MB_OK);
return;
}
}
strcat(str,"\\shell\\open\\command");
dw=1024;
if( RegQueryValue( HKEY_CLASSES_ROOT,str,str2,&dw)!=ERROR_SUCCESS )
{
MessageBox(NULL,"Error: Can't locate a browser.","Error",MB_OK);
return;
}
ptr=strstr(str2,"%1");
if(ptr!=NULL)
{
strncpy(str,ptr+2,sizeof(str));
strcpy(ptr,url);
strcat(str2,str);
}
else
{
strcat(str2," ");
strcat(str2,url);
}
WinExec(str2,SW_MAXIMIZE);
}
void App::SetWinTitle(const char *s)
{
SIZE sz;
HDC hdc;
int x,y,maxx,maxy;
strncpy(mText,s,sizeof(mText));
hdc = GetDC(mHwnd);
GetTextExtentPoint32(
hdc,
mText,
strlen(mText),
&sz);
maxx = sz.cx+20;
if(maxx<300)
maxx=300;
maxy = sz.cy*3;
x = (GetSystemMetrics(SM_CXSCREEN)/2) - (maxx/2);
y = (GetSystemMetrics(SM_CYSCREEN)/2) - (maxy/2);
SetWindowPos(mHwnd,HWND_TOP,x,y,maxx,maxy,0);
mYLoc=sz.cy;
mXLoc=(maxx/2)-(sz.cx/2);
ReleaseDC(mHwnd,hdc);
InvalidateRect(mHwnd,NULL,TRUE);
ShowWindow(mHwnd,SW_SHOW);
SetFocus(mHwnd);
}
void App::OnPaint()
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(mHwnd, &ps);
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, mXLoc, mYLoc, mText, strlen(mText));
EndPaint(mHwnd, &ps);
}
void App::RegisterWindowClass(HINSTANCE hInst)
{
mInstance=hInst;
WNDCLASS wndclass;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC) App::WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInst;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szClassName;
RegisterClass(&wndclass);
}
void App::CreateMainWindow()
{
mHwnd=CreateWindow(
szClassName,
szAppName,
WS_POPUP|WS_DLGFRAME,
10,
10,
100,
100,
NULL,
NULL,
mInstance,
NULL);
ShowWindow(mHwnd,SW_HIDE);
}
void App::GetResource(char* name, DWORD& contentLength, BYTE*& byt, char* location)
{
HRSRC hrc = FindResource(mInstance, name, "WEBDAT");
HGLOBAL hglb = LoadResource(mInstance, hrc);
byt = (BYTE*)LockResource(hglb);
contentLength = SizeofResource(mInstance, hrc);
}
void App::CreateMainDialog()
{
char dlgTitle[80];
mDlg = ::CreateDialog(mInstance, "MAIN", NULL, (DLGPROC) App::MainDlgProc);
strncpy(dlgTitle, szAppName, 80);
strcat(dlgTitle," Control Panel");
::SetWindowText(mDlg, dlgTitle);
ShowDialogWindow();
}
void App::HideDialogWindow()
{
::ShowWindow(mDlg, SW_HIDE);
}
void App::ShowDialogWindow()
{
::ShowWindow(mDlg, SW_SHOW);
::SetForegroundWindow(mDlg);
}
void App::CleanUp(void)
{
int i;
TaskNotify(NIM_DELETE,IDI_DOWN,"");
mWebKnown.StopServer();
mWebServer.StopServer();
DestroyWindow(mDlg);
for(i=0;i<HTTP_CONNECTIONS;i++)
{
delete mWebServer.m_connections[i];
delete mWebKnown.m_connections[i];
}
}
void App::AddSlash(char *f)
{
if(*f == 0)
return;
if( f[strlen(f)-1]!='\\')
strcat(f,"\\");
}
// 0=up,1=down,2=add
void App::ServerEvent(HttpServer *source,int type)
{
char *t;
if(source==&mWebKnown)
return;
switch(type)
{
case 0:
t="jWebServer Running";
TaskNotify(NIM_MODIFY,IDI_UP,t);
SetDlgItemText(mDlg,IDC_STATUS,t);
EnableWindow(GetDlgItem(mDlg,IDC_START),FALSE);
EnableWindow(GetDlgItem(mDlg,IDC_STOP),TRUE);
break;
case 1:
t = "jWebServer Not Running";
TaskNotify(NIM_MODIFY,IDI_DOWN,t);
SetDlgItemText(mDlg,IDC_STATUS,t);
EnableWindow(GetDlgItem(mDlg,IDC_START),TRUE);
EnableWindow(GetDlgItem(mDlg,IDC_STOP),FALSE);
break;
case 2:
t = "jWebServer Not Running";
TaskNotify(NIM_ADD,IDI_DOWN, t);
SetDlgItemText(mDlg,IDC_STATUS,t);
EnableWindow(GetDlgItem(mDlg,IDC_START),FALSE);
EnableWindow(GetDlgItem(mDlg,IDC_STOP),TRUE);
break;
}
}
|
|
|
#pragma once
#include "HttpServer.h"
class Socket;
class App
{
public:
void Create(HINSTANCE hInst);
void CleanUp(void);
static void AddSlash(char *str);
int GetPort();
void GetResource(char* name, DWORD& contentLength, BYTE*& byt, char* location);
void ServerEvent(HttpServer* source, int type);
void SetWinTitle(const char *s);
void SetNonBlockingMode(Socket& sock);
HWND GetHwnd() {return mHwnd; }
private:
void OnPaint();
void OnInitDialog(HWND hwnd);
void OnCloseDialog();
void OnClickOk();
void OnClickCancel();
void OnClickConfig();
void OnClickAbout();
void OnClickStart();
void OnClickStop();
void OnWinCreate();
void OnWinClose();
void OnWinSocketAccept(WPARAM wparam);
void OnWinSocketClose(WPARAM wparam);
void OnWinActivate(WPARAM wparam);
void LaunchBrowser(char *url);
void TaskNotify(int action, int icon, char *tip);
void CreateMainWindow();
void RegisterWindowClass(HINSTANCE hInst);
void CreateMainDialog();
void HideDialogWindow();
void ShowDialogWindow();
static LRESULT WINAPI MainDlgProc(HWND hd, UINT msg, WPARAM wparam, LPARAM lparam);
static LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
private:
HWND mHwnd;
char mText[80];
HttpServer mWebKnown;
HttpServer mWebServer;
HWND mDlg;
HINSTANCE mInstance;
int mXLoc;
int mYLoc;
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "Buffer.h"
Buffer::Buffer()
{
m_size = 0;
m_bufferSize = 2048;
m_data = (BYTE*)GlobalAlloc(GPTR,m_bufferSize);
}
Buffer::~Buffer()
{
GlobalFree(m_data);
}
void Buffer::Grow(DWORD by)
{
DWORD sz = m_bufferSize;
while( sz < (m_size + by + 5) )
sz *= 2;
if(sz!=m_bufferSize)
{
BYTE* temp = (BYTE*)GlobalAlloc(GPTR,sz);
memcpy(temp,m_data,m_bufferSize);
GlobalFree(m_data);
m_data = temp;
m_bufferSize = sz;
}
}
void Buffer::ConCat(const char *buffer,long length)
{
if(length==-1)
{
Grow(strlen(buffer)+1);
strcat((char*)m_data+m_size,buffer);
m_size += strlen(buffer);
}
else
{
Grow(length);
memcpy(m_data+m_size,buffer,length);
m_size += length;
}
}
void Buffer::ConCat(const string& s)
{
ConCat(s.c_str());
}
void Buffer::ConCat(BYTE b)
{
Grow(m_size+1);
*(m_data+m_size)=b;
m_size++;
}
|
|
|
#pragma once
#include <string>
using std::string;
class Buffer
{
public:
Buffer();
~Buffer();
void Clear(void){m_size=0;*m_data=0;};
BYTE *GetBuffer(void) { return m_data; };
DWORD GetLength(void) { return m_size; };
void ConCat(const char *buffer, long length=-1);
void ConCat(BYTE b);
void ConCat(const string& s);
void Write(const string& s)
{
ConCat(s);
}
void Writeln(const string& s)
{
ConCat(s);
ConCat("\r\n");
}
private:
void Grow(DWORD by);
protected:
DWORD m_size;// How much data has been added to this buffer
DWORD m_bufferSize;// How big a buffer is currently allocated
BYTE *m_data;// A pointer to the actual buffer
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include "common.h"
#include "Request.h"
#include "App.h"
#include "NtHandle.h"
#include "ConfigInfo.h"
//uncomment to do tracing!
//#define TRACEME
#ifdef TRACEME
#define TRACE(s, p1, p2, p3) \
{ \
FILE* fp = fopen("out.txt", "a"); \
fprintf(fp, "%8.8ld: INFO : " s, clock(), p1, p2, p3); \
fclose(fp); \
}
#else
#define TRACE(s, p1, p2, p3)
#endif
#define PRINTERR(s, p1, p2, p3) \
{ \
FILE* fp = fopen("out.txt", "a"); \
fprintf(fp, "%8.8ld: ERROR: " s, clock(), p1, p2, p3); \
fclose(fp); \
}
class Cgi
{
public:
} ;
bool Request::Cgi(char *path)
{
char fn[MAX_PATH],fn2[MAX_PATH],cgiroot[MAX_PATH],*p,*org;
const int cBufSize = 4096;
char buffer[cBufSize];
WIN32_FIND_DATA ff;
NtHandle hChildStdoutWr("hChildStdoutWr");
NtHandle hSaveStdin("hSaveStdin");
NtHandle hChildStdinRd("hChildStdinRd");
NtHandle hChildStdinWr("hChildStdinWr");
NtHandle hChildStdinWrDup("hChildStdinWrDup");
NtHandle hChildStdoutRd("hChildStdoutRd");
BOOL b,needHeader;
SECURITY_ATTRIBUTES sa;
int i;
Buffer post;
Buffer env;
BYTE b1,b2,b3,b4;
char script[MAX_PATH];
if(*path=='/')
path++;
if(!*path)
return false;
strncpy(fn, gConfigInfo.mWwwRoot.c_str(),sizeof(fn));
App::AddSlash(fn);
strcat(fn, szCgiBinName);
strcat(fn, "\\");
strncpy(cgiroot,fn,sizeof(cgiroot));
strcat(fn,path);
// Prevent the use of '..' to get to previous directory
p=strchr(fn,'?');
if(p!=NULL)
*p=0;
if( (strstr(fn,"..")!=NULL) ||
(strstr(m_fileRequest,"*")!=NULL) )
{
Error(403);
return false;
}
NtFindHandle h("h");
h.mHandle = FindFirstFile(fn, &ff);
if(h.mHandle == INVALID_HANDLE_VALUE)
return false;
// Setup pipes for output capture
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if(!CreatePipe(&hChildStdoutRd.mHandle,&hChildStdoutWr.mHandle,&sa,0))
return false;
//hChildStdoutWr closed below
hSaveStdin.mHandle = GetStdHandle(STD_INPUT_HANDLE);
if(!CreatePipe(&hChildStdinRd.mHandle,&hChildStdinWr.mHandle,&sa,0))
return false;
b = DuplicateHandle(GetCurrentProcess(),hChildStdinWr.mHandle,GetCurrentProcess(),&hChildStdinWrDup.mHandle,0,
FALSE,DUPLICATE_SAME_ACCESS);
if(!b)
return false;
// Read the entire post into memory
m_soc.Skip(1); //skip an initial cr
for(;;)
{
i = m_soc.Recv(buffer, cBufSize);
if( (i!=-1) && i)
post.ConCat(buffer,i);
else
break;
}
// Setup server environmental variables
org = p = GetEnvironmentStrings();
while( *p )
{
while(*p)
{
i++;
p++;
}
p++;
i++;
}
env.ConCat(org,i);
env.ConCat((BYTE)0);
// Add specific environmental variables
if(m_post)
env.ConCat("REQUEST_METHOD=POST");
else
env.ConCat("REQUEST_METHOD=GET");
env.ConCat((BYTE)0);
wsprintf(buffer,"CONTENT_LENGTH=%ld",post.GetLength()-1);
env.ConCat(buffer);
env.ConCat((BYTE)0);
env.ConCat("QUERY_STRING=");
if(m_query!=NULL)
env.ConCat(m_query);
env.ConCat((BYTE)0);
env.ConCat("SERVER_SOFTWARE=");
env.ConCat(szServerVersion);
env.ConCat((BYTE)0);
env.ConCat("SERVER_NAME=");
env.ConCat(gConfigInfo.mSiteName);
env.ConCat((BYTE)0);
wsprintf(buffer,"SERVER_PORT=%ld",gConfigInfo.m_port);
env.ConCat(buffer);
env.ConCat((BYTE)0);
Socket::Long2IP(m_requestBy,&b1,&b2,&b3,&b4);
wsprintf(buffer,"REMOTE_HOST=%d.%d.%d.%d",b1,b2,b3,b4);
env.ConCat(buffer);
env.ConCat((BYTE)0);
wsprintf(buffer,"REMOTE_ADDR=%d.%d.%d.%d",b1,b2,b3,b4);
env.ConCat(buffer);
env.ConCat((BYTE)0);
env.ConCat("DOCUMENT_ROOT=");
strncpy(buffer, gConfigInfo.mWwwRoot.c_str(), sizeof(buffer));
SwapChar(buffer,'\\','/');
env.ConCat(buffer);
env.ConCat((BYTE)0);
env.ConCat("SCRIPT_FILENAME=");
strncpy(buffer,fn,sizeof(buffer));
SwapChar(buffer,'\\','/');
env.ConCat(buffer);
env.ConCat((BYTE)0);
wsprintf(buffer,"REMOTE_PORT=%ld",m_port);
env.ConCat(buffer);
env.ConCat((BYTE)0);
env.ConCat("GATEWAY_INTERFACE=CGI/1.1");
env.ConCat((BYTE)0);
env.ConCat("SERVER_PROTOCOL=");
env.ConCat(m_version);
env.ConCat((BYTE)0);
env.ConCat("REQUEST_URI=");
env.ConCat(m_request);
env.ConCat((BYTE)0);
env.ConCat("SCRIPT_NAME=");
p=strchr(m_request,'?');
if(p!=NULL)
*p=0;
env.ConCat(m_request);
env.ConCat((BYTE)0);
// Add the HTTP headers as environmental variables
p = m_headers;
i = strlen(m_headers);
b = TRUE;
needHeader = TRUE;
while(i--)
{
if(*p!=13)
{
if(b)
{// before the :
if(*p==':')
{
p++;
env.ConCat((BYTE)'=');
b=FALSE;
while( (*p==' ') && i )
{
p++;
i--;
}
p--;
}
else
{
if(needHeader)
env.ConCat("HTTP_");
needHeader=FALSE;
env.ConCat(toupper((BYTE)*p));
}
}
else
env.ConCat(toupper((BYTE)*p));
}
else
{// After the :
env.ConCat((BYTE)0);
b=TRUE;
needHeader=TRUE;
}
p++;
}
env.ConCat((BYTE)0);
env.ConCat((BYTE)0);
FreeEnvironmentStrings(org);
// See if this is a script
p = fn + strlen(fn) - 1;
i=0;
while( (*p!='.') && (i<=3) )
{
p--;
i++;
}
*script=0;
if(*p=='.')
gConfigInfo.GetScript(p+1,script);
if(*script)
{
strncpy(fn2,script,sizeof(fn2));
strcat(fn2," ");
strcat(fn2,fn);
}
else
{
strcpy(fn2,fn);
}
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&si,0,sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdInput = hChildStdinRd.mHandle;
si.hStdOutput = hChildStdoutWr.mHandle;
si.hStdError = hChildStdoutWr.mHandle;
b = CreateProcess(NULL,fn2,NULL,NULL,TRUE,0,env.GetBuffer(),cgiroot,&si,&pi);
//pi.hProcess closed below
//pi.hThread closed below
if(!b)
return false;
mOut.WriteHeader();
// Write the post data to the process
// Read in request line and all headers
DWORD dw;
WriteFile(hChildStdinWrDup.mHandle,post.GetBuffer(),post.GetLength(),&dw,NULL);
// Non blocking mode
web.SetNonBlockingMode(m_soc);
// Now route the incoming bytes to the internet
// Note: the incoming bytes can arrive in bursts.
// Note: when the child terminates, it does an implicit close done on the anonymous pipe.
// Note: there can be bytes in the pipe after the child is dead
// Note: if there are no bytes in the pipe after the child is dead and Peek returns 0 available bytes,
// then the child did not write anything
TRACE("about to start main loop\n", 0, 0, 0)
bool childIsDead = false;
DWORD bytesRead = 0;
DWORD avail = 0;
for(;;) //main program loop
{
//read a byte to see if anything is there
dw = PeekNamedPipe(hChildStdoutRd.mHandle, buffer, 1, &bytesRead, &avail, NULL);
TRACE("after peek: dw=%lu avail=%lu bytesread=%lu\n", dw, avail, bytesRead);
if (!dw)
{
PRINTERR("after peek: dw=0x%8.8lX\n", dw, 0, 0)
break;
}
//if there's nothing to read, check if the child is dead
//otherwise go ahead and read it
if (bytesRead == 0 && avail == 0)
{
//child is dead and there's nothing to read, all done...
if (childIsDead)
break;
//child is still alive and there's nothing to read, wait a bit
Sleep(100);
//check if process is still up
dw = WaitForSingleObject(pi.hProcess, 0);
childIsDead = (dw == WAIT_OBJECT_0);
TRACE("wait on process; dw=%ld childIsDead=%d\n", dw, childIsDead, 0)
continue;
}
//there's something to read, so read it all...
for(;;)
{
DWORD bytestoread = avail > cBufSize ? cBufSize : avail;
TRACE("inner loop: bytestoread=%lu\n", bytestoread, 0, 0);
if (bytestoread == 0)
break;
dw = ReadFile(hChildStdoutRd.mHandle,buffer,bytestoread,&bytesRead,NULL);
if (!dw)
{
PRINTERR("after readfile: dw=0x%8.8lX\n", dw, 0, 0);
break;
}
m_soc.Send(buffer, bytesRead);
avail -= bytesRead;
TRACE("inner loop: after Read: avail=%lu bytesread=%lu\n", avail, bytesRead, 0);
}
}
TRACE("exit main loop\n", 0, 0, 0);
m_done = true;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}
|
|
|
#pragma once
#define EXE_NAME _pgmptr
// This constant defines how many concurrent connections the http
// server can handle at one time. This is NOT how many users can
// use the site at once, but rather how many concurrent requests
// it can process.
const int HTTP_CONNECTIONS = 100;
const int MAX_ERROR_TEXT = 80;
const int MAX_STD_STRING = 255;
extern const char* szExeName; //jwebserver
extern const char* szAppName; //jwebserver v9.9
extern const char* szCgiBinName; //cgi-bin
extern const char* errors[];
extern const char* szServerVersion;
class App;
extern App& web;
class ConfigInfo;
extern ConfigInfo& gConfigInfo;
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include "common.h"
#include "NtHandle.h"
#include "ConfigInfo.h"
ConfigInfo::ConfigInfo()
{
m_error=false;
LoadConfig();
}
ConfigInfo::~ConfigInfo()
{
SaveConfig();
}
void ConfigInfo::LoadConfig(void)
{
char defwww[MAX_PATH];
char buffer[80];
WIN32_FIND_DATA ff;
char *ptr;
m_error=false;
strncpy(configPath,EXE_NAME,sizeof(configPath));
ptr = configPath + strlen(configPath) - 1;
while( (*ptr!='\\') && (ptr>configPath) )
ptr--;
if(*ptr=='\\')
{
ptr++;
*ptr=0;
}
strncpy(defwww,configPath,sizeof(defwww));
strcat(defwww,"www\\");
GetFileName(configPath);
{
NtFindHandle h("h");
h.mHandle = FindFirstFile(configPath,&ff);
if( h.mHandle == INVALID_HANDLE_VALUE )
{
m_error=true;
return;
}
}
char temp[512];
GetPrivateProfileString("Config","servername","127.0.0.1", temp, MAX_PATH, configPath);
mSiteName = temp;
GetPrivateProfileString("Config","wwwroot", defwww, temp, MAX_PATH, configPath);
mWwwRoot = temp;
GetPrivateProfileString("Config","adminid","admin", temp,80,configPath);
mAdminId = temp;
GetPrivateProfileString("Config","adminpw","admin", temp, 80,configPath);
mAdminPwd = temp;
GetPrivateProfileString("Config","default","index.html", temp,80,configPath);
mDefaultDoc = temp;
GetPrivateProfileString("Config","logs","N",buffer,80,configPath);
if(toupper(*buffer)=='Y')
m_logs=true;
else
m_logs=false;
GetPrivateProfileString("Config","list","N",buffer,80,configPath);
if(toupper(*buffer)=='Y')
m_list=true;
else
m_list=false;
GetPrivateProfileString("Config","cgi","Y",buffer,80,configPath);
if(toupper(*buffer)=='Y')
m_cgi=true;
else
m_cgi=false;
m_port=GetPrivateProfileInt("Config","port",80,configPath);
GetPrivateProfileString("Mime","html","DEFAULT",buffer,80,configPath);
if(stricmp(buffer,"DEFAULT") == 0)
GenerateDefaultMime();
GetPrivateProfileString("Script","pl","DEFAULT",buffer,80,configPath);
if(!stricmp(buffer,"DEFAULT"))
GenerateDefaultScript();
}
void ConfigInfo::SaveConfig(void)
{
char buffer[80];
WritePrivateProfileString("Config","servername", (char*) mSiteName.c_str(), configPath);
WritePrivateProfileString("Config","wwwroot", (char*) mWwwRoot.c_str(), configPath);
WritePrivateProfileString("Config","adminid", (char*) mAdminId.c_str(), configPath);
WritePrivateProfileString("Config","adminpw", (char*) mAdminPwd.c_str(), configPath);
WritePrivateProfileString("Config","default", (char*) mDefaultDoc.c_str(), configPath);
*buffer=m_logs?'Y':'N';
buffer[1]=0;
WritePrivateProfileString("Config","logs",buffer,configPath);
*buffer=m_list?'Y':'N';
WritePrivateProfileString("Config","list",buffer,configPath);
*buffer=m_cgi?'Y':'N';
WritePrivateProfileString("Config","cgi",buffer,configPath);
wsprintf(buffer,"%ld",m_port);
WritePrivateProfileString("Config","port",buffer,configPath);
}
void ConfigInfo::GetFileName(char *dir)
{
char *ptr;
char tryit[MAX_PATH];
WIN32_FIND_DATA ff;
strncpy(dir,EXE_NAME,MAX_PATH);
ptr = dir + strlen(dir)-1;
while( (*ptr!='\\') && (ptr>dir) )
ptr--;
if(*ptr=='\\')
{
ptr++;
*ptr=0;
}
strcpy(tryit,dir);
strcat(tryit,"JWeb.ini");
{
NtFindHandle h("h");
h.mHandle = FindFirstFile(tryit,&ff);
if( h.mHandle != INVALID_HANDLE_VALUE )
{
strcpy(dir,tryit);
}
else
strcat(dir,"jwebserver.ini");
}
}
void ConfigInfo::GenerateDefaultMime(void)
{
char dir[MAX_PATH];
GetFileName(dir);
WritePrivateProfileString("Mime","gif","image/gif",dir);
WritePrivateProfileString("Mime","jpeg","image/jpeg",dir);
WritePrivateProfileString("Mime","jpg","image/jpeg",dir);
WritePrivateProfileString("Mime","html","text/html",dir);
WritePrivateProfileString("Mime","htm","text/html",dir);
WritePrivateProfileString("Mime","pps","application/pps",dir);
WritePrivateProfileString("Mime","pot","application/pot",dir);
WritePrivateProfileString("Mime","ppt","application/ppt",dir);
WritePrivateProfileString("Mime","pps","application/pps",dir);
WritePrivateProfileString("Mime","doc","application/msword",dir);
}
void ConfigInfo::AddMime(const string& e, const string& t)
{
char dir[MAX_PATH];
const char* ext = e.c_str();
const char* tag = t.c_str();
if (t.empty())
tag = 0;
char ext2[256];
char tag2[256];
if(*ext == '.')
ext++;
GetFileName(dir);
if(tag == NULL)
{
WritePrivateProfileString("Mime",ext,NULL,dir);
return;
}
strncpy(ext2,ext, sizeof(ext2));
CharLowerBuff(ext2, strlen(ext2));
strncpy(tag2,tag, sizeof(tag2));
CharLowerBuff(tag2, strlen(tag2));
WritePrivateProfileString("Mime", ext2, tag2, dir);
}
void ConfigInfo::GetMime(char *ext,char *tag)
{
char dir[MAX_PATH];
if(*ext=='.')
ext++;
GetFileName(dir);
GetPrivateProfileString("Mime",ext,"application/octet-stream",tag,80,dir);
}
void ConfigInfo::DelMime(const string& ext)
{
AddMime(ext, "");
}
void ConfigInfo::GetMimeList(char *buffer)
{
char dir[MAX_PATH];
GetFileName(dir);
GetPrivateProfileString("Mime",NULL,"",buffer,4096,dir);
}
void ConfigInfo::AddScript(const string& e, const string& t)
{
char dir[MAX_PATH];
const char* ext = e.c_str();
const char* tag = t.c_str();
if (t.empty())
tag = 0;
char ext2[256];
char tag2[256];
if(*ext=='.')
ext++;
GetFileName(dir);
if(tag==NULL)
{
WritePrivateProfileString("Script",ext,NULL,dir);
return;
}
strncpy(ext2,ext,sizeof(ext2));
CharLowerBuff(ext2, strlen(ext2));
strncpy(tag2,tag, sizeof(ext2));
CharLowerBuff(tag2, strlen(tag2));
WritePrivateProfileString("Script", ext2, tag2, dir);
}
void ConfigInfo::GetScript(char *ext,char *tag)
{
char dir[MAX_PATH];
if(*ext=='.')
ext++;
GetFileName(dir);
GetPrivateProfileString("Script",ext,"",tag,80,dir);
}
void ConfigInfo::DelScript(const string& ext)
{
AddScript(ext, "");
}
void ConfigInfo::GetScriptList(char *buffer)
{
char dir[MAX_PATH];
GetFileName(dir);
GetPrivateProfileString("Script",NULL,"",buffer,4096,dir);
}
void ConfigInfo::GenerateDefaultScript(void)
{
char dir[MAX_PATH];
GetFileName(dir);
WritePrivateProfileString("Script","pl","perl.exe",dir);
WritePrivateProfileString("Script","cgi","perl.exe",dir);
}
|
|
|
#pragma once
#include <string>
using std::string;
class ConfigInfo
{
public:
ConfigInfo();
~ConfigInfo();
void LoadConfig(void);
void SaveConfig(void);
void GenerateDefaultMime(void);
void GetFileName(char *dir);
// Mime tags
void AddMime(const string& e, const string& t);
void GetMime(char *ext,char *tag);
void DelMime(const string& ext);
void GetMimeList(char *buffer);
// Scripts
void AddScript(const string& ext, const string& path);
void GetScript(char *ext,char *path);
void DelScript(const string& ext);
void GetScriptList(char *buffer);
void GenerateDefaultScript(void);
string mSiteName;
string mWwwRoot;
string mDefaultDoc;
string mAdminId;
string mAdminPwd;
int m_port;
bool m_logs;
bool m_error;
bool m_list;
bool m_cgi;
char configPath[MAX_PATH];
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include "NtHandle.h"
#include "DirLister.h"
class DirLister::Private
{
public:
Private()
: h("DirLister")
{
}
string mPath;
NtFindHandle h;
WIN32_FIND_DATA mFData;
} ;
DirLister::DirLister()
: impl(* new DirLister::Private)
{
}
DirLister::~DirLister()
{
delete &impl;
}
void DirLister::First(const string& path)
{
impl.mPath = path;
string fspec = path + "\\*.*";
impl.h.mHandle = FindFirstFile(fspec.c_str(), &impl.mFData);
}
bool DirLister::Next()
{
return FindNextFile(impl.h.mHandle, &impl.mFData) == TRUE;
}
bool DirLister::IsValid()
{
return impl.h.mHandle != INVALID_HANDLE_VALUE;
}
bool DirLister::IsHidden()
{
return (impl.mFData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0;
}
bool DirLister::IsDir()
{
return (impl.mFData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
bool DirLister::IsDot()
{
return strcmp(impl.mFData.cFileName,".") == 0;
}
string DirLister::SizeAsString()
{
char sz[40];
if(IsDir())
strcpy(sz, "-");
else if (impl.mFData.nFileSizeLow <= 1024)
wsprintf(sz, "%d", impl.mFData.nFileSizeLow);
else
wsprintf(sz, "%dK", impl.mFData.nFileSizeLow/1024);
return sz;
}
string DirLister::Name()
{
return impl.mFData.cFileName;
}
string DirLister::DateAsString()
{
char strMod[40];
SYSTEMTIME st;
FileTimeToSystemTime(&impl.mFData.ftLastWriteTime,&st);
TimeAsString(st, strMod);
return strMod;
}
void DirLister::TimeAsString(const SYSTEMTIME& st,char *out)
{
char *dow[7]={ "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
char *month[12]={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
assert(st.wDayOfWeek<7);
strcpy(out, dow[st.wDayOfWeek]);
assert(st.wMonth && (st.wMonth<=12) );
wsprintf(out+ strlen(out),". %ld %s %ld %02ld:%02ld:%02ld GMT",
st.wDay,month[st.wMonth-1], st.wYear, st.wHour, st.wMinute, st.wSecond);
}
|
|
|
#pragma once
#include <string>
using std::string;
//#include "NtHandle.h"
class DirLister
{
public:
DirLister();
~DirLister();
void First(const string& path);
bool Next();
bool IsValid();
bool IsHidden();
bool IsDir();
bool IsDot();
string SizeAsString();
string Name();
string DateAsString();
void TimeAsString(const SYSTEMTIME& st,char *out);
private:
class Private;
Private& impl;
} ;
|
|
|
#pragma once
#pragma warning(disable: 4786)
#include "HtmlStream.h"
#include "HttpOutStream.h"
#include "HtmlBuffer.h"
typedef HtmlStream<HttpOutStream> HtmlOutStream;
typedef HtmlStream<HtmlBuffer> HtmlStrStream;
|
|
|
#pragma once
class HtmlBuffer : public Buffer
{
public:
void WriteOn(HttpOutStream& out)
{
out.WriteBytes(GetBuffer(), GetLength());
}
} ;
|
|
|
#pragma once
class HtmlDirGen
{
public:
HtmlDirGen(HtmlOutStream& os)
: mOut(os)
{
}
void Gen(const string& path)
{
Init(path);
mLister.First(path);
if(mLister.IsValid())
{
GenHeadingRow();
GenRows();
}
else
{
mOut.H1("FindFirst failed. Cannot read directory.");
}
Term();
}
private:
void GenRows()
{
do
{
if (mLister.IsDot()) continue;
if (mLister.IsHidden()) continue;
GenRow();
} while (mLister.Next());
}
void Init(const string& path)
{
mOut.HTML();
mOut.HEAD();
mOut.TITLE(path);
mOut.CloseTag();//head
mOut.BODY();
mOut.H1("Directory listing of " + path);
mOut.TABLE(false);
}
void GenHeadingRow()
{
mOut.TR();
mOut.TH("Type");
mOut.TH("File Name");
mOut.TH("Size");
mOut.TH("Last Modified");
mOut.CloseTag(); //TR
}
void GenRow()
{
mOut.TR();
GenLabelColumn();
GenPathColumn();
GenSizeColumn();
GenDateColumn();
mOut.CloseTag(); //TR
}
void GenSizeColumn()
{
mOut.TD(mLister.SizeAsString());
}
static void toPlus(char& c)
{
if (c == ' ')
c = '+';
}
void GetConvertedPath()
{
mConvertedPath = mLister.Name();
for_each(mConvertedPath.begin(), mConvertedPath.end(), toPlus);
if(mLister.IsDir())
mConvertedPath += "/";
}
void GenPathColumn()
{
GetConvertedPath();
mOut.TD();
mOut.A(mConvertedPath, strcmp(mConvertedPath.c_str(), "../") == 0 ? "Parent Directory" : mLister.Name() );
mOut.CloseTag(); //TD
}
void GenLabelColumn()
{
mOut.TD();
if(mLister.IsDir())
mOut.Write("[DIR]");
else
mOut.Write("[FILE]");
mOut.CloseTag(); //TD
}
void GenDateColumn()
{
mOut.TD(mLister.DateAsString());
}
void Term()
{
mOut.CloseAllTags();
}
private:
DirLister mLister;
HtmlOutStream mOut;
string mConvertedPath;
} ;
|
|
|
#pragma once
#include "Html.h"
#include "ConfigInfo.h"
class HtmlPageGen
{
public:
HtmlPageGen(HtmlStrStream& out)
: mStrOut(out)
{
}
enum eConfigType {Script, Mime};
void ConfirmationPage(const string& title, const string& text, bool docontinue = true)
{
mStrOut.Clear();
mStrOut.HTML();
mStrOut.HEAD();
mStrOut.TITLE(title);
mStrOut.CloseTag();
mStrOut.BODY();
mStrOut.H1(title);
mStrOut.Text(text);
if (docontinue)
AdminContinue();
mStrOut.CloseAllTags();
}
void ConfigPage(eConfigType type, const string& title, const string& text,
const string& changeaction, const string& changetitle, const string& changeitem,
const string& deleteaction, const string& deletetitle)
{
mStrOut.HTML();
mStrOut.HEAD();
mStrOut.TITLE(title);
mStrOut.CloseTag();
mStrOut.BODY();
mStrOut.H1(title);
mStrOut.P();
mStrOut.Text(text);
mStrOut.CloseTag(); //P
if (type == Script)
GenScriptTable();
else
GenMimeTable();
mStrOut.HR();
ChangeForm(changeaction, changetitle, changeitem);
mStrOut.HR();
DeleteForm(deleteaction, deletetitle);
mStrOut.HR();
AdminContinue();
mStrOut.CloseAllTags();
}
void MainPage(int port)
{
char buffer[1024];
mStrOut.HTML();
mStrOut.HEAD();
wsprintf(buffer,"Welcome Back %s", gConfigInfo.mAdminId.c_str());
mStrOut.TITLE(buffer);
mStrOut.CloseTag(); //HEAD
mStrOut.BODY();
mStrOut.H1("jWebServer Configuration");
mStrOut.FORM_POST("/admin/change.html");
AddHiddenFields();
mStrOut.TABLE(true);
InputRow("Root Directory for Web Site:", "ROOT", gConfigInfo.mWwwRoot);
InputRow("Port to run Web from:", "PORT", gConfigInfo.m_port);
InputRow("Administrator ID:", "ID", gConfigInfo.mAdminId);
PasswordRow("Administrator Password:", "PW", gConfigInfo.mAdminPwd);
InputRow("Default Document:", "DEF", gConfigInfo.mDefaultDoc);
InputRow("Website URL(domain eg. www.arrizza.com):", "SITE", gConfigInfo.mSiteName);
CheckboxRow("Log requests (access.log)?", "LOG", gConfigInfo.m_logs);
CheckboxRow("Allow directory browsing?", "LIST", gConfigInfo.m_list);
CheckboxRow("Enable cgi-bin?", "CGI", gConfigInfo.m_cgi);
mStrOut.TR();
mStrOut.Writeln("<TD COLSPAN=2 ALIGN=\"CENTER\">");
mStrOut.SUBMIT("ACTION", "SAVE");
mStrOut.SUBMIT("ACTION", "MIME");
mStrOut.SUBMIT("ACTION", "SCRIPT");
mStrOut.Writeln("</TD>");
mStrOut.CloseTag(); //TR
mStrOut.CloseTag(); //TABLE
mStrOut.CloseTag(); //FORM
mStrOut.P();
wsprintf(buffer,"http://127.0.0.1:%d/admin", port);
mStrOut.A(buffer, "[Cancel Changes]");
mStrOut.CloseAllTags();
}
private:
void DeleteForm(const string& action, const string& title)
{
DeleteForm(action, title, "File Extension to Delete:", "EXT", "Delete");
}
void DeleteForm(const string& action, const string& title, const string& item, const string& tag, const string& submitname)
{
mStrOut.FORM_POST(action);
mStrOut.H2(title);
AddHiddenFields();
mStrOut.TABLE(false);
InputRow(item, tag, "");
mStrOut.CloseTag();//TABLE
mStrOut.SUBMIT("", submitname);
mStrOut.CloseTag();//FORM
}
void ChangeForm(const string& action, const string& title, const string& item)
{
ChangeForm(action, title, item, "TAG", "Add/Change");
}
void ChangeForm(const string& action, const string& title, const string& item, const string& tag, const string& submitname)
{
mStrOut.FORM_POST(action);
mStrOut.H2(title);
AddHiddenFields();
mStrOut.TABLE(false);
InputRow("File Extension", "EXT", "");
InputRow(item, tag, "");
mStrOut.CloseTag(); //TABLE
mStrOut.SUBMIT("", submitname);
mStrOut.CloseTag(); //FORM
}
void InputRow(const string& title, const string& name, const string& value)
{
mStrOut.TR();
mStrOut.TD(title);
mStrOut.TD();
mStrOut.INPUT(name, value);
mStrOut.CloseTag(); //TD
mStrOut.CloseTag(); //TR
}
void InputRow(const string& title, const string& name, long value)
{
mStrOut.TR();
mStrOut.TD(title);
mStrOut.TD();
mStrOut.INPUT(name, value);
mStrOut.CloseTag(); //TD
mStrOut.CloseTag(); //TR
}
void PasswordRow(const string& title, const string& name, const string& value)
{
mStrOut.TR();
mStrOut.TD(title);
mStrOut.TD();
mStrOut.PASSWORD(name, value);
mStrOut.CloseTag(); //TD
mStrOut.CloseTag(); //TR
}
void CheckboxRow(const string& title, const string& name, bool value)
{
mStrOut.TR();
mStrOut.TD(title);
mStrOut.TD();
mStrOut.CHECKBOX(name, value);
mStrOut.CloseTag(); //TD
mStrOut.CloseTag(); //TR
}
void AdminContinue(void)
{
mStrOut.FORM_POST("/admin/login.html");
mStrOut.HIDDEN("ID", gConfigInfo.mAdminId);
mStrOut.HIDDEN("PW", gConfigInfo.mAdminPwd);
mStrOut.SUBMIT("", "Continue");
mStrOut.CloseTag(); //FORM
}
void AddHiddenFields()
{
mStrOut.HIDDEN("AID", gConfigInfo.mAdminId);
mStrOut.HIDDEN("APW", gConfigInfo.mAdminPwd);
}
void GenMimeTable()
{
mStrOut.TABLE(true);
mStrOut.TR();
mStrOut.TH("File Extension(i.e. .gif, .jpg, .html etc)");
mStrOut.TH("Mime Tag to Map");
mStrOut.CloseTag(); //TR
char buffer[4096];
gConfigInfo.GetMimeList(buffer);
char str[256];
char str2[256];
for(char* sptr = buffer; *sptr; sptr += strlen(sptr) + 1)
{
strcpy(str, sptr);
gConfigInfo.GetMime(str, str2);
mStrOut.TR();
mStrOut.TD(str);
mStrOut.TD(str2);
mStrOut.CloseTag(); //TR
}
mStrOut.CloseTag(); //TABLE
}
void GenScriptTable()
{
mStrOut.TABLE(true);
mStrOut.TR();
mStrOut.TH("File Extension(i.e. .cgi, .pl, etc)");
mStrOut.TH("Script Engine");
mStrOut.CloseTag(); //TR
char buffer[4096];
gConfigInfo.GetScriptList(buffer);
char str[256];
char str2[256];
for (char* sptr = buffer; *sptr; sptr += strlen(str) + 1)
{
strcpy(str, sptr);
gConfigInfo.GetScript(str, str2);
mStrOut.TR();
mStrOut.TD(str);
mStrOut.TD(str2);
mStrOut.CloseTag(); //TR
}
mStrOut.CloseTag(); //TABLE
}
private:
HtmlStrStream& mStrOut;
};
|
|
|
#pragma once
#include <stack>
using std::stack;
//writes HTML
// tWriter must implement:
// Write(const string& s)
// Writeln(const string& s)
template <class tWriter>
class HtmlStream : public tWriter
{
public:
void HTML()
{
Tag("HTML");
}
void HEAD()
{
Tag("HEAD");
}
void BODY()
{
Tag("BODY");
}
void P()
{
Tag("P");
}
void BR()
{
Writeln("<BR/>");
}
void HR()
{
Writeln("<HR/>");
}
void TITLE(const string& s)
{
Write("<TITLE>");
Write(s);
Writeln("</TITLE>");
}
void H1(const string& s)
{
Write("<H1>");
Write(s);
Writeln("</H1>");
}
void H2(const string& s)
{
Write("<H2>");
Write(s);
Writeln("</H2>");
}
void INPUT(const string& name, const string& value)
{
InputField("TEXT", name, value);
}
void INPUT(const string& name, long value)
{
char buf[20];
sprintf(buf, "%ld", value);
InputField("TEXT", name, buf);
}
void HIDDEN(const string& name, const string& value)
{
InputField("HIDDEN", name, value);
}
void SUBMIT(const string& name, const string& value)
{
InputField("SUBMIT", name, value);
}
void PASSWORD(const string& name, const string& value)
{
InputField("PASSWORD", name, value);
}
void CHECKBOX(const string& name, bool checked)
{
char buffer[2048];
strcpy(buffer, "<INPUT TYPE='CHECKBOX' ");
if (!name.empty())
{
strcat(buffer, "NAME='");
strcat(buffer, name.c_str());
strcat(buffer, "' ");
}
if (checked)
{
strcat(buffer, "CHECKED");
}
strcat(buffer, " />");
Writeln(buffer);
}
void FORM_POST(const string& action)
{
Write("<FORM METHOD='POST' ACTION='");
Write(action);
Write("'>");
mCloseTags.push("</FORM>");
}
void Text(const string& text)
{
Writeln(text);
}
void CloseTag()
{
if (mCloseTags.empty()) return;
string tag = mCloseTags.top();
mCloseTags.pop();
Write(tag);
};
void CloseAllTags()
{
while(!mCloseTags.empty())
CloseTag();
};
void TABLE(bool border)
{
if (border)
Write("<TABLE BORDER=1>");
else
Write("<TABLE BORDER=0>");
mCloseTags.push("</TABLE>");
}
void TH(const string& s)
{
Write("<TH>");
Write(s);
Writeln("</TH>");
}
void TD()
{
Tag("TD");
}
void TD(const string& s)
{
Write("<TD>");
Write(s);
Writeln("</TD>");
}
void TR()
{
Tag("TR");
}
void A(const string& href, const string& s)
{
Write("<A HREF=\"");
Write(href);
Write("\">");
Write(s);
Write("</A>");
}
private:
void InputField(const string& type, const string& name, const string& value)
{
char buffer[2048];
strcpy(buffer, "<INPUT ");
if (!type.empty())
{
strcat(buffer, "TYPE='");
strcat(buffer, type.c_str());
strcat(buffer, "' ");
}
if (!name.empty())
{
strcat(buffer, "NAME='");
strcat(buffer, name.c_str());
strcat(buffer, "' ");
}
if (!value.empty())
{
strcat(buffer, "VALUE='");
strcat(buffer, value.c_str());
strcat(buffer, "' ");
}
strcat(buffer, " />");
Writeln(buffer);
}
void Tag(const string& name)
{
Write("<" + name + ">");
mCloseTags.push("</" + name + ">");
}
private:
stack<string> mCloseTags;
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include "common.h"
#include "HttpOutStream.h"
HttpOutStream::HttpOutStream()
: mBytesSent(0)
{
}
void HttpOutStream::Write(const string& s)
{
Write(s.c_str());
}
void HttpOutStream::Write(const char* s)
{
mBytesSent += mSocket.Send(s, (unsigned long) strlen(s));
}
void HttpOutStream::Writeln(const char *s)
{
Write(s);
Write("\r\n");
}
void HttpOutStream::WriteBytes(const unsigned char* buffer, unsigned long len)
{
mBytesSent += mSocket.Send(buffer, len);
}
void HttpOutStream::SetSocket(Socket& s)
{
mSocket = s;
}
void HttpOutStream::WriteHtmlContentType()
{
WriteMimeFor(0);
}
void HttpOutStream::WriteHeader()
{
Writeln("HTTP/1.0 200 OK");
WriteServerVersion();
Writeln("Accept-Ranges: bytes");
}
void HttpOutStream::WriteEndOfHeaders()
{
Write("\r\n");
mBytesSent = 0;
}
void HttpOutStream::WriteDate()
{
SYSTEMTIME st;
GetSystemTime(&st);
WriteDate(st);
}
void HttpOutStream::WriteDate(const SYSTEMTIME& st)
{
WriteDate(st, "Date: ");
}
void HttpOutStream::WriteLastModifiedDate(const SYSTEMTIME& st)
{
WriteDate(st, "Last-Modified: ");
}
void HttpOutStream::WriteLastModifiedDate()
{
SYSTEMTIME st;
GetSystemTime(&st);
WriteLastModifiedDate(st);
}
void HttpOutStream::WriteContentLength(long len)
{
char buffer[100];
wsprintf(buffer, "Content-Length: %ld", len);
Writeln(buffer);
}
void HttpOutStream::WriteMimeFor(const char* ext)
{
char mime[80];
GenerateMime(ext, mime);
Writeln(mime);
}
void HttpOutStream::WriteServerVersion()
{
Write("Server: ");
Writeln(szServerVersion);
}
void HttpOutStream::WriteMovePermanently()
{
Writeln("HTTP/1.0 301 Moved Permanently");
}
long HttpOutStream::GetBytesSent()
{
return mBytesSent;
}
void HttpOutStream::TimeString(const SYSTEMTIME& st,char *out)
{
char *dow[7]={ "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
char *month[12]={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
assert(st.wDayOfWeek<7);
strcpy(out, dow[st.wDayOfWeek]);
assert(st.wMonth && (st.wMonth<=12) );
wsprintf(out+strlen(out),". %ld %s %ld %02ld:%02ld:%02ld GMT", st.wDay,month[st.wMonth-1], st.wYear, st.wHour, st.wMinute, st.wSecond);
}
void HttpOutStream::WriteDate(const SYSTEMTIME& st, char* header)
{
char buffer[100];
strcpy(buffer,"Date: ");
TimeString(st, buffer+strlen(buffer)-1);
Writeln(buffer);
}
void HttpOutStream::GenerateMime(const char *e, char *buffer)
{
strcpy(buffer,"Content-Type: ");
if (e == 0)
strcat(buffer, "text/html");
else if( stricmp(e,"HTML") == 0 || stricmp(e,"HTM") == 0 )
strcat(buffer,"text/html");
else if( stricmp(e,"JPG") == 0 || stricmp(e,"JPEG") == 0)
strcat(buffer,"image/jpeg");
else if( stricmp(e,"GIF") == 0)
strcat(buffer,"image/gif");
else
strcat(buffer,"application/octet-stream");
}
|
|
|
#pragma once
#include <string>
using std::string;
#include "Socket.h"
//sends an HTTP stream to a socket
class HttpOutStream
{
public:
HttpOutStream();
void Write(const string& s);
void Write(const char* s);
void Writeln(const char *s);
void WriteBytes(const unsigned char* buffer, unsigned long len);
void SetSocket(Socket& s);
void WriteHtmlContentType();
void WriteHeader();
void WriteEndOfHeaders();
void WriteDate();
void WriteDate(const SYSTEMTIME& st);
void WriteLastModifiedDate(const SYSTEMTIME& st);
void WriteLastModifiedDate();
void WriteContentLength(long len);
void WriteMimeFor(const char* ext);
void WriteServerVersion();
void WriteMovePermanently();
long GetBytesSent();
private:
void TimeString(const SYSTEMTIME& st,char *out);
void WriteDate(const SYSTEMTIME& st, char* header);
void GenerateMime(const char *e, char *buffer);
private:
Socket mSocket;
long mBytesSent;
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <assert.h>
#include "common.h"
#include "App.h"
#include "HttpRequest.h"
#include "NtHandle.h"
HttpRequest::HttpRequest()
: mPageGen(mStrOut)
{
m_started=false;
m_post = false;
m_thread = NULL;
}
const char* errors[] = {
"400 Bad Request",
"403 Forbidden",
"404 Object Not Found",
"500 Internal Error",
"501 Not Supported",
0
};
void HttpRequest::Error(int n)
{
strncpy(m_errorText, "HTTP/1.0 ", MAX_ERROR_TEXT);
for(int i = 0; errors[i]; ++i)
{
if(atoi(errors[i])==n)
{
strcat(m_errorText, errors[i]);
return;
}
}
strcat(m_errorText,"500 Internal Error");
}
void HttpRequest::DoError(void)
{
mOut.Writeln(m_errorText);
mOut.WriteHtmlContentType();
mOut.WriteEndOfHeaders();
mOut.BODY();
mOut.H1(m_errorText);
mOut.CloseTag(); //body
}
void HttpRequest::Start(const Socket& s, unsigned long by,unsigned long by_port, HttpServer *svr)
{
m_started=true;
m_soc = s;
mOut.SetSocket(m_soc);
m_requestBy = by;
m_server = svr;
m_port = by_port;
if(m_thread != NULL )
m_thread=NULL;
}
bool HttpRequest::IsRunning()
{
return m_started;
}
void HttpRequest::DoTransaction(void)
{
char ch,last;
int i;
DWORD t;
SYSTEMTIME st;
GetSystemTime(&st);
*m_fileRequest=0;
*m_errorText=0;
m_done=false;
m_head=false;
m_post = false;
try
{
// Read in request line and all headers
mStrOut.Clear();
m_headerBuffer.Clear();
t = GetTickCount()/1000;
for(;;)
{
i = m_soc.Recv(&ch, 1);
if( (i!=-1) && i)
{
t = GetTickCount()/1000;
if(ch!='\n')
{
m_headerBuffer.ConCat((BYTE)ch);
if( (ch==13) && (last==13) ) // two CR's mark the end of headers
break;
last = ch;
}
}
else
{
if( ((GetTickCount()/1000)-t)>30)
break;
}
}
// Get the request
m_headers=strchr(m_verb=(char*)m_headerBuffer.GetBuffer(),'\r');
if(m_headers==NULL)
return;
*(m_headers++)=0;
m_request=strchr(m_verb,' ');
if(m_request==NULL)
return;
*(m_request++)=0;
if( strlen(m_request) >2048 )
m_request[2048] = 0;
m_version=strchr(m_request,' ');
if(m_version==NULL)
return;
*(m_version++)=0;
}
catch(...)
{
return;
}
// now parse the request
try
{
m_head=false;
CharUpperBuff(m_verb, strlen(m_verb));
if (stricmp(m_verb,"HEAD") == 0)
{
m_head=true;
Get(m_request);
}
else if (stricmp(m_verb,"GET") == 0)
{
Get(m_request);
}
else if (stricmp(m_verb,"POST") == 0)
{
Post(m_request);
}
else if (stricmp(m_verb,"PUT") == 0 || stricmp(m_verb,"TRACE") == 0 )
{
Error(501);
}
else
Error(400);
}
catch(...)
{
Error(500);
}
try
{
// Complete transaction
if( *m_errorText )
{
DoError();
}
else if (*m_fileRequest && ( *(m_fileRequest + strlen(m_fileRequest)-1)=='\\' ) )
{
FileList();
}
else if (!m_done)
{
if(*m_fileRequest)
SendFile();
else
{
// Transmit the response
mOut.WriteHeader();
mOut.WriteDate(st);
mOut.WriteHtmlContentType();
mOut.WriteLastModifiedDate(st);
mOut.WriteContentLength(mStrOut.GetLength());
mOut.WriteEndOfHeaders();
// Transmit data
if(!m_head)
mStrOut.WriteOn(mOut);
}
}
m_soc.AsyncClose(web.GetHwnd());
m_soc.ShutDown();
m_started=false;
LogRequest();
}
catch(...)
{
}
}
void HttpRequest::LogRequest(void)
{
}
void HttpRequest::SendFile(void)
{
unsigned char buffer[256];
char* ext;
NtHandle fp("fp");
DWORD dw;
long bytesLeft;
FILETIME ft;
SYSTEMTIME st;
DWORD contentLength;
fp.mHandle = CreateFile(
m_fileRequest,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if(fp.mHandle ==INVALID_HANDLE_VALUE)
{
Error(404);
return;
}
contentLength = GetFileSize(fp.mHandle, NULL);
GetFileTime(fp.mHandle, NULL,NULL,&ft);
FileTimeToSystemTime(&ft,&st);
ext = strchr(m_fileRequest,'.');
if (ext != 0)
ext++;
mOut.WriteHeader();
mOut.WriteDate();
mOut.WriteMimeFor(ext);
mOut.WriteLastModifiedDate(st);
mOut.WriteContentLength(contentLength);
mOut.WriteEndOfHeaders();
bytesLeft = contentLength;
// Block mode
m_soc.SetNonBlockingMode(web.GetHwnd());
// Transmit data
while(bytesLeft>0)
{
if( ReadFile(fp.mHandle, buffer, 256, &dw, NULL) == 0)
break;
mOut.WriteBytes(buffer, dw);
bytesLeft -= dw;
}
}
void HttpRequest::SendResource(char *name, char *ext)
{
BYTE *byt;
DWORD contentLength;
web.GetResource(name, contentLength, byt, "WEBDAT");
mOut.WriteHeader();
mOut.WriteDate();
mOut.WriteMimeFor(ext);
mOut.WriteLastModifiedDate();
mOut.WriteContentLength(contentLength);
mOut.WriteEndOfHeaders();
mOut.WriteBytes(byt, contentLength);
m_done=true;
}
void HttpRequest::Get(char *)
{
Error(404);
}
void HttpRequest::Post(char *s)
{
m_post = true;
Get(s);
}
void HttpRequest::FileList(void)
{
Error(403);
}
bool HttpRequest::Parse(string& name, string& value)
{
int i;
char ch,hexcode[3];
int state;
int hex;
DWORD t;
name = "";
value = "";
// Read in request line and all headers
state = 0;
hex=0;
t = GetTickCount()/1000;
for(;;)
{
if( ((GetTickCount()/1000)-t)>30)
return false;
i = m_soc.Recv(&ch, 1);
if( (i!=-1) && i)
{
t = GetTickCount()/1000;
if( (ch==13) || (ch==10) )
continue;
// URL decode first
switch(hex)
{
case 0:
if(ch=='=')
{
state = 1;
continue;
}
if(ch=='&')
return true;
if(ch=='+')
ch=32;
if(ch=='%')
{
hex=1;
continue;
}
break;
case 1:
hexcode[0]=toupper(ch);
hexcode[2]=0;
hex=2;
continue;
case 2:
hexcode[1]=toupper(ch);
hexcode[2]=0;
hex=0;
ch = IntFromHex(hexcode);
break;
}
// now place it where it goes
switch(state)
{
case 0: name += ch; break;
case 1: value += ch; break;
}
}
else
return !name.empty();
}
return true;
}
int HttpRequest::IntFromHex(char *pChars)
{
int hi,lo,result;
hi=pChars[0];
if( '0'<=hi && hi <='9' )
hi-='0';
else if( 'a'<=hi && hi<='f' )
hi-=('a'-10);
else if( 'A'<=hi && hi<='F' )
hi-=('A'-10);
lo=pChars[1];
if( '0'<=lo && lo <='9' )
lo-='0';
else if( 'a'<=lo && lo<='f' )
lo-=('a'-10);
else if( 'A'<=lo && lo<='F' )
lo-=('A'-10);
result = lo + (16* hi);
return result;
}
void HttpRequest::SwapChar(char *pOriginal, char cBad,char cGood)
{
int i;
i=0;
while(pOriginal[i])
{
if(pOriginal[i])
{
if(pOriginal[i]==cBad) pOriginal[i]=cGood;
i++;
}
}
}
void HttpRequest::URLDecode(char *pEncoded)
{
char *pDecoded;
SwapChar(pEncoded,'+',' ');
pDecoded=pEncoded;
while(*pEncoded)
{
if(*pEncoded=='%')
{
pEncoded++;
if(isxdigit(pEncoded[0]) && isxdigit(pEncoded[1]) )
{
*pDecoded++=(char)IntFromHex(pEncoded);
pEncoded+=2;
}
}
else
{
*pDecoded++=*pEncoded++;
}
}
*pDecoded=0;
}
bool HttpRequest::StartsWith(char *s1,char *cmp)
{
while(*cmp)
{
if( toupper(*s1)!=toupper(*cmp) )
return false;
s1++;
cmp++;
}
return true;
}
|
|
|
#pragma once
#include "Buffer.h"
class HttpServer;
#include "Html.h"
#include "Socket.h"
#include "HtmlPageGen.h"
class HttpRequest
{
public:
HttpRequest();
void Start(const Socket& s,unsigned long by,unsigned long by_port,HttpServer *svr);
void DoTransaction();
bool IsRunning();
void Error(int n);
HANDLE m_thread;
static bool StartsWith(char *s1,char *cmp);
static int IntFromHex(char *pChars);
static void SwapChar(char *pOriginal, char cBad,char cGood);
static void URLDecode(char *pEncoded);
protected:
virtual void Get(char *path);
virtual void Post(char *path);
virtual void LogRequest(void);
virtual void FileList(void);
void SendFile(void);
void SendResource(char *name,char *mime);
void DoError(void);
bool Parse(string& name, string& value);
bool m_started;
Socket m_soc;
unsigned long m_port;
unsigned long m_requestBy;
HttpServer *m_server;
char m_fileRequest[MAX_PATH];
char m_errorText[MAX_ERROR_TEXT];
bool m_head;
bool m_done;
bool m_post;
Buffer m_headerBuffer;
HtmlStrStream mStrOut;
HtmlOutStream mOut;
HtmlPageGen mPageGen; //must come after mStrOut!
char* m_verb;
char* m_request;
char* m_headers;
char* m_version;
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include "common.h"
#include "App.h"
#include "HttpServer.h"
#include "HttpRequest.h"
void HttpServer::HandleRequest(void *p)
{
HttpRequest *http=(HttpRequest *)p;
http->DoTransaction();
_endthread();
}
HttpServer::HttpServer()
{
int i;
m_autoFindPort=false;
m_running=false;
for(i=0;i<HTTP_CONNECTIONS;i++)
m_connections[i]=NULL;
}
HttpServer::~HttpServer()
{
StopServer();
}
bool HttpServer::IsRunning(void)
{
return m_running;
}
void HttpServer::Accept(void)
{
unsigned long addr;
unsigned long port;
Socket newConn = m_listener.Accept(addr, port);
HttpRequest *req = FindConnection();
req->Start(newConn, addr, port, this);
req->m_thread = (HANDLE)_beginthread(HandleRequest, 32767, (LPVOID)req);
}
void HttpServer::StartServer(int p)
{
if(m_running)
return;
for(int i=0; i < HTTP_CONNECTIONS; i++)
if(m_connections[i]==NULL)
m_connections[i]=new HttpRequest;
web.ServerEvent(this, 1);
m_portno = p;
// Setup the listner socket
m_listener.CreateListener();
if (m_listener.IsInvalid())
{
web.SetWinTitle(m_listener.GetLastErrorDesc());
return;
}
if(m_autoFindPort)
{
bool done=false;
while(!done)
{
int err = m_listener.Bind(m_portno);
if(m_listener.IsError(err))
{
if(m_listener.IsAddressInUse())
{
char out[80];
wsprintf(out, "Can't bind to port %i.",m_portno);
web.SetWinTitle(out);
return;
}
else
m_portno++;
}
else
done=true;
}
}
else
{
int err = m_listener.Bind(m_portno);
if (m_listener.IsError(err))
{
char out[80];
if (m_listener.IsAddressInUse())
wsprintf(out, "Can't use port %d. Another web server may be running.",m_portno);
else
wsprintf(out, "Can't bind to port %d.",m_portno);
web.SetWinTitle(out);
return;
}
}
int err = m_listener.Listen(5);
if (m_listener.IsError(err))
{
web.SetWinTitle("Socket Listen Failed");
return;
}
m_listener.AsyncCloseOrAccept(web.GetHwnd());
m_running=true;
web.ServerEvent(this, 0);
}
void HttpServer::StopServer(void)
{
if(!m_running)
return;
m_listener.Close();
m_running=false;
web.ServerEvent(this, 1);
}
int HttpServer::GetPort(void)
{
return m_portno;
}
HttpRequest *HttpServer::FindConnection(void)
{
for(;;)
{
for(int i=0;i<HTTP_CONNECTIONS;i++)
if( !m_connections[i]->IsRunning() )
return m_connections[i];
Sleep(1000);
}
}
bool HttpServer::Compare(const Socket& s)
{
return m_listener.IsEqual(s);
}
|
|
|
#pragma once
#include "Socket.h"
class HttpRequest;
class HttpServer
{
public:
HttpServer();
~HttpServer();
void StartServer(int p=80);
void StopServer(void);
bool IsRunning(void);
int GetPort(void);
bool Compare(const Socket& s);
static void HandleRequest(void *p);
HttpRequest *FindConnection(void);
void Accept(void);
bool m_autoFindPort;
HttpRequest *m_connections[HTTP_CONNECTIONS];
protected:
Socket m_listener;
int m_portno;
bool m_running;
};
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "common.h"
#include "App.h"
#include "resource.h"
#include <shlobj.h>
#include "NtHandle.h"
#include "ConfigInfo.h"
#include "Install.h"
static Install* This = 0;
Install::Install()
: mInstance(0), mDlg(0)
{
}
Install::Install(HINSTANCE inst, HWND dlg)
: mInstance(inst), mDlg(dlg)
{
This = this;
}
void Install::Run(void)
{
if( DialogBox(mInstance,"INSTALL",NULL,(DLGPROC) Proc1) == IDCANCEL )
return;
if( DialogBox(mInstance,"INSTALL2",NULL,(DLGPROC) Proc2) == IDCANCEL )
return;
MakeDir(mBinDir);
MakeDir(mWwwrootDir);
char cgi[MAX_PATH];
strncpy(cgi, mWwwrootDir, MAX_PATH);
App::AddSlash(cgi);
strcat(cgi,"\\");
strcat(cgi, szCgiBinName);
strcat(cgi, "\\");
MakeDir(cgi);
char exeName[MAX_PATH];
strncpy(exeName,mBinDir,MAX_PATH);
App::AddSlash(exeName);
strcat(exeName,"jWebServer.exe");
if( stricmp(EXE_NAME, exeName) != 0)
{
if( CopyFile(EXE_NAME,exeName,FALSE) == 0)
{
char str[MAX_PATH];
wsprintf(str,"Could not copy %s to %s.",EXE_NAME,exeName);
MessageBox(NULL, str, szAppName,MB_OK);
return;
}
}
CoInitialize(NULL);
CreateStartMenuLink(exeName);
CreateAutoStartLink(exeName);
CoUninitialize();
char s1[MAX_PATH];
strncpy(gConfigInfo.configPath, mBinDir, sizeof(gConfigInfo.configPath));
App::AddSlash(gConfigInfo.configPath);
strncpy(s1, gConfigInfo.configPath, sizeof(s1));
strcat(gConfigInfo.configPath, "jWebServer.ini");
char s2[MAX_PATH];
strncpy(s2, s1, sizeof(s2));
strcat(s2,"fileid.diz");
ResourceFileCopy(IBIN_FILEID_DIZ,s2);
gConfigInfo.mWwwRoot = mWwwrootDir;
gConfigInfo.mDefaultDoc = "index.html";
gConfigInfo.m_port = 80;
gConfigInfo.mAdminId = "admin";
gConfigInfo.mAdminPwd = "admin";
gConfigInfo.m_logs = false;
gConfigInfo.SaveConfig();
MessageBox(NULL,"jWebServer was successfully installed.",szAppName, MB_OK);
}
void Install::CreateAutoStartLink(const char* exeName)
{
if(!mAutoStart ) return;
char str[MAX_PATH];
ITEMIDLIST* lst;
SHGetSpecialFolderLocation(mDlg,CSIDL_COMMON_STARTUP,&lst);
if(lst == 0)
SHGetSpecialFolderLocation(mDlg,CSIDL_STARTUP,&lst);
if(lst == 0)
return;
SHGetPathFromIDList(lst,str);
LPMALLOC ma;
SHGetMalloc( &ma );
ma->Free(lst);
App::AddSlash(str);
strcat(str,"jWebServer.lnk");
if(CreateLink(exeName, str, szAppName) )
MessageBox(NULL,"Warning, could not create a link to autostart.", szAppName, MB_OK);
}
void Install::CreateStartMenuLink(const char* exeName)
{
if (!mStartMenu ) return;
char str[MAX_PATH];
ITEMIDLIST *lst;
SHGetSpecialFolderLocation(mDlg,CSIDL_PROGRAMS,&lst);
if(lst == 0)
return;
SHGetPathFromIDList(lst,str);
LPMALLOC ma;
SHGetMalloc( &ma );
ma->Free(lst);
App::AddSlash(str);
strcat(str,"jWebServer");
MakeDir(str);
strcat(str,"\\jWebServer.lnk");
if( CreateLink(exeName,str,szAppName) )
MessageBox(NULL,"Warning, could not create a link on the start menu.",szAppName,MB_OK);
}
void Install::ResourceFileCopy(unsigned long res,char *dest)
{
BYTE *byt;
unsigned long length;
web.GetResource(MAKEINTRESOURCE(res), length, byt, "BIN");
NtHandle fp("fp");
fp.mHandle = CreateFile(
dest,
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
DWORD dw;
WriteFile(fp.mHandle, byt,length, &dw, NULL);
}
void Install::MakeDir(char *str)
{
for (char* p = strchr(str,'\\'); p; p = strchr(p+1,'\\'))
{
*p=0;
CreateDirectory(str, NULL);
*p='\\';
}
CreateDirectory(str, NULL);
}
LRESULT WINAPI Install::Proc1(HWND hdlg, UINT msg, WPARAM wparam, LPARAM )
{
switch(msg)
{
case WM_INITDIALOG: This->SetHwnd(hdlg); break;
case WM_COMMAND:
switch( LOWORD(wparam) )
{
case IDCANCEL: This->OnCancel(wparam); return TRUE;
case IDOK: This->CloseDialog(wparam); return TRUE;
}
break;
}
return FALSE;
}
LRESULT WINAPI Install::Proc2(HWND hdlg, UINT msg, WPARAM wparam, LPARAM)
{
switch(msg)
{
case WM_INITDIALOG: This->OnInitDialog(hdlg); break;
case WM_COMMAND:
switch( LOWORD(wparam) )
{
case IDCANCEL: This->OnCancel(wparam); return TRUE;
case IDOK: This->OnOk(wparam); return TRUE;
case IDC_BROWSE1: This->OnBrowse1(); return TRUE;
case IDC_BROWSE2: This->OnBrowse2(); return TRUE;
}
break;
}
return FALSE;
}
void Install::SetHwnd(HWND hdlg)
{
mHwnd = hdlg;
}
void Install::OnInitDialog(HWND hdlg)
{
char str[MAX_PATH];
DWORD dw;
HKEY key;
SetHwnd(hdlg);
key = NULL;
RegOpenKey( HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion",&key);
dw=MAX_PATH;
RegQueryValueEx( key,"ProgramFilesDir",NULL,NULL,(BYTE*)str,&dw);
RegCloseKey(key);
App::AddSlash(str);
strcat(str,"jWebServer");
SetDlgItemText(mHwnd,IDC_JWEBDIR,str);
strcat(str,"\\wwwroot");
SetDlgItemText(mHwnd, IDC_JWEBHTML,str);
CheckDlgButton(mHwnd, IDC_STARTMENU,BST_CHECKED);
}
void Install::OnCancel(WPARAM wParam)
{
PostQuitMessage(1);
CloseDialog(wParam);
}
void Install::OnOk(WPARAM wParam)
{
GetDlgItemText(mHwnd,IDC_JWEBHTML, mWwwrootDir, MAX_PATH);
GetDlgItemText(mHwnd,IDC_JWEBDIR, mBinDir, MAX_PATH);
mStartMenu = !!IsDlgButtonChecked(mHwnd,IDC_STARTMENU);
mAutoStart = !!IsDlgButtonChecked(mHwnd,IDC_AUTORUN);
CloseDialog(wParam);
}
void Install::CloseDialog(WPARAM wParam)
{
EndDialog(mHwnd, LOWORD(wParam));
}
void Install::OnBrowse1()
{
OnBrowse("Select where to install jWebServer", IDC_JWEBDIR);
}
void Install::OnBrowse2()
{
OnBrowse("Select where the HTML files will be kept", IDC_JWEBHTML);
}
void Install::OnBrowse(const char* title, int resourceid)
{
ITEMIDLIST *lst;
LPMALLOC ma;
BROWSEINFO bi;
char str[MAX_PATH];
bi.hwndOwner = mHwnd;
bi.pidlRoot=NULL;
bi.pszDisplayName=str;
bi.lpszTitle="Select where to install jWebServer";
bi.ulFlags=0;
bi.lpfn=NULL;
bi.lParam=0;
bi.iImage=0;
lst = SHBrowseForFolder( &bi);
if(lst!=NULL)
{
SHGetPathFromIDList(lst,str);
SHGetMalloc( &ma );
ma->Free(lst);
SetDlgItemText(mHwnd, resourceid, str);
}
}
// CreateLink - uses the shell's IShellLink and IPersistFile interfaces
// to create and store a shortcut to the specified object.
// Returns the result of calling the member functions of the interfaces.
// lpszPathObj - address of a buffer containing the path of the object.
// lpszPathLink - address of a buffer containing the path where the
// shell link is to be stored.
// lpszDesc - address of a buffer containing the description of the
// shell link.
HRESULT Install::CreateLink(LPCSTR lpszPathObj, LPSTR lpszPathLink, LPCSTR lpszDesc)
{
// Get a pointer to the IShellLink interface.
IShellLink* psl;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
if (FAILED(hres))
return hres;
// Set the path to the shortcut target and add the
// description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
IPersistFile* ppf;
hres = psl->QueryInterface( IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hres))
{
// Ensure that the string is ANSI.
WORD wsz[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, (LPWSTR)wsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save( (LPWSTR)wsz, TRUE);
ppf->Release();
}
psl->Release();
return hres;
}
|
|
|
#pragma once
class Install
{
public:
Install(HINSTANCE inst, HWND dlg);
void Run(void);
Install();
private:
void MakeDir(char *str);
void ResourceFileCopy(unsigned long res,char *dest);
void CreateStartMenuLink(const char* exeName);
void CreateAutoStartLink(const char* exeName);
HRESULT CreateLink(LPCSTR lpszPathObj, LPSTR lpszPathLink, LPCSTR lpszDesc);
void OnInitDialog(HWND hdlg);
void OnCancel(WPARAM wParam);
void OnOk(WPARAM wParam);
void OnBrowse1();
void OnBrowse2();
void OnBrowse(const char* title, int resourceid);
void CloseDialog(WPARAM wParam);
void SetHwnd(HWND hdlg);
static LRESULT WINAPI Proc1(HWND hdlg, UINT msg, WPARAM wparam, LPARAM );
static LRESULT WINAPI Proc2(HWND hdlg, UINT msg, WPARAM wparam, LPARAM);
char mWwwrootDir[MAX_PATH];
char mBinDir[MAX_PATH];
bool mStartMenu;
bool mAutoStart;
HWND mHwnd;
HWND mDlg;
HINSTANCE mInstance;
} ;
|
|
|
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "common.h"
#include "App.h"
#include "ConfigInfo.h"
//globals
const char* szAppName ="jWebServer V0.1";// The name of the application
const char* szServerVersion ="jWebServer/0.1";// The version string used in responses
const char* szCgiBinName = "cgi-bin";
static App localWeb;
App& web = localWeb;
static ConfigInfo localConfigInfo;
ConfigInfo& gConfigInfo = localConfigInfo;
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
//jaa: allow multiple instances
// h = CreateMutex(NULL,TRUE,szAppName);
// if(GetLastError()==ERROR_ALREADY_EXISTS)
// return 0;
web.Create(hInst);
MSG msg;
while (GetMessage( &msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
web.CleanUp();
//jaa: allow multiple instances
// CloseHandle(h);
return 0;
}
|
|
|
#pragma once
class NtHandle
{
public:
HANDLE mHandle;
char mId[50];
NtHandle(char* id)
: mHandle(INVALID_HANDLE_VALUE)
{
strcpy(mId, id);
}
~NtHandle()
{
if (mHandle != INVALID_HANDLE_VALUE)
CloseHandle(mHandle);
mHandle = INVALID_HANDLE_VALUE;
}
private:
// NtHandle();
} ;
class NtFindHandle
{
public:
HANDLE mHandle;
char mId[50];
NtFindHandle(char* id)
: mHandle(INVALID_HANDLE_VALUE)
{
strcpy(mId, id);
}
~NtFindHandle()
{
if (mHandle != INVALID_HANDLE_VALUE)
FindClose(mHandle);
mHandle = INVALID_HANDLE_VALUE;
}
private:
//NtHandle();
} ;
|
|
|
#pragma warning(disable: 4786)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <algorithm>
using std::for_each;
#include "common.h"
#include "App.h"
#include "resource.h"
#include "Request.h"
#include "NtHandle.h"
#include "ConfigInfo.h"
#include "DirLister.h"
#include "HtmlDirGen.h"
Request::Request()
{
m_query=NULL;
}
void Request::Get(char *path)
{
WIN32_FIND_DATA ff;
char *back;
URLDecode(path);
if(*path=='/')
path++;
if( StartsWith(path,"admin") )
{
Admin(path+5);
return;
}
strncpy(m_fileRequest,gConfigInfo.mWwwRoot.c_str(),MAX_PATH);
App::AddSlash( m_fileRequest );
strcat(m_fileRequest,path);
SwapChar(m_fileRequest,'/','\\');
// Prevent using .. to get to previous directory
m_query=strchr(m_fileRequest,'?');
if(m_query != 0)
*(m_query++) = 0;
if(strstr(m_fileRequest,"..") != 0 || strstr(m_fileRequest,"*") != 0 )
{
Error(403);
return;
}
if( gConfigInfo.m_cgi && StartsWith(path,"cgi-bin") )
{
if( Cgi(path+7) )
return;
}
NtFindHandle h("h");
h.mHandle =FindFirstFile(m_fileRequest,&ff);
if(h.mHandle !=INVALID_HANDLE_VALUE)
{
if(ff.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
if(m_fileRequest[strlen(m_fileRequest)-1] != '\\')
{
strcat(m_fileRequest,"\\");
GenMovedPermanentlyPage(path);
return;
}
}
}
if(m_fileRequest[strlen(m_fileRequest)-1]=='\\')
{
back = m_fileRequest+strlen(m_fileRequest);
strcat(m_fileRequest, gConfigInfo.mDefaultDoc.c_str());
NtHandle h("h2");
h.mHandle =FindFirstFile(m_fileRequest,&ff);
if(h.mHandle == INVALID_HANDLE_VALUE)
{
*back=0;
App::AddSlash(m_fileRequest);
}
}
}
void Request::Admin(char *path)
{
if(*path=='/')
path++;
CharUpperBuff(path, strlen(path));
if(StartsWith(path,"LOGIN.HTML") )
HandleLogin();
else if(StartsWith(path,"CHANGE.HTML") )
HandleChange();
else if(StartsWith(path,"DELMIME.HTML") )
HandleMimeDelete();
else if(StartsWith(path,"CHANGEMIME.HTML") )
HandleMimeChange();
else if(StartsWith(path,"DELSCRIPT.HTML") )
HandleScriptDelete();
else if(StartsWith(path,"CHANGESCRIPT.HTML") )
HandleScriptChange();
else if (!stricmp(path,"SINFO.HTML") )
SendResource(MAKEINTRESOURCE(IWD_SINFO_HTML),"HTML");
else if(!stricmp(path,"VERSION.HTML") )
SendResource(MAKEINTRESOURCE(IWD_VERSION_HTML),"HTML");
else if(!stricmp(path,"INDEX.HTML") || !*path)
SendResource(MAKEINTRESOURCE(IWD_INDEX_HTML),"HTML");
else if(!stricmp(path,"LICENSE.HTML") )
SendResource(MAKEINTRESOURCE(IWD_LICENSE_HTML),"HTML");
else if(!stricmp(path,"TECH.HTML") )
SendResource(MAKEINTRESOURCE(IWD_TECH_HTML),"HTML");
else if(!stricmp(path,"FAQ.HTML") )
SendResource(MAKEINTRESOURCE(IWD_FAQ_HTML),"HTML");
else if(!stricmp(path,"ADDRESS.HTML") )
SendResource(MAKEINTRESOURCE(IWD_ADDRESS_HTML),"HTML");
else if(!stricmp(path,"MINFO.HTML") )
SendResource(MAKEINTRESOURCE(IWD_MINFO_HTML),"HTML");
else if(!stricmp(path,"FILES.HTML") )
SendResource(MAKEINTRESOURCE(IWD_FILES_HTML),"HTML");
else if(!stricmp(path,"CONFIG.HTML") )
SendResource(MAKEINTRESOURCE(IWD_CONFIG_HTML),"HTML");
else if(!stricmp(path,"QUICK.HTML") )
SendResource(MAKEINTRESOURCE(IWD_QUICK_HTML),"HTML");
else if(!stricmp(path,"ABOUT.HTML") )
SendResource(MAKEINTRESOURCE(IWD_ABOUT_HTML),"HTML");
else
Error(404);
}
void Request::HandleChange(void)
{
gConfigInfo.m_logs=false;
gConfigInfo.m_list=false;
gConfigInfo.m_cgi=false;
string id;
string pw;
string newid;
string newpw;
string action;
string name;
string value;
while( Parse(name, value) )
{
if(name == "AID")
id = value;
else if (name == "APW")
pw = value;
else if(name == "ACTION")
action = value;
else if(name == "ID")
newid = value;
else if(name == "PW")
newpw = value;
else if(name == "SITE")
gConfigInfo.mSiteName = value;
else if(name == "PORT")
gConfigInfo.m_port=atoi(value.c_str());
else if(name == "ROOT")
gConfigInfo.mWwwRoot = value;
else if(name == "DEF")
gConfigInfo.mDefaultDoc = value;
else if(name == "LOG")
gConfigInfo.m_logs = value =="on";
else if(name == "LIST")
gConfigInfo.m_list = value =="on";
else if(name == "CGI")
gConfigInfo.m_cgi = value =="on";
}
if (LoginFailed(id, pw))
return;
if(action == "MIME")
{
HandleMime();
return;
}
if(action == "SCRIPT")
{
HandleScript();
return;
}
gConfigInfo.mAdminId = newid;
gConfigInfo.mAdminPwd = newpw;
gConfigInfo.SaveConfig();
mPageGen.ConfirmationPage("Changes Saved", "Restart the server if you changed the port (click stop and then start).", false);
}
void Request::HandleLogin(void)
{
char *ptr=NULL;
string id;
string pw;
string name;
string value;
while(Parse(name, value))
{
if(name == "ID")
id = value;
else if(name == "PW")
pw = value;
}
if (LoginFailed(id, pw))
return;
GenMainConfigPage();
}
void Request::HandleMime(void)
{
mPageGen.ConfigPage(HtmlPageGen::Mime, "MIME Type Configuration",
"Mime types indicate the kind of file being sent to a web browser. "
"Web browsers recognize standard mime tags and display files depending on the type. "
"You can associate a MIME tag with a file extension using this page.",
"/admin/changemime.html", "Add/Change a MIME mapping", "Mime Mapping",
"/admin/delmime.html", "Delete a MIME Mapping"
);
}
void Request::HandleMimeChange(void)
{
string id;
string pw;
string ext;
string tag;
string name;
string value;
while(Parse(name, value))
{
if(name == "AID")
id = value;
else if(name == "APW")
pw = value;
else if(name == "EXT")
ext = value;
else if(name == "TAG")
tag = value;
}
if (LoginFailed(id, pw))
return;
if(!ext.empty() && !tag.empty())
gConfigInfo.AddMime(ext,tag);
gConfigInfo.SaveConfig();
mPageGen.ConfirmationPage("Mime Changes Made", "The MIME changes you requested have been made.");
}
void Request::HandleMimeDelete(void)
{
string id;
string pw;
string ext;
string name;
string value;
while( Parse(name, value) )
{
if(name == "AID")
id = value;
else if(name == "APW")
pw = value;
else if(name == "EXT")
ext = value;
}
if (LoginFailed(id, pw))
return;
if (!ext.empty())
gConfigInfo.DelMime(ext);
gConfigInfo.SaveConfig();
mPageGen.ConfirmationPage("Mime Tag Deleted", "The MIME tag has been deleted.");
}
void Request::HandleScript(void)
{
mPageGen.ConfigPage(HtmlPageGen::Script, "Script Configuration",
"Indicate which script engine to run for file extensions in your cgi-bin directory.",
"/admin/changescript.html", "Add/Change a Script Mapping", "Script Engine (full path)",
"/admin/delscript.html", "Delete a Script Mapping"
);
}
void Request::HandleScriptChange(void)
{
string id;
string pw;
string ext;
string tag;
string value;
string name;
while(Parse(name, value))
{
if(name == "AID")
id = value;
else if(name == "APW")
pw = value;
else if(name == "EXT")
ext = value;
else if(name == "TAG")
tag = value;
}
if (LoginFailed(id, pw))
return;
if (!ext.empty() && !tag.empty())
gConfigInfo.AddScript(ext,tag);
gConfigInfo.SaveConfig();
mPageGen.ConfirmationPage("Script Changes Made", "The script changes have been made.");
}
void Request::HandleScriptDelete()
{
string id;
string pw;
string ext;
string name;
string value;
while( Parse(name, value) )
{
if(name == "AID")
id = value;
else if(name == "APW")
pw = value;
else if(name == "EXT")
ext = value;
}
if (LoginFailed(id, pw))
return;
if(!ext.empty())
gConfigInfo.DelScript(ext);
gConfigInfo.SaveConfig();
mPageGen.ConfirmationPage("Script Tag Deleted", "The script tag has been deleted.");
}
void Request::GenerateMime(char *e,char *buffer)
{
char tag[80];
gConfigInfo.GetMime(e, tag);
strncpy(buffer,"Content-Type: ",80);
strcat(buffer,tag);
}
void Request::LogRequest()
{
char buffer[4096];
char path[256];
if(!gConfigInfo.m_logs)
return;
GetCurrentDirectory(256,path);
if( path[strlen(path)-1]!='\\')
strcat(path,"\\");
strcat(path,"access.log");
NtHandle fp("fp");
fp.mHandle = CreateFile(
path,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS ,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if(fp.mHandle ==INVALID_HANDLE_VALUE)
return;
//format:
// 000.000.000.000 - - [dd/mmm/yyyy:hh:mm:ss -0400] "GET / HTTP/1.0" 200 361
unsigned char a,b,c,d;
char adj[20];
DWORD dw;
SYSTEMTIME st;
TIME_ZONE_INFORMATION tz;
int bias;
char *month[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
GetTimeZoneInformation(&tz);
GetLocalTime(&st);
Socket::Long2IP(m_requestBy,&a,&b,&c,&d);
SetFilePointer(fp.mHandle,0,0,FILE_END);
bias=tz.Bias;
if(bias<0)
bias=-bias;
wsprintf(buffer,"%d.%d.%d.%d - - [%02d/%s/%d:%02d:%02d:%02d %c%04d] \"%s %s\" ",a,b,c,d,
st.wDay,month[st.wMonth-1],st.wYear,st.wHour,st.wMinute,st.wSecond,tz.Bias<0?'-':'+',bias,
m_verb, m_request);
if(*m_errorText)
wsprintf(adj,"%d %ld\r\n",atol(m_errorText+9),mStrOut.GetLength());
else
wsprintf(adj,"%d %ld\r\n",100, mOut.GetBytesSent());
strcat(buffer,adj);
WriteFile(fp.mHandle,buffer,strlen(buffer),&dw,NULL);
}
void Request::FileList(void)
{
if(!gConfigInfo.m_list)
{
Error(403);
return;
}
mOut.WriteHeader();
mOut.WriteHtmlContentType();
mOut.WriteEndOfHeaders();
HtmlDirGen gen(mOut);
gen.Gen(m_fileRequest);
m_done = true;
}
void Request::GenMainConfigPage()
{
mPageGen.MainPage(web.GetPort());
}
bool Request::LoginFailed(const string& id, const string& pw)
{
if (gConfigInfo.mAdminPwd.empty())
return false;
int val =0;
if (pw == gConfigInfo.mAdminPwd)
val++;
if(id == gConfigInfo.mAdminId)
val++;
if(val ==2)
return false;
gConfigInfo.LoadConfig();
mPageGen.ConfirmationPage("Login Failed", "Invalid user name or password", false);
return true;
}
void Request::GenMovedPermanentlyPage(const string& newpath)
{
mOut.WriteMovePermanently();
mOut.WriteDate();
mOut.WriteServerVersion();
mOut.Write("Location: ");
mOut.Write(newpath);
mOut.Writeln("/");
mOut.Writeln("Keep-Alive: timeout=15, max=100");
mOut.WriteHtmlContentType();
mOut.WriteEndOfHeaders();
mOut.HTML();
mOut.HEAD();
mOut.TITLE("301 Moved Permanently");
mOut.CloseTag();//head
mOut.BODY();
mOut.H1("Moved Permanently");
mOut.Write("The document has moved ");
mOut.A(newpath, "here");
mOut.BR();
mOut.CloseAllTags();
}
|
|
|
#pragma once
#include "HttpRequest.h"
class Request:public HttpRequest
{
public:
Request();
protected:
void Get(char *path);
void Admin(char *path);
bool Cgi(char *path);
void HandleLogin(void);
void HandleChange(void);
void HandleMime(void);
bool LoginFailed(const string& id, const string& pw);
void GenerateMime(char *e,char *buffer);
void HandleMimeChange(void);
void HandleMimeDelete(void);
void HandleScriptChange(void);
void HandleScriptDelete(void);
void LogRequest(void);
void FileList(void);
void HandleScript(void);
void GenMainConfigPage();
void GenMovedPermanentlyPage(const string& newpath);
char *m_query;
};
|
|
|
#include <winsock2.h>
#include "Socket.h"
class Socket::Private
{
public:
Private()
: mSocket(0)
{
}
SOCKET mSocket;
HWND m_hwnd;
} ;
Socket::Socket()
: impl(* new Socket::Private())
{
}
Socket::Socket(unsigned int s)
: impl(* new Socket::Private())
{
impl.mSocket = s;
}
Socket::~Socket()
{
delete &impl;
}
bool Socket::IsInvalid()
{
return impl.mSocket == INVALID_SOCKET;
}
bool Socket::IsAddressInUse()
{
return WSAGetLastError () != WSAEADDRINUSE;
}
bool Socket::IsError(int err)
{
return err == SOCKET_ERROR;
}
bool Socket::IsEqual(const Socket& other)
{
return impl.mSocket == other.impl.mSocket;
}
void Socket::CreateListener()
{
impl.mSocket = socket(AF_INET, SOCK_STREAM, 0);
}
void Socket::Close()
{
if (impl.mSocket != 0)
{
closesocket(impl.mSocket);
impl.mSocket = 0;
}
}
void Socket::SetNonBlockingMode(HWND hwnd)
{
WSAAsyncSelect(impl.mSocket, hwnd, 0, 0);
unsigned long ul =0;
ioctlsocket(impl.mSocket, FIONBIO, &ul);
}
void Socket::AsyncClose(HWND hwnd)
{
WSAAsyncSelect(impl.mSocket, hwnd, WM_USER, FD_CLOSE);
}
void Socket::AsyncCloseOrAccept(HWND hwnd)
{
WSAAsyncSelect(impl.mSocket, hwnd, WM_USER, FD_CLOSE|FD_ACCEPT);
}
void Socket::Skip(int n)
{
char* buffer = new char[n+1];
recv(impl.mSocket, buffer, n, 0);
delete[] buffer;
}
unsigned long Socket::Recv(char* buffer, unsigned long bufsize)
{
return recv(impl.mSocket, buffer, bufsize,0);
}
unsigned long Socket::Send(const char* buffer, unsigned long bytestosend)
{
return send(impl.mSocket, buffer, bytestosend, 0);
}
void Socket::ShutDown()
{
shutdown(impl.mSocket, SD_SEND);
}
Socket Socket::Accept(unsigned long& addr, unsigned long& port)
{
struct sockaddr_in remote;
int dw = sizeof(remote);
remote.sin_family = AF_INET;
SOCKET s = accept(impl.mSocket, (struct sockaddr *)&remote, &dw );
addr = IP2Long(remote.sin_addr.S_un.S_un_b.s_b1,
remote.sin_addr.S_un.S_un_b.s_b2,
remote.sin_addr.S_un.S_un_b.s_b3,
remote.sin_addr.S_un.S_un_b.s_b4);
port = remote.sin_port;
return Socket(s);
}
Socket& Socket::operator=(const Socket& other)
{
impl.mSocket = other.impl.mSocket;
return *this;
}
int Socket::Bind(unsigned long portno)
{
SOCKADDR_IN localAddr;
memset(&localAddr,0,sizeof(localAddr) );
localAddr.sin_port = htons ((u_short) portno);
localAddr.sin_family = AF_INET;
return bind (impl.mSocket, (PSOCKADDR) &localAddr, sizeof (localAddr));
}
int Socket::Listen(int n)
{
return listen(impl.mSocket, n);
}
const char* Socket::GetLastErrorDesc()
{
switch(WSAGetLastError())
{
case WSANOTINITIALISED: return "Could not start server. WSAStartup not called.";
case WSAENETDOWN: return "Could not start server. The network subsystem failed.";
case WSAEAFNOSUPPORT: return "Could not start server. Address family not supported.";
case WSAEINPROGRESS: return "Could not start server. Still processing a call.";
case WSAEMFILE: return "Could not start server. No more socket descriptors available.";
case WSAENOBUFS: return "Could not start server. No buffer available.";
case WSAEPROTONOSUPPORT: return "Could not start server. Protocol is not supported.";
case WSAEPROTOTYPE: return "Could not start server. The wrong protocol for this socket.";
case WSAESOCKTNOSUPPORT: return "Could not start server. Unsupported socket type for this address family.";
default: return "Could not start server.";
}
}
void Socket::Long2IP(unsigned long l,unsigned char *b1,unsigned char *b2,unsigned char *b3,unsigned char *b4)
{
*b4=(unsigned char)(l&0xff);
*b3=(unsigned char)((l&0xff00)/0x100);
*b2=(unsigned char)((l&0xff0000)/0x10000);
*b1=(unsigned char)((l&0xff000000)/0x1000000);
}
unsigned long Socket::IP2Long(unsigned char b1,unsigned char b2,unsigned char b3,unsigned char b4)
{
unsigned long rtn;
rtn=b4+(b3*0x100)+(b2*0x10000)+(b1*0x1000000);
return rtn;
}
void Socket::TermEnvironment()
{
WSACleanup();
}
bool Socket::InitEnvironment()
{
WSADATA WsaData;
int err = WSAStartup (0x0101, &WsaData);
return err != SOCKET_ERROR;
}
|
|
|
#pragma once
class Socket
{
public:
Socket();
explicit Socket(unsigned int s);
~Socket();
Socket Accept(unsigned long& addr, unsigned long& port);
int Listen(int n);
int Bind(unsigned long portno);
bool IsInvalid();
bool IsEqual(const Socket& other);
void CreateListener();
void Close();
void SetNonBlockingMode(HWND hwnd);
void AsyncClose(HWND hwnd);
void AsyncCloseOrAccept(HWND hwnd);
void Skip(int n);
unsigned long Recv(char* buffer, unsigned long bufsize);
unsigned long Send(const char* buffer, unsigned long bytestosend);
inline unsigned long Send(const unsigned char* buffer, unsigned long bytestosend)
{
return Send((const char*) buffer, bytestosend);
}
void ShutDown();
bool IsAddressInUse();
bool IsError(int err);
Socket& operator=(const Socket& other);
const char* GetLastErrorDesc();
static void Long2IP(unsigned long l,unsigned char *b1,unsigned char *b2,unsigned char *b3,unsigned char *b4);
static void TermEnvironment();
static bool InitEnvironment();
private:
unsigned long IP2Long(unsigned char b1,unsigned char b2,unsigned char b3,unsigned char b4);
class Private;
Private& impl;
} ;
|