Listing 3: POP3.C POP3 window procedure and protocol implementation


/**********************************************************/
/* POP3.C - contains the POP3 window procedure and POP3   */
/*          protocol implementation                       */
/**********************************************************/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <mem.h>
#include <dos.h>
#include "popmail.rh"
#include "globals.h"
#include "winsock.h"

extern HANDLE hInst;
extern stConfig Config;
extern char IOBuffer[BUFFERSIZE];
extern char HostInfo[MAXGETHOSTSTRUCT];

long wBytesRead;
long wBytesSent;
long wBytesWritten;
int State;
int Bytes;
int MsgFile;
int MsgNumber;
int MsgCount;
int TotalMsgs;

long far PASCAL _export Pop3Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
	  IN_ADDR HostIp;
	  char WorkBuffer[255];
	  PHOSTENT pHostInfo;

	  switch (message)
		 {
			 case WM_CREATE:
				MsgCount = 0;
				wBytesRead = 0;
				wBytesSent = 0;
				wBytesWritten = 0;
            break;

			 case IMSG_HOSTFOUND:
				if (WSAGETASYNCERROR(lParam) == 0)
				  {
					  pHostInfo = (PHOSTENT) HostInfo;
					  /* here's the hosts primary name and address type */
					  wsprintf(WorkBuffer, "Found Host  : %s\r\n", pHostInfo->h_name);
					  Display(WorkBuffer);
					  wsprintf(WorkBuffer, "Address Type: %d, length %d\r\n", pHostInfo->h_addrtype, pHostInfo->h_length);
					  Display(WorkBuffer);

					  /* copy the IP address */
					  memcpy(&HostIp, pHostInfo->h_addr, 4);
					  wsprintf(WorkBuffer, "Primary IP  : %s\r\n", inet_ntoa(HostIp));
					  wsprintf(Config.ServerIp, "%s", inet_ntoa(HostIp));
					  Display(WorkBuffer);

					  /* now we make a connection */
					  ConnectToServer(hwnd);
				  }
				else Display("An error occurred during host lookup.\r\n");
				break;

			 case IMSG_NETIO:
				switch (WSAGETSELECTEVENT(lParam))
				  {
					  case FD_CONNECT:
						 Display("Connection to POP port established.\r\n");
						 State = POP_LOGIN;
						 break;

					  case FD_READ:
						 Bytes = recv((SOCKET) wParam, IOBuffer, 1024, 0);
						 if (State == POP_XFER)
							SaveToFile((SOCKET) wParam, Bytes);
						 else
							ProcBuffer((SOCKET) wParam, Bytes);
						 break;

					  case FD_CLOSE:
						 closesocket((SOCKET) wParam);
						 break;
				  }
				break;
		 }
	  return DefWindowProc(hwnd, message, wParam, lParam);
  }

void SaveToFile(SOCKET Socket, int Bytes)
  {
	  BOOL EndOfMessage = FALSE;

	  IOBuffer[Bytes] = '\0';
	  if (strlen(IOBuffer) >= 5)
		 {
			 char* ptr = &IOBuffer[strlen(IOBuffer) - 5];
			 if (strcmp(ptr, "\r\n.\r\n") == 0)
				{
					EndOfMessage = TRUE;
					strcpy(ptr, "");
				}
		 }

	  wBytesWritten += _lwrite(MsgFile, IOBuffer, strlen(IOBuffer));

	  if (EndOfMessage)
		 {
			 _lclose(MsgFile);
			 MsgCount++;
			 State = POP_DELE;
			 Send(Socket, POP_DELE, MsgNumber);
		 }
  }

void ProcBuffer(SOCKET Socket, int Bytes)
  {
	  char Token[5], *ptr;
	  char WorkBuffer[30], TempFile[144];
	  struct time t;

	  IOBuffer[Bytes] = '\0';
	  Display(IOBuffer);

	  strncpy(Token, IOBuffer, 4);
	  Token[4] = '\0'; /* old habit */

	  switch (State)
		 {
			 case POP_LOGIN:
				Send(Socket, POP_USER, Config.Pop3Name);
				State = POP_PASS;
				break;

			 case POP_PASS:
				Send(Socket, POP_PASS, Config.Pop3Pass);
				State = POP_VRFY;
				break;

			 case POP_VRFY:
				if (strcmpi(Token, "+OK ") == 0)
				  {
					  Send(Socket, POP_STAT);
					  State = POP_STAT;
				  }
				else
				  {
					  Display("The server refused your name/password.");
					  closesocket(Socket);
				  }
				break;

			 case POP_STAT:
				strcpy(WorkBuffer, (char*)&IOBuffer[4]);
				ptr = strstr(WorkBuffer, " ");
				if (ptr != NULL) strcpy(ptr, "");
				TotalMsgs = atoi(WorkBuffer);

				if (TotalMsgs >= 1)
				  {
					  MsgNumber = 1;
					  State = POP_RETR;
                 Send(Socket, POP_RETR, MsgNumber);
				  }
				else
				  {
					  State = POP_QUIT;
					  Send(Socket, POP_QUIT);
				  }
				break;

			 case POP_DELE:
				if (++MsgNumber > TotalMsgs)
				  {
					  State = POP_QUIT;
					  Send(Socket, POP_QUIT);
				  }
				else
				  {
					  State = POP_RETR;
					  Send(Socket, POP_RETR, MsgNumber);
				  }
				break;

			 case POP_RETR:
				gettime(&t);
				sprintf(TempFile, "%s%02d%02d%02d.MSG", Config.MailDir, t.ti_hour, t.ti_min, t.ti_sec);
				MsgFile = _lcreat(TempFile, 0);
				_
				State = POP_XFER;
				break;
		 }
  }

void Send(SOCKET Socket, int ResourceId, ...)
  {
	  va_list ArgPtr;
	  char ResourceString[255], WorkBuffer[255];

	  va_start(ArgPtr, ResourceId);
	  LoadString(hInst, ResourceId, ResourceString, 255);
	  vsprintf(WorkBuffer, ResourceString, ArgPtr);
	  va_end(ArgPtr);

	  wBytesSent += send(Socket, WorkBuffer, strlen(WorkBuffer), 0);

	  if (State != POP_PASS)
		 Display(WorkBuffer);
	  else
		 Display("PASS ********\r\n");
  }