⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2003-01-05_email.cpp

📁 JK Proxy Project - Version 0.1 ------------------------------ This was going to be a proxy serve
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				conn->srvmail[conn->srvmaillen] = 0;

				// check now
				bool chkmail = (bool)CheckMsg(conn->srvmail, mainset.emailsettings.rules);

				// now of all generate (hopefully) unique file name
				CHARPTR sfile = GetFilename();

				// check if messages passes
				if (chkmail == true)
				{
					// message passes
					// connect filename and dir
					spath = ConnectStrings(conn->msgdir, sfile);
					// set terminating zero-byte
					(conn->srvmail)[conn->srvmaillen] = 0;
					// write
					WriteToFile(spath, conn->srvmail);

				}
				else
				{
					// message being blocked
					// connect filename and dir
					spath = ConnectStrings(mainset.emailsettings.trashdir , sfile);
					// set terminating zero-byte
					(conn->srvmail)[conn->srvmaillen] = 0;
					// write
					WriteToFile(spath, conn->srvmail);

				}
				
				// delete pointer
				delete conn->srvmail;
				
				// free memory
				delete sfile;
				delete spath;

				// now we need to delete the mail on the server
				CHARPTR delecmd = new char[11];
				sprintf(delecmd,"DELE %d\x0D\x0A\0",conn->srvcurmsg);
				emailscks->Sendsz(conn->serversock,delecmd);
				delete delecmd;
				
				conn->state = ECS_SDELETE;
			}
			else
			{
				
				// copy line to the end of current buffer
				memcpy(&(conn->srvmail)[conn->srvmaillen], msgstart,msgend-msgstart+1);
				// increate length counter
				(conn->srvmaillen) += (msgend-msgstart+1);
				// copy crlf
				memcpy(&(conn->srvmail)[conn->srvmaillen],CRLF,2);
				// increase counter again
				(conn->srvmaillen) += 2;
			}
		}

		break;

	case ECS_SDELETE:
		// proceed with nxt message
		GetNextMsg(conn);
		break;

	default:
		;
	}
}

int GetNumOfMails(CHARPTR msgstart, CHARPTR msgend)
// extracts the number of emails on the server from STAT response
{
	CHARPTR seek = msgstart;
	CHARPTR seek2;
	UINT temp;

	// first 4 bytes are "+OK ", skip them
	seek += 4;
	// next byte should be first byte of number of emails
	// ensure that seek doesn't point to a space anyway
	while (*seek == 32) seek++;
	// now find end of number by searching next space
	seek2 = seek;
	while (*seek2 != 32) seek2++;

	// extract number and convert to integer
	CHARPTR result = (CHARPTR)CopyAndPtr(seek,seek2-seek);
	
	temp = atoi(result);
	delete result;
	return temp;
}

void ProcessClientMsg(EMAILCONN* conn, CHARPTR msgstart, CHARPTR msgend)
// this procedure processes incoming messages from the email
// client of the specific socket
{
	UINT inum;
	CHARPTR snum;
	// now extract the first 4 character which represent the POP command
	// and convert to lowercase
	CHARPTR cmd = (CHARPTR)CopyAndPtr(msgstart,4);
	strlwr(cmd);
	// convert to integer
	UINT icmd = *(UINT*)cmd;


	// first of check if QUIT command was sent
	if (icmd == POP_QUIT)
	{
		// send goodbye & close connection and leave procedure
		emailscks->Sendsz(conn->clientsock, "+OK good bye\x0D\x0A\0");
		emailscks->Close(conn->clientsock);
		// if connected to server, disconnect
		if (conn->serversock !=0)
			emailscks->Sendsz(conn->serversock, "QUIT\x0D\x0A\0");

		// call close handler manually, it contains important functions
		// for cleanup
		CloseHandler(conn->clientsock);
		return;
	}

	// in which state is this connection?
	switch (conn->state)
	{
	case ECS_CSENTHELLO:
		// sent hello to client, waiting for username
		if (icmd == POP_USER)
		{
			// now extract server, port and real username info
			SERVERUSER* srvuser = ExtractUsernameInfo(msgstart+5,msgend);
			// if zero was returned then username has wrong format
			if (srvuser == 0)
			{
			emailscks->Sendsz(conn->clientsock,
				"-ERR send username in format username@host[:port]\0");
			}
			else
			{
				// ensure that directory exists
				conn->msgdir = EnsureDirectory(srvuser);

				// store username and connect to server
				conn->username = srvuser->user;
				conn->serversock = emailscks->Connect(srvuser->server,srvuser->port);
				// create mapping
				(*connmap)[conn->serversock] = conn;
				// now delete info which we don't need anymore
				delete srvuser->server;
				delete srvuser;
				// set state
				conn->state = ECS_SCONNECT;
			}
		}		
		else
			// wrong command at this state
			emailscks->Sendsz(conn->clientsock,
				"-ERR awaiting USER command\x0D\x0A\0");

		break;

	case ECS_CWAITPASS:
		// password should arrive now
		if (icmd == POP_PASS)
		{
			// forward password to server
			ForwardMessage(conn->serversock,msgstart,msgend);
			conn->state = ECS_SSENTPASS;

		}
		else
			// wrong command at this state
			emailscks->Sendsz(conn->clientsock,
				"-ERR awaiting PASS command\x0D\x0A\0");

		break;

	case ECS_READY:
		// which command was sent?
		switch (icmd)
		{
		case POP_STAT:
			// STAT command
			if (conn->mailschecked == true)
				STATResponse(conn);
			else
			{	conn->savecommand = POP_STAT;
				GetMails(conn);
			}
			break;

		case POP_LIST:
			// LIST command
			if (conn->mailschecked == true)
				LISTResponse(conn);
			else
			{
				conn->savecommand = POP_LIST;
				GetMails(conn);
			}
			break;

		case POP_RETR:
			// extract mail number
			snum = (CHARPTR)CopyAndPtr(msgstart+5,msgend-(msgstart+5)+1);
			// convert to int
			inum = atoi(snum);

			// RETR command
			if (conn->mailschecked == true)
				RETRResponse(conn, inum);
			else
			{
				conn->savecommand = POP_RETR;
				conn->savenum = inum;
				GetMails(conn);
			}
			break;

		case POP_DELE:
			// extract mail number
			snum = (CHARPTR)CopyAndPtr(msgstart+5,msgend-(msgstart+5)+1);
			// convert to int
			inum = atoi(snum);

			// DELE command
			if (conn->mailschecked == true)
				DELEResponse(conn, inum);
			else
			{
				conn->savecommand = POP_DELE;
				conn->savenum = inum;
				GetMails(conn);
			}
			break;


			

		
		}

	default:
		;
	}
}

CHARPTR EnsureDirectory(SERVERUSER* user)
{
	// ensures that the archive directory for a certain user exists
	// and returns string 
	
	// first of all connect host and user to a string (without port)
	CHARPTR temp = (CHARPTR)CopyAndPtr(user->user, strlen(user->user) + 1);
	temp[strlen(temp)] = '@';
	CHARPTR fullusr = ConnectStrings(temp,user->server);
	CHARPTR dir = ConnectStrings(mainset.emailsettings.archivedir,fullusr);

	// create dir
	CreateDir(dir);

	// return directory string
	return dir;
	

	delete temp;
	delete fullusr;
	delete dir;
}

void GetNextMsg(EMAILCONN* conn)
// retrieves next email msg from server
{
	// next msg
	(conn->srvcurmsg)++;
	// done?
	if (conn->srvcurmsg > conn->srvnummails)
	{
		// done receiving emails
		conn->mailschecked = true;
		conn->state = ECS_READY;
		// now get information about all emails in that folder
		conn->srvm = MailDirInfo(conn->msgdir);

		// now process the command which the client originally sent
		switch (conn->savecommand)
		{
		case POP_STAT:
			STATResponse(conn);
			break;
		case POP_LIST:
			LISTResponse(conn);
			break;
		case POP_RETR:
			RETRResponse(conn, conn->savenum);

		}
		
	}
	else
	{
		// get next mail

		// create buffer which is large enough to hold email
		// use + 1 for zero
		conn->srvmail = new char[conn->srvmsglen[conn->srvcurmsg-1]+10];
		conn->srvmaillen = 0;
	
		// build string
		char tmp[12];
		sprintf(tmp,"RETR %u\x0D\x0A\0",conn->srvcurmsg);

		// send
		emailscks->Sendsz(conn->serversock,tmp);
		// set state
		conn->state = ECS_SMSG;
		// indicate that next msg is status line
		conn->first = true;
	}
	
}

void GetMails(EMAILCONN* conn)
// this procedure initiates the receiving of emails from the server
{
	// send STAT command 
	emailscks->Sendsz(conn->serversock,"STAT\x0D\x0A\0");
	conn->state = ECS_SSENTSTAT;

}


SERVERMAILS* MailDirInfo(CHARPTR dir)
// retrieves information about email files in a directory
// and returns a SERVERMAILS struct
{
	// create SERVERMAILS struct
	SERVERMAILS* ret = new SERVERMAILS;
	ret->nummails = 0;
	ret->paths = 0;
	ret->fullsize = 0;
	ret->sizes = 0;
	// add wildcard * to dir
	CHARPTR dirw = ConnectStrings(dir,"/*\0");

#ifdef WIN32
	// *** WIN32 implementation start
	WIN32_FIND_DATA find;

	// now we need to iterate through all files to count the number of file
	HANDLE search = FindFirstFile(dirw,&find);
		
	while (true)
	{	
		// only increase counter if not "." or ".." (check for single
		// period at the beginning of file string
		if (find.cFileName[0] != '.')
			ret->nummails++;

		if (FindNextFile(search,&find) == 0) break;
	}
	FindClose(search);

	// now that we know the number of files we can create
	// the array of pointers
	ret->paths = new CHARPTR [ret->nummails];
	// create array to save sizes of files
	ret->sizes = new UINT [ret->nummails];

	// walk through all files again, but this time, save
	// file paths in array
	search = FindFirstFile(dirw,&find);
	UINT i=0;
	while (true)
	{	
		// only save in array if not "." or ".." (check for single
		// period at the beginning of file string
		if (find.cFileName[0] != '.')
		{
			// copy to new string and save pointer
			ret->paths[i] = (CHARPTR)CopyAndPtr(find.cFileName, strlen(find.cFileName));

			// connect path and filename again for filesize argument
			CHARPTR tmp = ConnectStrings(dir,"/");
			CHARPTR tmp2 = ConnectStrings(tmp,ret->paths[i]);
			// get file size and save in array
			ret->sizes[i] = GetFileLength(tmp2);
			// add to full size
			ret->fullsize += ret->sizes[i];

			// deallocate memory
			delete tmp2;

			i++;

		}

		if (FindNextFile(search,&find) == 0) break;
	}
	FindClose(search);


	// *** WIN32 implementation end
#endif

	// delete connected string
	delete dirw;
	// return struct
	return ret;	

}

void STATResponse(EMAILCONN* conn)
// creates and sends a response to a STAT command from client
{
	// we reserve 22 bytes for the response string
	// response is in form:
	// +OK xxxx yyyyyyyyyy[CR][LF][0]
	// i think 4 digits for the number of emails and 10 digits
	// for the total size should be more than enough
	CHARPTR res = new char[22];
	
	// fill string
	sprintf(res,"+OK %d %d\x0D\x0A\0", conn->srvm->nummails, conn->srvm->fullsize);

	// send message to client
	emailscks->Sendsz(conn->clientsock, res);
	
	conn->state = ECS_READY;
}

void LISTResponse(EMAILCONN* conn)
// creates and sends a response to a LIST command from client
{
	// we reserve 40 bytes for the initial status response:
	// +OK xxxx messages (yyyyyyyyyy octets)[CR][LF]
	// then we need an additional 17 bytes for each message
	// xxxx yyyyyyyyyy[CR][LF]
	// plus 4 bytes for finishing line .[CR][LF][0]
	// i know the digit lengths for message numbers and message
	// size are way to huge but this way there won't be any complications
	CHARPTR res = new char[40 + (17 * conn->srvm->nummails) + 4];
	UINT pos=0;

	// write status line
	pos += sprintf(res, "+OK %d messages (%d octets)\x0D\x0A",
							conn->srvm->nummails, conn->srvm->fullsize);

	// now write line for each message
	for (UINT i=0;i<conn->srvm->nummails;i++)
	{
		pos += sprintf(&res[pos], "%d %d\x0D\x0A", 
					(i+1),conn->srvm->sizes[i]);
	}

	// write finishing line
	sprintf(&res[pos], ".\x0D\x0A\0");

	// send response
	emailscks->Sendsz(conn->clientsock, res);
	
	conn->state = ECS_READY;
}

void RETRResponse(EMAILCONN* conn, UINT inum)
// sends a message to the client (if existing)
{
	// check if message is in correct range
	if ((inum < 0) || (inum > conn->srvm->nummails))
	{
		// error! return error msg
		emailscks->Sendsz(conn->clientsock, 
						"-ERR no such message\x0D\x0A\0");
		return;
	}

	// ok, now try to get file contents
	CHARPTR filecont;
	UINT filelen;
		
	// connect path and file
	CHARPTR tmp  = (CHARPTR)ConnectStrings(conn->msgdir, "/\0");
	CHARPTR tmp2 = (CHARPTR)ConnectStrings(tmp, conn->srvm->paths[inum-1]);
	GetFileCont(tmp2, &filecont, &filelen);

	filelen; // [DBG]

	// if filecont == zero -> failed, file probably deleted
	if (filecont == 0)
	{
		// error! return error msg
		emailscks->Sendsz(conn->clientsock, 
						"-ERR no such message\x0D\x0A\0");
		return;
	}

	// send ok + number of octets
	CHARPTR res = new CHAR[17];
	sprintf(res,"+OK %d\x0D\x0A\0",conn->srvm->sizes[inum-1]);
	emailscks->Sendsz(conn->clientsock, res);
	
	// file contents seems to be loaded correctly, send now
	emailscks->Send(conn->clientsock, filecont, strlen(filecont));
	// and send finishing line
	emailscks->Sendsz(conn->clientsock, "\x0D\x0A.\x0D\x0A\0");

	conn->state = ECS_READY;

}

void DELEResponse(EMAILCONN* conn, UINT inum)
// deletes a message and sends response to client
{
	// connect path and file
	CHARPTR tmp  = (CHARPTR)ConnectStrings(conn->msgdir, "/\0");
	CHARPTR tmp2 = (CHARPTR)ConnectStrings(tmp, conn->srvm->paths[inum-1]);

	// check if file exists
	if (FileExists(tmp2) == false)
	{
		emailscks->Sendsz(conn->clientsock, 
						"-ERR no such message\x0D\x0A\0");
		return;
	}

	// delete file
	KillFile(tmp2);

	// send response
	emailscks->Sendsz(conn->clientsock, 
					"+OK message deleted\x0D\x0A\0");

	conn->state = ECS_READY;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -