/*
 *	Module: 		wssoup.cpp
 *	Author:			TANAKA Goh <goh@yamato.ibm.co.jp>
 *	Date:			1995/07/07
 *	Description:	Realize part of wssoup class.
 *					This class read/write WSSoup data
 */

#include <windows.h>
#include <windowsx.h>
#include <errno.h>
#include <fstream.h>
#include <io.h>
#include <iostream.h>
#include <strstrea.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "wssoup.h"
#include "resource.h"

/* This is for NT */
#ifdef _WIN32
extern HANDLE		dll_module_handle;
#define	GENSOCK_EXPORT

/* This is for WIN16 */
#else
extern HINSTANCE	dll_module_handle;
#define	GENSOCK_EXPORT	_export
#endif

//
// wssoup_areas class
//

wssoup_areas::wssoup_areas(void)
{
	filename = NULL;
	group = NULL;
	memset(encoding, 0, sizeof(encoding));
}

wssoup_areas::wssoup_areas(char* filename, char* group, char* encoding)
{
	if (filename) {
		wssoup_areas::filename = new char[strlen(filename) + 1];
		
		if (wssoup_areas::filename) {
			strcpy(wssoup_areas::filename, filename);
		}
	} else {
		wssoup_areas::filename = NULL;
	}
	
	if (group) {
		wssoup_areas::group = new char[strlen(group) + 1];
		
		if (wssoup_areas::group) {
			strcpy(wssoup_areas::group, group);
		}
	} else {
		wssoup_areas::group = NULL;
	}
	
	if (encoding) {
		strncpy(wssoup_areas::encoding, encoding, sizeof(wssoup_areas::encoding) - 1);
	} else {
		memset(wssoup_areas::encoding, 0, sizeof(wssoup_areas::encoding));
	}
}

wssoup_areas::~wssoup_areas(void)
{
	if (filename) {
		delete [] filename;
	}
	
	if (group) {
		delete [] group;
	}
}

void wssoup_areas::put_filename(char* filename)
{
	if (wssoup_areas::filename) {
		delete [] wssoup_areas::filename;
	}
	
	if (filename) {
		wssoup_areas::filename = new char[strlen(filename) + 1];
		
		if (wssoup_areas::filename) {
			strcpy(wssoup_areas::filename, filename);
		}
	}
}

char* wssoup_areas::get_filename(void)
{
	return filename;
}

void wssoup_areas::put_group(char* group)
{
	if (wssoup_areas::group) {
		delete [] wssoup_areas::group;
	}
	
	if (group) {
		wssoup_areas::group = new char[strlen(group) + 1];
		
		if (wssoup_areas::group) {
			strcpy(wssoup_areas::group, group);
		}
	}
}

char* wssoup_areas::get_group(void)
{
	return group;
}

void wssoup_areas::put_encoding(char* encoding)
{
	if (encoding) {
		strncpy(wssoup_areas::encoding, encoding, sizeof(wssoup_areas::encoding) - 1);
	} else {
		memset(wssoup_areas::encoding, 0, sizeof(wssoup_areas::encoding));
	}
}

char* wssoup_areas::get_encoding(void)
{
	return encoding;
}

typedef int (*COMPARE_WSSOUP_AREAS)(const void*, const void*);

int compare_wssoup_areas_group(wssoup_areas** a, wssoup_areas** b)
{
	return strcmp((*a)->group, (*b)->group);
}

//
// wssoup_areas_table class
//

wssoup_areas_table::wssoup_areas_table(void)
{
	soup_areas = NULL;
	soup_areas_total = 0;
	rc = 0;
}

wssoup_areas_table::wssoup_areas_table(char* filename)
{
	soup_areas = NULL;
	soup_areas_total = 0;
	rc = 0;
	
	read_wssoup_areas(filename);
}

wssoup_areas_table::~wssoup_areas_table(void)
{
	for (unsigned long i = 0 ; i < soup_areas_total ; i++) {
		if (*(soup_areas + i)) {
			delete *(soup_areas + i);
		}
	}
	
	if (soup_areas) {
		GlobalFreePtr(soup_areas);
	}
}

wssoup_areas_table::operator int()
{
	return rc;
}

void wssoup_areas_table::read_wssoup_areas(char* filename)
{
	for (unsigned long i = 0 ; i < soup_areas_total ; i++) {
		if (*(soup_areas + i)) {
			delete *(soup_areas + i);
		}
	}
	
	if (soup_areas) {
		GlobalFreePtr(soup_areas);
	}
	
	ifstream	areas(filename, ios::in | ios::nocreate | ios::binary);
	
	if (areas) {
		for ( ; ; ) {
			char	line[1024];
			
			areas.getline(line, sizeof(line));
			
			if (areas.eof()) {
				if (soup_areas_total) {
					rc = 1;
				} else {
					rc = 0;
				}
				
				break;
			}
			
			if (soup_areas_total) {
#ifdef _WIN32
				if ((soup_areas = (wssoup_areas**)GlobalReAllocPtr(soup_areas, sizeof(wssoup_areas*) * (soup_areas_total + 1), GMEM_MOVEABLE)) == NULL) {
#else
				if ((soup_areas = (wssoup_areas huge* huge*)GlobalReAllocPtr(soup_areas, sizeof(wssoup_areas*) * (soup_areas_total + 1), GMEM_MOVEABLE)) == NULL) {
#endif
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nGlobalReAllocPtr() has an error.", __LINE__);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					soup_areas_total = 0;
					rc = 0;
					break;
				}
			} else {
#ifdef _WIN32
				if ((soup_areas = (wssoup_areas**)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_areas*))) == NULL) {
#else
				if ((soup_areas = (wssoup_areas huge* huge*)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_areas*))) == NULL) {
#endif
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nGlobalAllocPtr() has an error.", __LINE__);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					soup_areas_total = 0;
					rc = 0;
					break;
				}
			}
			
			*(soup_areas + soup_areas_total) = new wssoup_areas();
			
			istrstream	areas_line(line);
			char		token[1024];
			
			areas_line.getline(token, sizeof(token), '\t');
			(*(soup_areas + soup_areas_total))->put_filename(token);
			areas_line.getline(token, sizeof(token), '\t');
			(*(soup_areas + soup_areas_total))->put_group(token);
			areas_line.getline(token, sizeof(token), '\t');
			(*(soup_areas + soup_areas_total))->put_encoding(token);
			
			soup_areas_total++;
		}
		
		if (soup_areas) {
			qsort((void *)soup_areas, (size_t)soup_areas_total, sizeof(wssoup_areas*), (COMPARE_WSSOUP_AREAS)compare_wssoup_areas_group);
		}
		
		areas.close();
	} else {
		char	error[256];
		
		sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, filename);
		MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
		soup_areas = NULL;
		soup_areas_total = 0;
		rc = 0;
	}
}

wssoup_areas** wssoup_areas_table::get_wssoup_areas(void)
{
	return (wssoup_areas**)soup_areas;
}

wssoup_areas** wssoup_areas_table::get_wssoup_areas(char* group)
{
	wssoup_areas	areas(NULL, group, NULL);
	wssoup_areas*	pareas = &areas;
	
	return (wssoup_areas**)bsearch((void *)&pareas, (void *)soup_areas, (size_t)soup_areas_total, sizeof(wssoup_areas*), (COMPARE_WSSOUP_AREAS)compare_wssoup_areas_group);
}

unsigned long wssoup_areas_table::get_wssoup_areas_total(void)
{
	return soup_areas_total;
}

//
// wssoup_index class
//

wssoup_index::wssoup_index(void)
{
	number = 0;
	subject = NULL;
	from = NULL;
	date = NULL;
	message_id = NULL;
	references = NULL;
	bytes = 0;
	lines = 0;
	offset = 0;
}

wssoup_index::wssoup_index(unsigned long number, char* subject = NULL, char* from = NULL, char* date = NULL, char* message_id = NULL, char* references = NULL, unsigned long bytes = 0, unsigned long lines = 0, unsigned long offset = 0)
{
	wssoup_index::number = number;
	
	if (subject) {
		wssoup_index::subject = new char[strlen(subject) + 1];
		
		if (wssoup_index::subject) {
			strcpy(wssoup_index::subject, subject);
		}
	} else {
		wssoup_index::subject = NULL;
	}
	
	if (from) {
		wssoup_index::from = new char[strlen(from) + 1];
		
		if (wssoup_index::from) {
			strcpy(wssoup_index::from, from);
		}
	} else {
		wssoup_index::from = NULL;
	}
	
	if (date) {
		wssoup_index::date = new char[strlen(date) + 1];
		
		if (wssoup_index::date) {
			strcpy(wssoup_index::date, date);
		}
	} else {
		wssoup_index::date = NULL;
	}
	
	if (message_id) {
		wssoup_index::message_id = new char[strlen(message_id) + 1];
		
		if (wssoup_index::message_id) {
			strcpy(wssoup_index::message_id, message_id);
		}
	} else {
		wssoup_index::message_id = NULL;
	}
	
	if (references) {
		wssoup_index::references = new char[strlen(references) + 1];
		
		if (wssoup_index::references) {
			strcpy(wssoup_index::references, references);
		}
	} else {
		wssoup_index::references = NULL;
	}
	
	wssoup_index::bytes = bytes;
	wssoup_index::lines = lines;
	wssoup_index::offset = offset;
}

wssoup_index::~wssoup_index(void)
{
	if (subject) {
		delete [] subject;
	}
	
	if (from) {
		delete [] from;
	}
	
	if (date) {
		delete [] date;
	}
	
	if (message_id) {
		delete [] message_id;
	}
	
	if (references) {
		delete [] references;
	}
}

void wssoup_index::put_number(unsigned long number)
{
	wssoup_index::number = number;
}

unsigned long wssoup_index::get_number(void)
{
	return number;
}

void wssoup_index::put_subject(char* subject)
{
	if (wssoup_index::subject) {
		delete [] wssoup_index::subject;
	}
	
	if (subject) {
		wssoup_index::subject = new char[strlen(subject) + 1];
		
		if (wssoup_index::subject) {
			strcpy(wssoup_index::subject, subject);
		}
	}
}

char* wssoup_index::get_subject(void)
{
	return subject;
}

void wssoup_index::put_from(char* from)
{
	if (wssoup_index::from) {
		delete [] wssoup_index::from;
	}
	
	if (from) {
		wssoup_index::from = new char[strlen(from) + 1];
		
		if (wssoup_index::from) {
			strcpy(wssoup_index::from, from);
		}
	}
}

char* wssoup_index::get_from(void)
{
	return from;
}

void wssoup_index::put_date(char* date)
{
	if (wssoup_index::date) {
		delete [] wssoup_index::date;
	}
	
	if (date) {
		wssoup_index::date = new char[strlen(date) + 1];
		
		if (wssoup_index::date) {
			strcpy(wssoup_index::date, date);
		}
	}
}

char* wssoup_index::get_date(void)
{
	return date;
}

void wssoup_index::put_message_id(char* message_id)
{
	if (wssoup_index::message_id) {
		delete [] wssoup_index::message_id;
	}
	
	if (message_id) {
		wssoup_index::message_id = new char[strlen(message_id) + 1];
		
		if (wssoup_index::message_id) {
			strcpy(wssoup_index::message_id, message_id);
		}
	}
}

char* wssoup_index::get_message_id(void)
{
	return message_id;
}

void wssoup_index::put_references(char* references)
{
	if (wssoup_index::references) {
		delete [] wssoup_index::references;
	}
	
	if (references) {
		wssoup_index::references = new char[strlen(references) + 1];
		
		if (wssoup_index::references) {
			strcpy(wssoup_index::references, references);
		}
	}
}

char* wssoup_index::get_references(void)
{
	return references;
}

void wssoup_index::put_bytes(unsigned long bytes)
{
	wssoup_index::bytes = bytes;
}

unsigned long wssoup_index::get_bytes(void)
{
	return bytes;
}

void wssoup_index::put_lines(unsigned long lines)
{
	wssoup_index::lines = lines;
}

unsigned long wssoup_index::get_lines(void)
{
	return lines;
}

void wssoup_index::put_offset(unsigned long offset)
{
	wssoup_index::offset = offset;
}

unsigned long wssoup_index::get_offset(void)
{
	return offset;
}

typedef int (*COMPARE_WSSOUP_INDEX)(const void*, const void*);

int compare_wssoup_index_number(wssoup_index** a, wssoup_index** b)
{
	if ((*a)->number > (*b)->number) {
		return 1;
	} else if ((*a)->number < (*b)->number) {
		return -1;
	} else {
		return 0;
	}
}

int compare_wssoup_index_message_id(wssoup_index** a, wssoup_index** b)
{
	return strcmp((*a)->message_id, (*b)->message_id);
}

//
// wssoup_index_table class
//

wssoup_index_table::wssoup_index_table(void)
{
	soup_index = NULL;
	soup_index_total_org = 0;
	soup_index_total = 0;
	rc = 0;
}

wssoup_index_table::wssoup_index_table(char* inbound, char* filename, char* encoding)
{
	soup_index = NULL;
	soup_index_total_org = 0;
	soup_index_total = 0;
	rc = 0;
	
	read_wssoup_index_table(inbound, filename, encoding);
}

wssoup_index_table::~wssoup_index_table(void)
{
	for (unsigned long i = 0 ; i < soup_index_total ; i++) {
		if (*(soup_index + i)) {
			delete *(soup_index + i);
		}
	}
	
	if (soup_index) {
		GlobalFreePtr(soup_index);
	}
}

wssoup_index_table::operator int()
{
	return rc;
}

void wssoup_index_table::read_wssoup_index_table(char* inbound, char* filename, char* encoding)
{
	for (unsigned long i = 0 ; i < soup_index_total ; i++) {
		if (*(soup_index + i)) {
			delete *(soup_index + i);
		}
	}
	
	if (soup_index) {
		GlobalFreePtr(soup_index);
	}
	
	switch (*encoding) {
		case 'u': {
			switch (*(encoding + 1)) {
				//case 'n': {
				//	break;
				//}
				
				case 'c': {
					char	index_filename[256];
					sprintf(index_filename, "%s%s.idx", inbound, filename);
					ifstream	index(index_filename, ios::in | ios::nocreate | ios::binary);
					
					if (index) {
						for ( ; ; ) {
							char			line[4096];
							unsigned long	index_offset = index.tellg();
							
							index.getline(line, sizeof(line));
							
							if (index.eof()) {
								if (soup_index_total) {
									rc = 1;
								} else {
									rc = 0;
								}
								
								break;
							}
							
							wssoup_index**	ppindex;
							char*			p = strrchr(line, '\t');
							unsigned long	number = atol(p + 1);
							
							if (ppindex = get_wssoup_index(number)) {
								soup_index_total_org++;
							} else {
								if (soup_index_total) {
#ifdef _WIN32
									if ((soup_index = (wssoup_index**)GlobalReAllocPtr(soup_index, sizeof(wssoup_index*) * (soup_index_total + 1), GMEM_MOVEABLE)) == NULL) {
#else
									if ((soup_index = (wssoup_index huge* huge*)GlobalReAllocPtr(soup_index, sizeof(wssoup_index*) * (soup_index_total + 1), GMEM_MOVEABLE)) == NULL) {
#endif
										char	error[256];
										
										sprintf(error, "wssoup.cpp(%d)\nGlobalReAllocPtr() has an error.", __LINE__);
										MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
										soup_index_total_org = 0;
										soup_index_total = 0;
										rc = 0;
										break;
									}
								} else {
#ifdef _WIN32
									if ((soup_index = (wssoup_index**)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_index*))) == NULL) {
#else
									if ((soup_index = (wssoup_index huge* huge*)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_index*))) == NULL) {
#endif
										char	error[256];
										
										sprintf(error, "wssoup.cpp(%d)\nGlobalAllocPtr() has an error.", __LINE__);
										MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
										soup_index_total_org = 0;
										soup_index_total = 0;
										rc = 0;
										break;
									}
								}
								
								*(soup_index + soup_index_total) = new wssoup_index();
								ppindex = (wssoup_index**)(soup_index + soup_index_total);
								soup_index_total_org++;
								soup_index_total++;
							}
							
							istrstream	index_line(line);
							char		token[1024];
							
							// Offset
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_offset(atol(token));
							
							// Subject
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_subject(token);
							
							// From
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_from(token);
							
							// Date
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_date(token);
							
							// Message-ID
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_message_id(token);
							
							// References
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_references(token);
							
							// Bytes
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_bytes(atol(token));
							
							// Lines
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_lines(atol(token));
							
							// Number
							index_line.getline(token, sizeof(token), '\t');
							(*ppindex)->put_number(atol(token));
						}
						
						if (soup_index) {
							qsort((void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
						}
						
						index.close();
					} else {
						char	error[256];
						
						sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, index_filename);
						MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						soup_index = NULL;
						soup_index_total_org = 0;
						soup_index_total = 0;
						rc = 0;
					}
					
					break;
				}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					soup_index = NULL;
					soup_index_total_org = 0;
					soup_index_total = 0;
					rc = 0;
					break;
				}
			}
			
			break;
		}
		
		//case 'm': {
		//	break;
		//}
		
		//case 'M': {
		//	break;
		//}
		
		case 'b': {
			switch (*(encoding + 1)) {
				case 'n': {
					char	message_filename[256];
					sprintf(message_filename, "%s%s.msg", inbound, filename);
					ifstream	message(message_filename, ios::in | ios::nocreate | ios::binary);
					
					if (message) {
						for ( ; ; ) {
							unsigned long	l;
							
							message.read((char*)&l, sizeof(long));
							l = MAKELONG(MAKEWORD(HIBYTE(HIWORD(l)),
												  LOBYTE(HIWORD(l))),
										 MAKEWORD(HIBYTE(LOWORD(l)),
												  LOBYTE(LOWORD(l))));
							
							if (message.eof()) {
								if (soup_index_total) {
									rc = 1;
								} else {
									rc = 0;
								}
								
								break;
							}
							
							if (soup_index_total) {
#ifdef _WIN32
								if ((soup_index = (wssoup_index**)GlobalReAllocPtr(soup_index, sizeof(wssoup_index*) * (soup_index_total + 1), GMEM_MOVEABLE)) == NULL) {
#else
								if ((soup_index = (wssoup_index huge* huge*)GlobalReAllocPtr(soup_index, sizeof(wssoup_index*) * (soup_index_total + 1), GMEM_MOVEABLE)) == NULL) {
#endif
									char	error[256];
									
									sprintf(error, "wssoup.cpp(%d)\nGlobalReAllocPtr() has an error.", __LINE__);
									MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
									soup_index_total_org = 0;
									soup_index_total = 0;
									rc = 0;
									break;
								}
							} else {
#ifdef _WIN32
								if ((soup_index = (wssoup_index**)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_index*))) == NULL) {
#else
								if ((soup_index = (wssoup_index huge* huge*)GlobalAllocPtr(GMEM_MOVEABLE, sizeof(wssoup_index*))) == NULL) {
#endif
									char	error[256];
									
									sprintf(error, "wssoup.cpp(%d)\nGlobalAllocPtr() has an error.", __LINE__);
									MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
									soup_index_total_org = 0;
									soup_index_total = 0;
									rc = 0;
									break;
								}
							}
							
							*(soup_index + soup_index_total) = new wssoup_index();
							wssoup_index**	ppindex = (wssoup_index**)(soup_index + soup_index_total);
							soup_index_total_org++;
							soup_index_total++;
							
							// Number
							(*ppindex)->put_number(soup_index_total);
							
							// Bytes
							(*ppindex)->put_bytes(l);
							
							// Offset
							(*ppindex)->put_offset(message.tellg());
							
							char				line[4096];
							char*				p = line;
							enum {HEADER, BODY}	article = HEADER;
							unsigned long		lines = 0;
							
							for (unsigned long i = 0 ; i < l ; i++) {
								int		c1 = message.get();
								
								if (article == HEADER) {
									int		c2 = message.peek();
									
									switch (c1) {
										case '\t':
											*p++ = ' ';
											break;
										
										case '\n':
											if (p == line) {
												article = BODY;
												break;
											}
											
											if (c2 != '\t' && c2 != ' ') {
												*p = 0;
												
												switch (*line) {
													case 'D':	case 'd':
														if (!strnicmp(line, "Date: ", 6)) {
															(*ppindex)->put_date(line + 6);
														}
														
														break;
													
													case 'F':	case 'f':
														if (!strnicmp(line, "From: ", 6)) {
															(*ppindex)->put_from(line + 6);
														}
														
														break;
													
													case 'L':	case 'l':
														if (!strnicmp(line, "Lines: ", 7)) {
															(*ppindex)->put_lines(atol(line + 7));
														}
														
														break;
													
													case 'M':	case 'm':
														if (!strnicmp(line, "Message-ID: ", 12)) {
															(*ppindex)->put_message_id(line + 12);
														}
														
														break;
													
													case 'R':	case 'r':
														if (!strnicmp(line, "References: ", 12)) {
															(*ppindex)->put_references(line + 12);
														}
														
														break;
													
													case 'S':	case 's':
														if (!strnicmp(line, "Subject: ", 9)) {
															(*ppindex)->put_subject(line + 9);
														}
														
														break;
												}
												
												p = line;
											}
											
											break;
										
										case '\r':
											break;
										
										default:
											*p++ = c1;
											break;
									}
								} else if ((*ppindex)->get_lines() == 0 && c1 == '\n') {
									lines++;
								}
							}
							
							if (lines) {
								(*ppindex)->put_lines(lines);
							}
						}
						
						if (soup_index) {
							qsort((void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
						}
						
						message.close();
					} else {
						char	error[256];
						
						sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, message_filename);
						MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						soup_index = NULL;
						soup_index_total_org = 0;
						soup_index_total = 0;
						rc = 0;
					}
					
					break;
				}
				
				//case 'c': {
				//	break;
				//}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					soup_index = NULL;
					soup_index_total_org = 0;
					soup_index_total = 0;
					rc = 0;
					break;
				}
			}
			
			break;
		}
		
		//case 'B': {
		//	break;
		//}
		
		//case 'i': {
		//	break;
		//}
		
		default: {
			char	error[256];
			
			sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
			MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
			soup_index = NULL;
			soup_index_total_org = 0;
			soup_index_total = 0;
			rc = 0;
			break;
		}
	}
	
	return;
}

void wssoup_index_table::write_wssoup_index_table(char* inbound, char* filename, char* encoding)
{
	switch (*encoding) {
		case 'u': {
			switch (*(encoding + 1)) {
				//case 'n': {
				//	break;
				//}
				
				case 'c': {
					time_t	t;
					
					sprintf(index_filename, "%s%s.idx", inbound, filename);
					index_org.open(index_filename, ios::in | ios::nocreate | ios::binary);
					
					sprintf(message_filename, "%s%s.msg", inbound, filename);
					message_org.open(message_filename, ios::in | ios::nocreate | ios::binary);
					
					time(&t);
					
					for ( ; ; t++) {
						sprintf(index_tmp_filename, "%s%08lx.idx", inbound, t);
						
						if (_access(index_tmp_filename, 0) && errno == ENOENT) {
							break;
						}
					}
					
					index_tmp.open(index_tmp_filename, ios::trunc | ios::out | ios::binary);
					
					for ( ; ; t++) {
						sprintf(message_tmp_filename, "%s%08lx.msg", inbound, t);
						
						if (_access(message_tmp_filename, 0) && errno == ENOENT) {
							break;
						}
					}
					
					message_tmp.open(message_tmp_filename, ios::trunc | ios::out | ios::binary);
					
					if (index_org && message_org && index_tmp && message_tmp) {
						for (unsigned long i = 0 ; i < soup_index_total ; i++) {
							wssoup_index*	pindex = *(soup_index + i);
							char			line[4096];
							
							message_org.seekg(pindex->get_offset());
							
							if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								index_org.close();
								message_org.close();
								index_tmp.close();
								message_tmp.close();
								remove(index_tmp_filename);
								remove(message_tmp_filename);
								return;
							}
							
							sprintf(line, "#! rnews %08lu\n", pindex->get_bytes());
							message_tmp.write(line, strlen(line));
							sprintf(line,
									"%lu\t%s\t%s\t%s\t%s\t%s\t%lu\t%lu\t%lu\n",
									message_tmp.tellp(),
									pindex->get_subject(),
									pindex->get_from(),
									pindex->get_date(),
									pindex->get_message_id(),
									pindex->get_references(),
									pindex->get_bytes(),
									pindex->get_lines(),
									pindex->get_number());
							index_tmp.write(line, strlen(line));
							
							if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								index_org.close();
								message_org.close();
								index_tmp.close();
								message_tmp.close();
								remove(index_tmp_filename);
								remove(message_tmp_filename);
								return;
							}
							
							for (unsigned long j = 0 ; j < pindex->get_bytes() ; j++) {
								message_tmp.put((char)message_org.get());
								
								if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
									char	error[256];
									
									sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
									MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
									index_org.close();
									message_org.close();
									index_tmp.close();
									message_tmp.close();
									remove(index_tmp_filename);
									remove(message_tmp_filename);
									return;
								}
							}
						}
						
						index_org.close();
						message_org.close();
						index_tmp.close();
						message_tmp.close();
						
						remove(index_filename);
						
						if (rename(index_tmp_filename, index_filename)) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							return;
						}
						
						remove(message_filename);
						
						if (rename(message_tmp_filename, message_filename)) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							return;
						}
						
						soup_index_total_org = soup_index_total;
					} else {
						char	error[256];
						
						if (!index_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, index_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else if (!message_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, message_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else {
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						}
						
						if (index_org) {
							index_org.close();
						}
						
						if (message_org) {
							message_org.close();
						}
						
						if (index_tmp) {
							index_tmp.close();
							remove(index_tmp_filename);
						}
						
						if (message_tmp) {
							message_tmp.close();
							remove(message_tmp_filename);
						}
					}
					
					break;
				}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					return;
				}
			}
			
			break;
		}
		
		//case 'm': {
		//	break;
		//}
		
		//case 'M': {
		//	break;
		//}
		
		case 'b': {
			switch (*(encoding + 1)) {
				case 'n': {
					time_t	t;
					
					sprintf(message_filename, "%s%s.msg", inbound, filename);
					message_org.open(message_filename, ios::in | ios::nocreate | ios::binary);
					
					time(&t);
					
					for ( ; ; t++) {
						sprintf(message_tmp_filename, "%s%08lx.msg", inbound, t);
						
						if (_access(message_tmp_filename, 0) && errno == ENOENT) {
							break;
						}
					}
					
					message_tmp.open(message_tmp_filename, ios::trunc | ios::out | ios::binary);
					
					if (message_org && message_tmp) {
						for (unsigned long i = 0 ; i < soup_index_total ; i++) {
							wssoup_index*	pindex = *(soup_index + i);
							
							message_org.seekg(pindex->get_offset());
							
							if (message_org.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								message_org.close();
								message_tmp.close();
								remove(message_tmp_filename);
								return;
							}
							
							unsigned long	l = pindex->get_bytes();
							l = MAKELONG(MAKEWORD(HIBYTE(HIWORD(l)),
												  LOBYTE(HIWORD(l))),
										 MAKEWORD(HIBYTE(LOWORD(l)),
												  LOBYTE(LOWORD(l))));
							message_tmp.write((const char*)&l, sizeof(long));
							
							if (message_org.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								message_org.close();
								message_tmp.close();
								remove(message_tmp_filename);
								return;
							}
							
							for (unsigned long j = 0 ; j < pindex->get_bytes() ; j++) {
								message_tmp.put((char)message_org.get());
								
								if (message_org.fail() || message_tmp.fail()) {
									char	error[256];
									
									sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
									MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
									message_org.close();
									message_tmp.close();
									remove(message_tmp_filename);
									return;
								}
							}
						}
						
						message_org.close();
						message_tmp.close();
						
						remove(message_filename);
						
						if (rename(message_tmp_filename, message_filename)) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							return;
						}
						
						soup_index_total_org = soup_index_total;
					} else {
						char	error[256];
						
						if (!message_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, message_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else {
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						}
						
						if (message_org) {
							message_org.close();
						}
						
						if (message_tmp) {
							message_tmp.close();
							remove(message_tmp_filename);
						}
					}
					
					break;
				}
				
				//case 'c': {
				//	break;
				//}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					return;
				}
			}
			
			break;
		}
		
		//case 'B': {
		//	break;
		//}
		
		//case 'i': {
		//	break;
		//}
		
		default: {
			char	error[256];
			
			sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
			MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
			return;
		}
	}
	
	return;
}

int wssoup_index_table::write_wssoup_index(char* inbound, char* filename, char* encoding, unsigned long i)
{
	switch (*encoding) {
		case 'u': {
			switch (*(encoding + 1)) {
				//case 'n': {
				//	break;
				//}
				
				case 'c': {
					if (i == 0) {
						time_t	t;
						
						sprintf(index_filename, "%s%s.idx", inbound, filename);
						index_org.open(index_filename, ios::in | ios::nocreate | ios::binary);
						
						sprintf(message_filename, "%s%s.msg", inbound, filename);
						message_org.open(message_filename, ios::in | ios::nocreate | ios::binary);
						
						time(&t);
						
						for ( ; ; t++) {
							sprintf(index_tmp_filename, "%s%08lx.idx", inbound, t);
							
							if (_access(index_tmp_filename, 0) && errno == ENOENT) {
								break;
							}
						}
						
						index_tmp.open(index_tmp_filename, ios::trunc | ios::out | ios::binary);
						
						for ( ; ; t++) {
							sprintf(message_tmp_filename, "%s%08lx.msg", inbound, t);
							
							if (_access(message_tmp_filename, 0) && errno == ENOENT) {
								break;
							}
						}
						
						message_tmp.open(message_tmp_filename, ios::trunc | ios::out | ios::binary);
					}
					
					if (index_org && message_org && index_tmp && message_tmp) {
						wssoup_index*	pindex = *(soup_index + i);
						char			line[4096];
						
						message_org.seekg(pindex->get_offset());
						
						if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							index_org.close();
							message_org.close();
							index_tmp.close();
							message_tmp.close();
							remove(index_tmp_filename);
							remove(message_tmp_filename);
							return -1;
						}
						
						sprintf(line, "#! rnews %08lu\n", pindex->get_bytes());
						message_tmp.write(line, strlen(line));
						sprintf(line,
								"%lu\t%s\t%s\t%s\t%s\t%s\t%lu\t%lu\t%lu\n",
								message_tmp.tellp(),
								pindex->get_subject(),
								pindex->get_from(),
								pindex->get_date(),
								pindex->get_message_id(),
								pindex->get_references(),
								pindex->get_bytes(),
								pindex->get_lines(),
								pindex->get_number());
						index_tmp.write(line, strlen(line));
						
						if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							index_org.close();
							message_org.close();
							index_tmp.close();
							message_tmp.close();
							remove(index_tmp_filename);
							remove(message_tmp_filename);
							return -1;
						}
						
						for (unsigned long j = 0 ; j < pindex->get_bytes() ; j++) {
							message_tmp.put((char)message_org.get());
							
							if (index_org.fail() || message_org.fail() || index_tmp.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								index_org.close();
								message_org.close();
								index_tmp.close();
								message_tmp.close();
								remove(index_tmp_filename);
								remove(message_tmp_filename);
								return -1;
							}
						}
						
						if (i == soup_index_total - 1) {
							index_org.close();
							message_org.close();
							index_tmp.close();
							message_tmp.close();
							
							remove(index_filename);
							
							if (rename(index_tmp_filename, index_filename)) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								return -1;
							}
							
							remove(message_filename);
							
							if (rename(message_tmp_filename, message_filename)) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								return -1;
							}
							
							soup_index_total_org = soup_index_total;
						}
					} else {
						char	error[256];
						
						if (!index_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, index_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else if (!message_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, message_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else {
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						}
						
						if (index_org) {
							index_org.close();
						}
						
						if (message_org) {
							message_org.close();
						}
						
						if (index_tmp) {
							index_tmp.close();
							remove(index_tmp_filename);
						}
						
						if (message_tmp) {
							message_tmp.close();
							remove(message_tmp_filename);
						}
						
						return -1;
					}
					
					break;
				}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					return -1;
				}
			}
			
			break;
		}
		
		//case 'm': {
		//	break;
		//}
		
		//case 'M': {
		//	break;
		//}
		
		case 'b': {
			switch (*(encoding + 1)) {
				case 'n': {
					if (i == 0) {
						time_t	t;
						
						sprintf(message_filename, "%s%s.msg", inbound, filename);
						message_org.open(message_filename, ios::in | ios::nocreate | ios::binary);
						
						time(&t);
						
						for ( ; ; t++) {
							sprintf(message_tmp_filename, "%s%08lx.msg", inbound, t);
							
							if (_access(message_tmp_filename, 0) && errno == ENOENT) {
								break;
							}
						}
						
						message_tmp.open(message_tmp_filename, ios::trunc | ios::out | ios::binary);
					}
					
					if (message_org && message_tmp) {
						wssoup_index*	pindex = *(soup_index + i);
						
						message_org.seekg(pindex->get_offset());
						
						if (message_org.fail() || message_tmp.fail()) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							message_org.close();
							message_tmp.close();
							remove(message_tmp_filename);
							return -1;
						}
						
						unsigned long	l = pindex->get_bytes();
						l = MAKELONG(MAKEWORD(HIBYTE(HIWORD(l)),
											  LOBYTE(HIWORD(l))),
									 MAKEWORD(HIBYTE(LOWORD(l)),
											  LOBYTE(LOWORD(l))));
						message_tmp.write((const char*)&l, sizeof(long));
						
						if (message_org.fail() || message_tmp.fail()) {
							char	error[256];
							
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
							message_org.close();
							message_tmp.close();
							remove(message_tmp_filename);
							return -1;
						}
						
						for (unsigned long j = 0 ; j < pindex->get_bytes() ; j++) {
							message_tmp.put((char)message_org.get());
							
							if (message_org.fail() || message_tmp.fail()) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								message_org.close();
								message_tmp.close();
								remove(message_tmp_filename);
								return -1;
							}
						}
						
						if (i == soup_index_total - 1) {
							message_org.close();
							message_tmp.close();
							
							remove(message_filename);
							
							if (rename(message_tmp_filename, message_filename)) {
								char	error[256];
								
								sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
								MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
								return -1;
							}
							
							soup_index_total_org = soup_index_total;
						}
					} else {
						char	error[256];
						
						if (!message_org) {
							sprintf(error, "wssoup.cpp(%d)\n%s not found.", __LINE__, message_filename);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						} else {
							sprintf(error, "wssoup.cpp(%d)\nAn error occured in file processing.", __LINE__);
							MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
						}
						
						if (message_org) {
							message_org.close();
						}
						
						if (message_tmp) {
							message_tmp.close();
							remove(message_tmp_filename);
						}
						
						return -1;
					}
					
					break;
				}
				
				//case 'c': {
				//	break;
				//}
				
				//case 'C': {
				//	break;
				//}
				
				//case 'i': {
				//	break;
				//}
				
				default: {
					char	error[256];
					
					sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
					MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
					return -1;
				}
			}
			
			break;
		}
		
		//case 'B': {
		//	break;
		//}
		
		//case 'i': {
		//	break;
		//}
		
		default: {
			char	error[256];
			
			sprintf(error, "wssoup.cpp(%d)\nSorry, `%s' SOUP format is not supported.", __LINE__, encoding);
			MessageBox(NULL, error, "GWSSOUP.DLL Error", MB_TASKMODAL | MB_OK | MB_ICONHAND);
			return -1;
		}
	}
	
	return 0;
}

wssoup_index** wssoup_index_table::get_wssoup_index(void)
{
	return (wssoup_index**)soup_index;
}

wssoup_index** wssoup_index_table::get_wssoup_index(unsigned long number)
{
	wssoup_index	index(number);
	wssoup_index*	pindex = &index;
	
	return (wssoup_index**)bsearch((void *)&pindex, (void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
}

wssoup_index* wssoup_index_table::get_wssoup_index(char* message_id)
{
	wssoup_index	index(0, NULL, NULL, NULL, message_id, NULL, 0, 0, 0);
	wssoup_index*	pindex = &index;
	wssoup_index**	ppindex;
	
	if (soup_index) {
		qsort((void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_message_id);
	}
	
	if (ppindex = (wssoup_index**)bsearch((void *)&pindex, (void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_message_id)) {
		pindex = *ppindex;
	} else {
		pindex = NULL;
	}
	
	if (soup_index) {
		qsort((void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
	}
	
	return pindex;
}

void wssoup_index_table::delete_wssoup_index(unsigned long number)
{
	wssoup_index	index(number);
	wssoup_index*	pindex = &index;
	wssoup_index**	ppindex = (wssoup_index**)bsearch((void *)&pindex, (void *)soup_index, (size_t)soup_index_total, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
	
	if (ppindex) {
		(*ppindex)->put_number(0xFFFFFFFF);
		qsort((void *)soup_index, (size_t)soup_index_total--, sizeof(wssoup_index*), (COMPARE_WSSOUP_INDEX)compare_wssoup_index_number);
		delete *(soup_index + soup_index_total);
	}
}

unsigned long wssoup_index_table::get_wssoup_index_total_org(void)
{
	return soup_index_total_org;
}

unsigned long wssoup_index_table::get_wssoup_index_total(void)
{
	return soup_index_total;
}

//
// wssoup class
//

BOOL FAR PASCAL GENSOCK_EXPORT GWSSoupSetupDlgProc(HWND, UINT, UINT, LONG);

char	InBound[256];
char	OutBound[256];
#ifdef CONTORL
char	Control[256];
#endif	// CONTROL

wssoup::wssoup(void)
{
	FARPROC	lpfnGWSSoupSetupDlgProc;
	char	filename[256];
	
	GetPrivateProfileString("WSSoup", "InBound", "", InBound, sizeof(InBound), ".\\gwssoup.ini");
	GetPrivateProfileString("WSSoup", "OutBound", "", OutBound, sizeof(OutBound), ".\\gwssoup.ini");
#ifdef CONTROL
	GetPrivateProfileString("WSSoup", "Control", "", Control, sizeof(Control), ".\\gwssoup.ini");
#endif	// CONTROL
	
#ifdef CONTROL
	if (!strcmp(InBound, "") || !strcmp(OutBound, "") || !strcmp(Control, "")) {
#else	// CONTROL
	if (!strcmp(InBound, "") || !strcmp(OutBound, "")) {
#endif	// CONTROL
		lpfnGWSSoupSetupDlgProc = &GWSSoupSetupDlgProc;//MakeProcInstance((FARPROC)GWSSoupSetupDlgProc, dll_module_handle);
		DialogBox(dll_module_handle, "GWSSoupSetupBox", NULL, lpfnGWSSoupSetupDlgProc);
	}
	
	strcpy(inbound, InBound);
	strcpy(outbound, OutBound);
#ifdef CONTROL
	strcpy(control, Control);
#endif	// CONTROL
	strcpy(filename, inbound);
	strcat(filename, "areas");
	soup_areas_table = new wssoup_areas_table(filename);
	soup_index_table = NULL;
	memset(server_command, 0, sizeof(server_command));
	server_response = FALSE;
	soup_areas = NULL;
}

wssoup::~wssoup(void)
{
	if (soup_index_table) {
		if (soup_index_table->get_wssoup_index_total_org() && (soup_index_table->get_wssoup_index_total_org() != soup_index_table->get_wssoup_index_total())) {
			soup_index_table->write_wssoup_index_table(inbound, (*soup_areas)->get_filename(), (*soup_areas)->get_encoding());
		}
		
		delete soup_index_table;
	}
	
	if (soup_areas_table) {
		delete soup_areas_table;
	}
}

void wssoup::put_server_command(char* command)
{
	if (!stricmp(server_command, "DATA")) {
		if (!strcmp(command + strlen(command) - 5, "\r\n.\r\n")) {
			data.write(command, strlen(command) - 5);
			
			unsigned long	l;
			
			l = data.tellp() - sizeof(long);
			l = MAKELONG(MAKEWORD(HIBYTE(HIWORD(l)), LOBYTE(HIWORD(l))),
						 MAKEWORD(HIBYTE(LOWORD(l)), LOBYTE(LOWORD(l))));
			data.seekp(0);
			data.write((const char*)&l, sizeof(long));
			data.close();
			get_data_response();
		} else {
			data.write(command, strlen(command));
		}
	} else if (!stricmp(server_command, "POST")) {
		if (!strcmp(command + strlen(command) - 5, "\r\n.\r\n")) {
			post.write(command, strlen(command) - 5);
			
			unsigned long	l;
			
			l = post.tellp() - sizeof(long);
			l = MAKELONG(MAKEWORD(HIBYTE(HIWORD(l)), LOBYTE(HIWORD(l))),
						 MAKEWORD(HIBYTE(LOWORD(l)), LOBYTE(LOWORD(l))));
			post.seekp(0);
			post.write((const char*)&l, sizeof(long));
			post.close();
			get_post_response();
		} else {
			post.write(command, strlen(command));
		}
	} else {
		if (!strnicmp(command, "ARTICLE", 7)) {
			put_article_command(command);
		} else if (!strnicmp(command, "DATA", 4)) {
			put_data_command(command);
			header = TRUE;
		} else if (!strnicmp(command, "DELETE", 6)) {
			put_delete_command(command);
		} else if (!strnicmp(command, "GROUP", 5)) {
			put_group_command(command);
		} else if (!strnicmp(command, "LIST", 4)) {
			put_list_command(command);
		} else if (!strnicmp(command, "POST", 4)) {
			put_post_command(command);
			header = TRUE;
		} else if (!strnicmp(command, "SENDME", 6)) {
			put_sendme_command(command);
		} else if (!strnicmp(command, "WRITE", 5)) {
			put_write_command(command);
		} else if (!strnicmp(command, "XOVER", 5)) {
			put_xover_command(command);
		} else if (!strnicmp(command, "HELO", 4) ||
				   !strnicmp(command, "MAIL FROM:", 10) ||
				   !strnicmp(command, "RCPT TO:", 8)) {
			strcpy(server_buffer, "250 Requested mail action okay, completed\r\n");
		} else {
			strcpy(server_buffer, "500 Command unrecognized\r\n");
		}
	}
}

void wssoup::put_article_command(char* command)
{
	if (soup_areas) {
		if (soup_index_table && soup_index_table->get_wssoup_index_total()) {
			char*	token = strtok(command, " \t\r\n");
			
			if ((token = strtok(NULL, " \t\r\n")) == NULL) {
				wssoup_index**	ppindex;
				
				if (ppindex = soup_index_table->get_wssoup_index()) {
					char	filename[256];
					
					strcpy(server_command, "ARTICLE");
					strcpy(filename, inbound);
					strcat(filename, (*soup_areas)->get_filename());
					strcat(filename, ".msg");
					message.open(filename, ios::in | ios::nocreate | ios::binary);
					message.seekg((*ppindex)->get_offset());
					
					if (message.fail()) {
						article_from = 1;
						article_to = 0;
					} else {
						article_from = 1;
						article_to = (*ppindex)->get_bytes();
					}
					
					sprintf(server_buffer, "220 %lu %s article\r\n", (*ppindex)->get_number(), (*ppindex)->get_message_id());
				} else {
					strcpy(server_buffer, "423 no such article number in this group\r\n");
				}
			} else {
				unsigned long	number;
				
				if (number = atol(token)) {
					wssoup_index**	ppindex;
					
					if (ppindex = soup_index_table->get_wssoup_index(number)) {
						char	filename[256];
						
						strcpy(server_command, "ARTICLE");
						strcpy(filename, inbound);
						strcat(filename, (*soup_areas)->get_filename());
						strcat(filename, ".msg");
						message.open(filename, ios::in | ios::nocreate | ios::binary);
						message.seekg((*ppindex)->get_offset());
						
						if (message.fail()) {
							article_from = 1;
							article_to = 0;
						} else {
							article_from = 1;
							article_to = (*ppindex)->get_bytes();
						}
						
						sprintf(server_buffer, "220 %lu %s article\r\n", (*ppindex)->get_number(), (*ppindex)->get_message_id());
					} else {
						strcpy(server_buffer, "423 no such article number in this group\r\n");
					}
				} else {
					wssoup_index*	pindex;
					
					if (pindex = soup_index_table->get_wssoup_index(token)) {
						char	filename[256];
						
						strcpy(server_command, "ARTICLE");
						strcpy(filename, inbound);
						strcat(filename, (*soup_areas)->get_filename());
						strcat(filename, ".msg");
						message.open(filename, ios::in | ios::nocreate | ios::binary);
						message.seekg(pindex->get_offset());
						
						if (message.fail()) {
							article_from = 1;
							article_to = 0;
						} else {
							article_from = 1;
							article_to = pindex->get_bytes();
						}
						
						sprintf(server_buffer, "220 %lu %s article\r\n", pindex->get_number(), pindex->get_message_id());
					} else {
						strcpy(server_buffer, "423 no such article number in this group\r\n");
					}
				}
			}
		} else {
			strcpy(server_buffer, "423 no such article number in this group\r\n");
		}
	} else {
		strcpy(server_buffer, "412 no newsgroup has been selected\r\n");
	}
}

void wssoup::put_data_command(char* command)
{
	char	filename[256];
	
	strcpy(filename, outbound);
	strcat(filename, "replies");
	
	ofstream	replies(filename, ios::app | ios::out | ios::binary);
	
	if (replies) {
		time_t	t;
		
		time(&t);
		
		for ( ; ; t++) {
			sprintf(filename, "%s%08lx.msg", outbound, t);
			
			if (_access(filename, 0) && errno == ENOENT) {
				break;
			}
		}
		
		data.open(filename, ios::out | ios::noreplace | ios::binary);
		
		if (data.fail()) {
			replies.close();
			strcpy(server_buffer, "554 Transaction failed\r\n");
		} else {
			char	line[256];
			
			sprintf(line, "%08lx\tmail\tBn\n", t);
			replies.write(line, strlen(line));
			replies.close();
			
			long	l = 0;
			
			data.write((const char*)&l, sizeof(long));
			strcpy(server_command, "DATA");
			strcpy(server_buffer, "354 Start mail input; end with <CR-LF>.<CR-LF>\r\n");
		}
	} else {
		strcpy(server_buffer, "554 Transaction failed\r\n");
	}
}

void wssoup::put_delete_command(char* command)
{
	if (soup_areas) {
		if (soup_index_table && soup_index_table->get_wssoup_index_total()) {
			char*	token = strtok(command, " \t\r\n");
			
			if ((token = strtok(NULL, " \t\r\n")) == NULL) {
				wssoup_index**	ppindex;
				
				if (ppindex = soup_index_table->get_wssoup_index()) {
					soup_index_table->delete_wssoup_index((*ppindex)->get_number());
					strcpy(server_buffer, "229 article deleted ok\r\n");
				} else {
					strcpy(server_buffer, "423 no such article number in this group\r\n");
				}
			} else {
				unsigned long	number;
				
				if (number = atol(token)) {
					wssoup_index**	ppindex;
					
					if (ppindex = soup_index_table->get_wssoup_index(number)) {
						soup_index_table->delete_wssoup_index(number);
						strcpy(server_buffer, "229 article deleted ok\r\n");
					} else {
						strcpy(server_buffer, "423 no such article number in this group\r\n");
					}
				} else {
					strcpy(server_buffer, "423 no such article number in this group\r\n");
				}
			}
		} else {
			strcpy(server_buffer, "423 no such article number in this group\r\n");
		}
	} else {
		strcpy(server_buffer, "412 no newsgroup has been selected\r\n");
	}
}

void wssoup::put_group_command(char* command)
{
	char*	token = strtok(command, " \t\r\n");
	
	if ((token = strtok(NULL, " \t\r\n")) == NULL) {
		strcpy(server_buffer, "501 command syntax error\r\n");
	} else {
		wssoup_areas**	soup_areas_org = soup_areas;
		
		if (soup_areas = soup_areas_table->get_wssoup_areas(token)) {
			if (!soup_areas_org || strcmp((*soup_areas_org)->get_filename(), (*soup_areas)->get_filename())) {
				if (soup_index_table) {
					if (soup_index_table->get_wssoup_index_total_org() && (soup_index_table->get_wssoup_index_total_org() != soup_index_table->get_wssoup_index_total())) {
						soup_index_table->write_wssoup_index_table(inbound, (*soup_areas_org)->get_filename(), (*soup_areas_org)->get_encoding());
					}
					
					delete soup_index_table;
				}
				
				soup_index_table = new wssoup_index_table(inbound, (*soup_areas)->get_filename(), (*soup_areas)->get_encoding());
			}
			
			if (soup_index_table && soup_index_table->get_wssoup_index_total()) {
				wssoup_index**	ppindex = soup_index_table->get_wssoup_index();
				unsigned long	n = soup_index_table->get_wssoup_index_total();
				unsigned long	f = (*ppindex)->get_number();
				unsigned long	l = (*(ppindex + n - 1))->get_number();
				
				sprintf(server_buffer, "211 %lu %lu %lu %s\r\n", n, f, l, token);
			} else {
				sprintf(server_buffer, "211 0 1 0 %s\r\n", token);
			}
		} else {
			//strcpy(server_buffer, "411 no such news group\r\n");
			sprintf(server_buffer, "211 0 1 0 %s\r\n", token);
		}
	}
}

void wssoup::put_list_command(char* command)
{
	char	filename[256];
	
	strcpy(server_command, "LIST");
#ifdef CONTROL
	strcpy(filename, control);
	strcat(filename, "list.dat");
#else	// CONTROL
	strcpy(filename, inbound);
	strcat(filename, "list");
#endif	// CONTORL
	list.open(filename, ios::in | ios::nocreate | ios::binary);
	
	if (!list) {
		list_from = 0;
	}
	
	strcpy(server_buffer, "215 list of newsgroups follows\r\n");
}

void wssoup::put_post_command(char* command)
{
	char	filename[256];
	
	strcpy(filename, outbound);
	strcat(filename, "replies");
	
	ofstream	replies(filename, ios::app | ios::out | ios::binary);
	
	if (replies) {
		time_t	t;
		
		time(&t);
		
		for ( ; ; t++) {
			sprintf(filename, "%s%08lx.msg", outbound, t);
			
			if (_access(filename, 0) && errno == ENOENT) {
				break;
			}
		}
		
		post.open(filename, ios::out | ios::noreplace | ios::binary);
		
		if (post.fail()) {
			replies.close();
			strcpy(server_buffer, "441 posting failed\r\n");
		} else {
			char	line[256];
			
			sprintf(line, "%08lx\tnews\tbn\n", t);
			replies.write(line, strlen(line));
			replies.close();
			
			long	l = 0;
			
			post.write((const char*)&l, sizeof(long));
			strcpy(server_command, "POST");
			strcpy(server_buffer, "340 send article to be posted. End with <CR-LF>.<CR-LF>\r\n");
		}
	} else {
		strcpy(server_buffer, "441 posting failed\r\n");
	}
}

void wssoup::put_sendme_command(char* command)
{
	if (soup_areas) {
		if (soup_index_table && soup_index_table->get_wssoup_index_total()) {
			char	filename[256];
			
			strcpy(filename, outbound);
			strcat(filename, "commands");
			
			ofstream	commands(filename, ios::app | ios::out | ios::binary);
			
			if (commands) {
				char*	token = strtok(command, " \t\r\n");
				
				if ((token = strtok(NULL, " \t\r\n")) == NULL) {
					wssoup_index**	ppindex;
					
					if (ppindex = soup_index_table->get_wssoup_index()) {
						char	line[512];
						
						sprintf(line, "SENDME\t%s\t%lu\n", (*soup_areas)->get_group(), (*ppindex)->get_number());
						commands.write(line, strlen(line));
					}
				} else {
					char	line[512];
					
					sprintf(line, "SENDME\t%s\t%s\n", (*soup_areas)->get_group(), token);
					commands.write(line, strlen(line));
				}
				
				commands.close();
			}
		}
	}
}

void wssoup::put_write_command(char* command)
{
	if (soup_areas) {
		if (soup_index_table) {
			if (soup_index_table->get_wssoup_index_total_org() && (soup_index_table->get_wssoup_index_total_org() != soup_index_table->get_wssoup_index_total())) {
				strcpy(server_command, "WRITE");
				write_from = 0;
				write_to = soup_index_table->get_wssoup_index_total();
				return;
			}
		}
	}
	
	memset(server_command, 0, sizeof(server_command));
	strcpy(server_buffer, ".\r\n");
}

void wssoup::put_xover_command(char* command)
{
	if (soup_areas) {
		strcpy(server_command, "XOVER");
		
		if (soup_index_table && soup_index_table->get_wssoup_index_total()) {
			char*	token = strtok(command, " \t\r\n");
			
			if ((token = strtok(NULL, " \t\r\n")) == NULL) {
				wssoup_index**	ppindex = soup_index_table->get_wssoup_index();
				
				xover_from = xover_to = (*ppindex)->get_number();
			} else {
				char*	token_to;
				
				if ((token_to = strchr(token, '-')) == NULL) {
					xover_from = atol(token);
					xover_to = atol(token);
				} else {
					*token_to++ = 0;
					xover_from = atol(token);
					xover_to = atol(token_to);
				}
			}
		} else {
			xover_from = 1;
			xover_to = 0;
		}
		
		strcpy(server_buffer, "224 data follows\r\n");
	} else {
		strcpy(server_buffer, "412 no newsgroup has been selected\r\n");
	}
}

void wssoup::put_server_response(char* buffer)
{
	strcpy(server_buffer, buffer);
}

char* wssoup::get_server_command(void)
{
	return server_command;
}

void wssoup::get_server_response(char* buffer, size_t length)
{
	if (server_response) {
		strcpy(buffer, "");
	} else if (strlen(server_buffer) > length - 1) {
		strncpy(buffer, server_buffer, length - 1);
		strcpy(server_buffer, server_buffer + length - 1);
	} else if (strlen(server_buffer)) {
		strcpy(buffer, server_buffer);
		memset(server_buffer, 0, sizeof(server_buffer));
	} else {
		server_response = TRUE;
		
		if (!stricmp(server_command, "ARTICLE")) {
			get_article_response();
		} else if (!stricmp(server_command, "LIST")) {
			get_list_response();
		} else if (!stricmp(server_command, "POST")) {
			;
		} else if (!stricmp(server_command, "WRITE")) {
			get_write_response();
		} else if (!stricmp(server_command, "XOVER")) {
			get_xover_response();
		}
		
		if (strlen(server_buffer) > length - 1) {
			strncpy(buffer, server_buffer, length - 1);
			strcpy(server_buffer, server_buffer + length - 1);
		} else {
			strcpy(buffer, server_buffer);
			memset(server_buffer, 0, sizeof(server_buffer));
		}
		
		server_response = FALSE;
	}
}

void wssoup::get_article_response(void)
{
	memset(server_buffer, 0, sizeof(server_buffer));
	
	for (unsigned long i = 0 ; article_from <= article_to && i < sizeof(server_buffer) - 1 ; article_from++, i++) {
		*(server_buffer + i) = message.get();
	}
	
	if (strcmp(server_buffer, "")) {
		return;
	} else {
		memset(server_command, 0, sizeof(server_command));
		strcpy(server_buffer, "\r\n.\r\n");
		message.close();
		return;
	}
}

void wssoup::get_data_response(void)
{
	memset(server_command, 0, sizeof(server_command));
	strcpy(server_buffer, "250 Requested mail action okay, completed\r\n");
}

void wssoup::get_list_response(void)
{
	for ( ; ; ) {
		wssoup_areas**	ppareas;
		char*			group;
		char			line[1024];
		
		if (list) {
			if (list.eof() || list.fail()) {
				break;
			}
			
			list.getline(line, sizeof(line));
			
			if ((group = strtok(line, " \t\r\n")) == NULL) {
				continue;
			}
			
			ppareas = soup_areas_table->get_wssoup_areas(group);
		} else {
			if (list_from >= soup_areas_table->get_wssoup_areas_total()) {
				break;
			}
			
			ppareas = soup_areas_table->get_wssoup_areas() + list_from++;
			group = (*ppareas)->get_group();
		}
			
		/*
		char			filename[256];
		unsigned long	f, l;
		
		strcpy(filename, control);
		strcat(filename, "group.dat");
		
		if (GetPrivateProfileInt("wssoup.subscribe", group, 0, filename)) {
			f = GetPrivateProfileInt(line, "first", 1, filename);
			l = GetPrivateProfileInt(line, "last", 0, filename);
		} else {
			f = 1;
			l = 0;
		}
		*/
		
		unsigned long	f, l;
		
		if (ppareas) {
			wssoup_index_table	index_table(inbound, (*ppareas)->get_filename(), (*ppareas)->get_encoding());
			
			if (index_table && index_table.get_wssoup_index_total()) {
				wssoup_index**	ppindex = index_table.get_wssoup_index();
				
				f = (*ppindex)-> get_number();
				l = (*(ppindex + index_table.get_wssoup_index_total() - 1))-> get_number();
			} else {
				f = 1;
				l = 0;
			}
		} else {
			f = 1;
			l = 0;
		}
		
		sprintf(server_buffer, "%s %lu %lu y\r\n", group, l, f);
		return;
	}
	
	memset(server_command, 0, sizeof(server_command));
	strcpy(server_buffer, ".\r\n");
	list.close();
	return;
}

void wssoup::get_post_response(void)
{
	memset(server_command, 0, sizeof(server_command));
	strcpy(server_buffer, "240 article posted ok\r\n");
}

void wssoup::get_write_response(void)
{
	if (write_from < write_to) {
		if (soup_index_table->write_wssoup_index(inbound, (*soup_areas)->get_filename(), (*soup_areas)->get_encoding(), write_from)) {
			memset(server_command, 0, sizeof(server_command));
			strcpy(server_buffer, ".\r\n");
		} else {
			sprintf(server_buffer, "%lu\r\n", write_from++);
		}
	} else {
		char	filename[256];
		
		strcpy(filename, inbound);
		strcat(filename, (*soup_areas)->get_filename());
		strcat(filename, ".idx");
		
		if (soup_index_table) {
			if (soup_index_table->get_wssoup_index_total_org() && (soup_index_table->get_wssoup_index_total_org() != soup_index_table->get_wssoup_index_total())) {
				soup_index_table->write_wssoup_index_table(inbound, (*soup_areas)->get_filename(), (*soup_areas)->get_encoding());
			}
			
			delete soup_index_table;
		}
		
		soup_index_table = new wssoup_index_table(inbound, (*soup_areas)->get_filename(), (*soup_areas)->get_encoding());
		memset(server_command, 0, sizeof(server_command));
		strcpy(server_buffer, ".\r\n");
	}
	
	return;
}

void wssoup::get_xover_response(void)
{
	for ( ; xover_from <= xover_to ; xover_from++) {
		wssoup_index**	ppindex;
		
		if (ppindex = soup_index_table->get_wssoup_index(xover_from)) {
			sprintf(server_buffer,
					"%lu\t%s\t%s\t%s\t%s\t%s\t%lu\t%lu\r\n",
					xover_from++,
					(*ppindex)->get_subject(),
					(*ppindex)->get_from(),
					(*ppindex)->get_date(),
					(*ppindex)->get_message_id(),
					(*ppindex)->get_references(),
					(*ppindex)->get_bytes(),
					(*ppindex)->get_lines());
			return;
		}
	}
	
	memset(server_command, 0, sizeof(server_command));
	strcpy(server_buffer, ".\r\n");
	return;
}

BOOL FAR PASCAL GENSOCK_EXPORT GWSSoupSetupDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam)
{
	switch (message) {
		case WM_INITDIALOG:
			if (!strcmp(InBound, "")) {
				strcpy(InBound, "c:\\wssoup\\inbound\\");
			}
			
			if (!strcmp(OutBound, "")) {
				strcpy(OutBound, "c:\\wssoup\\outbound\\");
			}
			
#ifdef CONTROL
			if (!strcmp(Control, "")) {
				strcpy(Control, "c:\\wssoup\\control\\");
			}
#endif	// CONTROL
			
			SetDlgItemText(hDlg, IDD_INBOUND, InBound);
			SetDlgItemText(hDlg, IDD_OUTBOUND, OutBound);
#ifdef CONTROL
			SetDlgItemText(hDlg, IDD_CONTROL, Control);
#endif	// CONTROL
			return TRUE;
		
		case WM_COMMAND:
			switch (wParam) {
				char	dirname[256];
				
				case IDOK:
					GetDlgItemText(hDlg, IDD_INBOUND, InBound, sizeof(InBound));
					GetDlgItemText(hDlg, IDD_OUTBOUND, OutBound, sizeof(OutBound));
#ifdef CONTROL
					GetDlgItemText(hDlg, IDD_CONTROL, Control, sizeof(Control));
#endif	// CONTROL
					
					// Check InBound directory
					if (!strcmp(InBound, "")) {
						MessageBox(hDlg, "InBound directory invalid.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_INBOUND));
						break;
					}
					
					if (*(InBound + strlen(InBound) - 1) != '\\') {
						strcat(InBound, "\\");
					}
					
					strcpy(dirname, InBound);
					*(dirname + strlen(dirname) - 1) = 0;
					
					if (_access(dirname, 0) && errno == ENOENT) {
						MessageBox(hDlg, "InBound directory not found.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_INBOUND));
						break;
					}
					
					// Check OutBound directory
					if (!strcmp(OutBound, "")) {
						MessageBox(hDlg, "OutBound directory invalid.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_OUTBOUND));
						break;
					}
					
					if (*(OutBound + strlen(OutBound) - 1) != '\\') {
						strcat(OutBound, "\\");
					}
					
					strcpy(dirname, OutBound);
					*(dirname + strlen(dirname) - 1) = 0;
					
					if (_access(dirname, 0) && errno == ENOENT) {
						MessageBox(hDlg, "OutBound directory not found.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_OUTBOUND));
						break;
					}
					
#ifdef CONTROL
					// Check Control directory
					if (!strcmp(Control, "")) {
						MessageBox(hDlg, "Control directory invalid.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_CONTROL));
						break;
					}
					
					if (*(Control + strlen(Control) - 1) != '\\') {
						strcat(Control, "\\");
					}
					
					strcpy(dirname, Control);
					*(dirname + strlen(dirname) - 1) = 0;
					
					if (_access(dirname, 0) && errno == ENOENT) {
						MessageBox(hDlg, "Control directory not found.", "GWSSOUP.DLL Setup Error", MB_OK);
						SetFocus(GetDlgItem(hDlg, IDD_CONTROL));
						break;
					}
#endif	// CONTROL
					
					WritePrivateProfileString("WSSoup", "InBound", InBound, ".\\gwssoup.ini");
					WritePrivateProfileString("WSSoup", "OutBound", OutBound, ".\\gwssoup.ini");
#ifdef CONTROL
					WritePrivateProfileString("WSSoup", "Control", Control, ".\\gwssoup.ini");
#endif	// CONTROL
					EndDialog(hDlg, TRUE);
					return TRUE;
				
				case IDCANCEL:
					memset(InBound, 0, sizeof(InBound));
					memset(OutBound, 0, sizeof(OutBound));
#ifdef CONTROL
					memset(Control, 0, sizeof(Control));
#endif	// CONTORL
					EndDialog(hDlg, FALSE);
					return TRUE;
			}
			
			break;
	}
	
	return FALSE;
}
