home *** CD-ROM | disk | FTP | other *** search
- /* WSMTPSrv.C - Windows SMTP Server
- - WinSock V1.1 required
-
- Author: Ian Blenke
-
- Ian Blenke cannot be held responsible for damages, expressed or implied, for
- the use of this software. No commercial use can be made of this product
- without the consent of the author. No profit of any kind can be made on the
- sale or distribution of this program. If you wish to distribute this program
- with other samples of WinSock programming, you must first contact the author
- so that he can keep accurate records of its usage. If you write any programs
- based on this source code, you may not sell them for any profit without the
- written consent of the author. If you incorporate this source code into a
- public domain program, all the author requires is a notification that "part
- of the code was written by Ian Blenke" and some form of notification that
- his name was used in the public domain software distribution. This does not
- represent a contract on the part of the author. If any issues cannot clearly
- be resolved by reading this text, immediately contact the author.
-
- I don't like such agreements, but in today's world of lawyers and lawbreakers
- I have little other choice. Enjoy!
- */
-
- #include "WSMTPSrv.h"
-
- /* DEBUGIT();
- Purpose: To print debugging messages to the debugging window/console.
- */
- /*VOID DEBUGIT( LPSTR lpString)
- {
- static char szErrors[256];
-
- wsprintf((LPSTR)szErrors, (LPSTR)"WSMTPD: %s\n\r", lpString);
- OutputDebugString( (LPSTR)szErrors );
- } /**/
-
- /* WinMain();
- Purpose: The entry point for our app.
- */
- UINT PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpszCmdLine, int nCmdShow)
- {
- MSG msg;
- WORD wVersionRequested;
- WSADATA wsaData;
- DLGPROC dlgProc;
- WNDCLASS wndclass;
- HICON hIcon;
-
- hInst=hInstance;
- lstrcpy((LPSTR)szAppName, (LPSTR)APP_NAME);
-
- //DEBUGIT("WinMain() Begin");
-
- if(hPrevInstance)
- {
- smtpError(IDS_PREV_INSTANCE);
- return(NULL);
- }
-
- wVersionRequested=WSVERSION;
- if(WSAStartup(wVersionRequested, (LPWSADATA)&wsaData))
- {
- smtpError(IDS_NO_WINSOCK);
- return(NULL);
- }
- if((LOBYTE(wsaData.wVersion)!=1) ||
- (HIBYTE(wsaData.wVersion)!=1))
- {
- smtpError(IDS_BAD_VERSION);
- WSACleanup();
- //DEBUGIT("WinSock version is not v1.1");
- return(NULL);
- }
-
- #ifdef USE_3D
- Ctl3dRegister(hInst);
- Ctl3dAutoSubclass(hInst);
- #endif /*USE_3D*/
-
-
- dlgProc=(DLGPROC)MakeProcInstance((FARPROC)DlgProc, hInst);
- hWndDlg=CreateDialog(hInst, (LPSTR)dlgWSMTPSRV,
- GetDesktopWindow(), dlgProc);
-
- if(!hWndDlg)
- {
- smtpError(IDS_SMTP_INIT);
- #ifdef USE_3D
- Ctl3dUnregister(hInst);
- #endif // USE_3D
- WSACleanup();
- //DEBUGIT("Modeless dialog window could not be opened");
- return(NULL);
- }
-
- hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONEMPTY));
-
- if(hIcon != NULL)
- {
- SetProp(hWndDlg, "icon", hIcon);
- }
- // else DEBUGIT("IDI_ICONEMPTY Resource not found");
-
- SetClassWord(hWndDlg, GCW_HICON, NULL);
-
- ShowWindow(hWndDlg, nCmdShow);
-
- //DEBUGIT("Starting smtpInit");
-
- if(smtpInit(INI_FILE))
- {
- DestroyWindow(hWndDlg);
- // smtpError(IDS_SMTP_INIT);
- #ifdef USE_3D
- Ctl3dUnregister(hInst);
- #endif /* USE_3D */
- WSACleanup();
- //DEBUGIT("Daemon initialization error");
- return(NULL);
- }
-
- while(GetMessage(&msg, NULL, 0, 0))
- {
- if(!IsDialogMessage(hWndDlg, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- #ifdef USE_3D
- Ctl3dUnregister(hInst);
- #endif
-
- WSACleanup();
-
- //DEBUGIT("WinMain() End");
-
- return msg.wParam;
- } /* WinMain */
-
-
- /* LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM);
- Purpose: To handle the main dialog user intervention.
- Given/Returns: Standard Dialog procedure
- */
- LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam,
- LPARAM lParam)
- {
- HICON hIcon;
-
- switch(Msg)
- {
- case WM_INITDIALOG:
- {
- if(iLogLevel==LOG_LOW)
- {
- CheckRadioButton(hWnd, IDR_NORMAL, IDR_DEBUG,
- IDR_NORMAL);
- }
- else
- {
- CheckRadioButton(hWnd, IDR_NORMAL, IDR_DEBUG,
- IDR_DEBUG);
- }
- SetDlgItemText(hWnd, IDE_PATH, (LPSTR)szLocalMailPath);
- SetDlgItemText(hWnd, IDE_HOSTNAME, (LPSTR)szLocalHostName);
- return(TRUE);
- }
- break;
-
- case WM_COMMAND:
- {
- switch(wParam)
- {
- case IDR_NORMAL:
- {
- iLogLevel=LOG_LOW;
- return(TRUE);
- }
-
- case IDR_DEBUG:
- {
- iLogLevel=LOG_HIGH;
- return(TRUE);
- }
-
- case IDB_PATH:
- {
- int iError;
- DWORD dwError;
-
- if(iError=GetOpenFileName((OPENFILENAME FAR *)&ofnMailPath))
- {
- WritePrivateProfileString(SECTION_MAIN, ENTRY_MAILPATH,
- (LPSTR)szLocalMailPath,
- (LPSTR)INI_FILE);
- SetDlgItemText(hWndDlg, IDE_PATH, (LPSTR)szLocalMailPath);
- }
- else
- { // Debugging
- dwError=CommDlgExtendedError();
- }
- return(TRUE);
- }
- }
- break;
-
- // All of this, for a changing Icon - Sheesh
- case WM_PAINT:
- {
- if(IsIconic(hWndDlg))
- {
- PAINTSTRUCT ps;
- HDC hDC;
- DWORD dwOrg;
- HICON hIcon = GetProp(hWndDlg, "icon");
-
- if(hIcon != NULL)
- {
- hDC=BeginPaint(hWndDlg, &ps);
-
- dwOrg = GetWindowOrg(hDC);
- SendMessage(hWndDlg, WM_ICONERASEBKGND, hDC, 0L);
- DrawIcon(hDC, LOWORD(dwOrg)+2, HIWORD(dwOrg)+2, hIcon);
- EndPaint(hWndDlg, &ps);
- return(TRUE);
- }
- }
- }
- break;
-
- case WM_ERASEBKGND:
- {
- if(IsIconic(hWndDlg)) return(TRUE);
- else return(FALSE);
- }
-
- case WM_CLOSE:
- {
- RemoveProp(hWndDlg, "icon");
- netClose();
- DestroyWindow(hWndDlg);
- return(TRUE);
- }
- break;
-
- case WM_QUERYDRAGICON:
- {
- HICON hIcon;
-
- return(hIcon = GetProp(hWndDlg, "icon"));
- }
-
- /* Periodically check for mail until user reads it */
- case WM_TIMER:
- {
- if(!smtpMailCheck(szLocalMailPath))
- {
- KillTimer(hWndDlg, (UINT)wParam);
- SetWindowText(hWndDlg, (LPSTR)STRING_NOMAIL);
- }
- else
- {
- SetWindowText(hWndDlg, (LPSTR)STRING_HAVEMAIL);
- }
- return(TRUE);
- }
- break;
-
- /* Don't let the user ReSize/Maximize the window! */
- case WM_INITMENUPOPUP:
- {
- if(HIWORD(lParam))
- {
- HMENU hSystemMenu;
-
- hSystemMenu = GetSystemMenu(hWndDlg, FALSE);
- EnableMenuItem(hSystemMenu, SC_SIZE, MF_GRAYED);
- EnableMenuItem(hSystemMenu, SC_MAXIMIZE, MF_GRAYED);
- }
- }
- break;
-
- case WM_DESTROY:
- {
- PostQuitMessage(0);
- return(TRUE);
- }
- break;
- }
- }
- return(FALSE);
- } /* dlgProc() */
-
-
- /* void smtpError(int);
- Purpose: To print out a resource string with parameters
- Given: ResourceID of format string, and variable arguements.
- Returns: Nothing.
- */
- void smtpError(int ResourceID, ...)
- {
- char szString[MAXLINE];
- char szBuffer[MAXLINE];
- va_list vaArgs;
- LPSTR lpArg1, lpArg2;
-
- va_start( vaArgs, ResourceID);
- lpArg1 = va_arg( vaArgs, LPSTR);
- lpArg2 = va_arg( vaArgs, LPSTR);
-
- if(IsIconic(hWndDlg)) // If in server mode, no modals!
- {
- smtpLog(LOG_HIGH | LOG_TIME, ResourceID, vaArgs);
- return;
- }
-
- if(!LoadString(hInst, ResourceID, (LPSTR)szString,
- MAXLINE))
- return;
-
- wsprintf((LPSTR)szBuffer, (LPSTR)szString, lpArg1, lpArg2);
-
- //DEBUGIT(szBuffer);
- MessageBeep(MB_ICONEXCLAMATION);
- MessageBox(NULL, (LPSTR)szBuffer, (LPSTR)szAppName,
- MB_OK | MB_ICONEXCLAMATION);
- return;
- } /* smtpError */
-
-
- /* void smtpLog(int, ...);
- Purpose: To print an item in the "log" listbox.
- Given: Resource ID and variable args.
- Returns: Nothing
- */
- void smtpLog(int iLevel, int ResourceID, ...)
- {
- char szString[MAXLINE];
- char szLine[MAXLINE];
- char szTime[30];
- LPSTR lpArg1, lpArg2;
- va_list vaArgs;
- DWORD dwCount;
-
- if((iLevel&(LOG_TIME-1))<iLogLevel) return; // Only log what we want
-
- va_start( vaArgs, ResourceID);
-
- if(!LoadString(hInst, ResourceID, (LPSTR)szLine, MAXLINE))
- return;
-
- lpArg1=va_arg(vaArgs, LPSTR);
- lpArg2=va_arg(vaArgs, LPSTR);
-
- wsprintf((LPSTR)szString, (LPSTR)szLine, lpArg1, lpArg2);
-
- if(iLevel&LOG_TIME)
- {
- netGetTimeAndDate((LPSTR)szTime, sizeof(szTime));
- wsprintf((LPSTR)szLine, "%s> %s", (LPSTR)szTime, (LPSTR)szString);
- }
- else
- {
- lstrcpy((LPSTR)szLine, (LPSTR)szString);
- }
- //DEBUGIT(szLine);
- SendDlgItemMessage(hWndDlg, IDL_LOG, LB_ADDSTRING, 0,
- (LPARAM)(LPCSTR)szLine);
-
- dwCount=SendDlgItemMessage(hWndDlg, IDL_LOG, LB_GETCOUNT, 0, 0l);
- if(dwCount>MAXITEMS)
- {
- SendDlgItemMessage(hWndDlg, IDL_LOG, LB_RESETCONTENT, 0, 0l);
- wsprintf((LPSTR)szLine, "%s> Reset Log - over %d lines", (LPSTR)szTime,
- MAXITEMS);
- //DEBUGIT(szLine);
- SendDlgItemMessage(hWndDlg, IDL_LOG, LB_ADDSTRING, 0,
- (LPARAM)(LPCSTR)szLine);
- }
- } /* smtpLog */
-
-
- /* BOOL smtpInit(PSTR);
- Purpose: To setup the SMTP protocol and structures.
- Given: A filename.
- Returns: TRUE on error, FALSE if not.
- */
- BOOL smtpInit(PSTR pFilename)
- {
- LPSTR lpString;
- HANDLE hMenu;
-
- ofnMailPath.lStructSize=sizeof(ofnMailPath);
- ofnMailPath.hwndOwner=hWndDlg;
- ofnMailPath.hInstance=hInst;
- szMailPathFilter[0]='\0';
- LoadString(hInst, IDS_FILTER,
- (LPSTR)szMailPathFilter, sizeof(szMailPathFilter));
- ofnMailPath.lpstrFilter=(LPSTR)szMailPathFilter;
- ofnMailPath.nFilterIndex=2;
- ofnMailPath.lpstrCustomFilter=(LPSTR)NULL;
- ofnMailPath.lpstrFile=(LPSTR)szLocalMailPath;
- ofnMailPath.nMaxFile=sizeof(szLocalMailPath);
- ofnMailPath.lpstrFileTitle=(LPSTR)NULL;
- ofnMailPath.lpstrInitialDir=(LPSTR)NULL;
- ofnMailPath.lpstrTitle=(LPSTR)szAppName;
- ofnMailPath.Flags=OFN_CREATEPROMPT | OFN_NOREADONLYRETURN;
- ofnMailPath.lpstrDefExt=(LPSTR)NULL;
-
- // Initialize network windows & such
- if(netInit()) return(TRUE);
-
- iLogLevel=GetPrivateProfileInt(SECTION_MAIN, ENTRY_DEBUG,
- LOG_HIGH, (LPSTR)pFilename);
- GetPrivateProfileString(SECTION_MAIN, ENTRY_MAILPATH,
- (LPSTR)DEFAULTMAILFILE,
- (LPSTR)szLocalMailPath,
- sizeof(szLocalMailPath),
- (LPSTR)pFilename);
-
- if(iLogLevel==LOG_LOW)
- {
- CheckRadioButton(hWndDlg, IDR_NORMAL, IDR_DEBUG,
- IDR_NORMAL);
- }
- else
- {
- CheckRadioButton(hWndDlg, IDR_NORMAL, IDR_DEBUG,
- IDR_DEBUG);
- }
- SetDlgItemText(hWndDlg, IDE_PATH, (LPSTR)szLocalMailPath);
- SetDlgItemText(hWndDlg, IDE_HOSTNAME, (LPSTR)szLocalHostName);
-
- return(FALSE);
- } /* smtpInit */
-
-
- /* BOOL smtpServer(LPSMTPCLIENT);
- Purpose: To be the heart & soul of the SMTP
- server.
- Given: pointer to the Client that was active.
- Returns: FALSE
- Notes: This is the heart & soul of the beast.
- */
- BOOL smtpServer(LPSMTPCLIENT lpClient)
- {
- static char szLine[MAXSNDBUFF]; // These are still holdovers
- static char szPaddedLine[MAXSNDBUFF]; // They should be replaced
- PSTR pLine;
- int iDebug;
- BOOL bCmdOk;
-
- if(!lpClient) return(TRUE);
-
- //DEBUGIT("smtpServer() Begin");
-
- // 8BITMIME hack
- if((lpClient->iExtendedFlags & ESMTP_8BITMIME) &&
- (lpClient->iState == STATE_WAIT_FOR_DOT))
- {
- //DEBUGIT("ESMTP_8BITMIME && STATE_WAIT_FOR_DOT");
- while(clientReceiveBlock(lpClient, szLine, sizeof(szLine)))
- {
- if(lpClient->hfFile!=HFILE_ERROR)
- {
- iDebug=_lwrite(lpClient->hfFile,
- (LPSTR)szLine, lstrlen((LPSTR)szLine));
- }
- } // While there is data
- } // If in DATA state with 8BITMIME active.
-
- // This is a hack for when a client QUIT's.
- bConnectionQuit=FALSE;
-
- // Get as many lines as are waiting
- while(!bConnectionQuit &&
- (clientReceiveLine(lpClient, szLine, sizeof(szLine)) >= 0))
- {
- // Treat them one at a time
- switch(lpClient->iState)
- { // Command mode?
- case STATE_WAIT_FOR_COMMAND:
- {
- int iLoop;
-
- //DEBUGIT("STATE_WAIT_FOR_COMMAND");
- if(!(*szLine))
- {
- smtpSendMessage(lpClient, 500, MSG_UNKNOWN);
- continue; // CR, LF, or '\0' came across
- }
-
- pLine=szLine;
- while((*pLine!='\0')&&(*pLine!=' ')&&(*pLine!='\n'))
- pLine++;
- AnsiLower((LPSTR)szLine);
- if(*pLine!='\0')
- {
- *(pLine++)='\0';
- }
- // szLine now holds the lowercase command
- // pLine points to the remaining parameters
- iLoop=0;
- bCmdOk=FALSE;
- while(smtpCodesTable[iLoop].SMTPCommand != NULL)
- {
- if(lstrcmp((LPSTR)smtpCodesTable[iLoop].SMTPCommand,
- (LPSTR)szLine)==0)
- {
- smtpParser(lpClient, smtpCodesTable[iLoop].SMTPCode, pLine);
- bCmdOk=TRUE;
- break;
- }
- iLoop++;
- }
- if(!bCmdOk) smtpSendMessage(lpClient, 500, MSG_UNKNOWN);
- }
- break;
-
- // Data mode?
- case STATE_WAIT_FOR_DOT:
- {
- //DEBUGIT("STATE_WAIT_FOR_DOT");
- if((szLine[0]=='.')&&(szLine[1]=='\0'))
- {
- lpClient->iState=STATE_WAIT_FOR_COMMAND;
- if(lpClient->hfFile!=HFILE_ERROR)
- {
- _lclose(lpClient->hfFile);
- }
- lpClient->hfFile=HFILE_ERROR;
- // Handle MAIL/SAML/SOML as MAIL
- if((lpClient->iMessageType==CMDMAIL)||
- (lpClient->iMessageType==CMDSAML)||
- (lpClient->iMessageType==CMDSOML))
- {
- smtpAppendToFile(lpClient, szLocalMailPath,
- lpClient->szFile);
- }
- // Handle SAML/SEND as SEND also
- if((lpClient->iMessageType==CMDSAML)||
- (lpClient->iMessageType==CMDSEND))
- {
- smtpDisplayFile(lpClient, lpClient->szFile);
- }
- smtpSendMessage(lpClient, 250, MSG_OK);
- continue;
- }
- else if((szLine[0]=='.')&&(szLine[1]=='.'))
- { // Byte stuff it! Someone tried to send a '.' in their
- // message. Only the first '.' is doubled.
- lstrcpy((LPSTR)szPaddedLine, (LPSTR)(szLine+1));
- lstrcpy((LPSTR)szLine, (LPSTR)szPaddedLine);
- }
- // All non '.' lines are stored.
- if(lpClient->hfFile!=HFILE_ERROR)
- {
- wsprintf((LPSTR)szPaddedLine, "%s\r\n", (LPSTR)szLine);
- iDebug=_lwrite(lpClient->hfFile,
- (LPSTR)szPaddedLine, lstrlen((LPSTR)szPaddedLine));
- }
- continue;
- } /* case(data mode) */
- break;
- } /* switch(mode); */
- if(bConnectionQuit) break;
- } /* while(lines exist);*/
- //DEBUGIT("smtpServer() End");
- return(FALSE);
- } /* smtpServer() */
-
-
- /* BOOL smtpParser(LPSMTPCLIENT, int, LPSTR);
- Purpose: The actual parser of the SMTP "language"
- Given: Client pointer, Token of command, and it's arguments
- */
- BOOL smtpParser(LPSMTPCLIENT lpClient, int iToken, LPSTR lpArgs)
- {
- //DEBUGIT("smtpParser() Begin");
- switch(iToken)
- {
- // HELO - SMTP client is identifying itself
- case CMDHELO:
- {
- //DEBUGIT("CMDHELO Begin");
- if(lstrcmpi(lpClient->szPeer, lpArgs) != 0)
- {
- if(lstrlen(lpArgs) == 0)
- smtpSendMessage(lpClient, 250, MSG_WHOAREYOU_S_S,
- (LPSTR)szLocalHostName,
- lpClient->szPeer);
- else
- smtpSendMessage(lpClient, 250, MSG_WHOAREYOU_S_S_S,
- (LPSTR)szLocalHostName,
- lpClient->szPeer,
- lpArgs);
- }
- else
- {
- smtpSendMessage(lpClient, 250, MSG_HELLO_S_S,
- (LPSTR)szLocalHostName,
- lpArgs);
- }
- //DEBUGIT("CMDHELO End");
- return(FALSE);
- }
-
- // EHLO - ESMTP client is identifying itself
- case CMDEHLO:
- {
- //DEBUGIT("CMDEHLO Begin");
- if(lstrcmpi(lpClient->szPeer,
- lpArgs) != 0)
- {
- if(lstrlen(lpArgs) == 0)
- smtpSendMessage(lpClient, 250, MSG_HWOAREYOU_S_S,
- (LPSTR)szLocalHostName,
- lpClient->szPeer);
- else
- smtpSendMessage(lpClient, 250, MSG_HWOAREYOU_S_S_S,
- (LPSTR)szLocalHostName,
- lpClient->szPeer,
- lpArgs);
- }
- else
- {
- smtpSendMessage(lpClient, 250, MSG_EHLLO_S_S,
- (LPSTR)szLocalHostName,
- lpArgs);
- }
- lpClient->iExtendedFlags |= ESMTP_EHLO_USED;
- //DEBUGIT("CMDEHLO End");
- return(FALSE);
- }
-
- // Oh, joy.
- case CMDSEND: // Send user a message to screen
- case CMDSAML: // Send to screen AND store as mail
- case CMDSOML: // Send to screen OR store as mail
- case CMDMAIL: // Store as mail to user
- {
- LPSTR lpPtr;
- LPSTR lpWalk;
- LPSTR lpMark;
- BOOL bSentReply = FALSE;
-
- //DEBUGIT("CMDMAIL Begin");
- lpClient->iMessageType=iToken;
- if(lpClient->bHaveFrom)
- {
- smtpSendMessage(lpClient, 503, MSG_ALREADYSENDER);
- return(FALSE);
- }
- else
- {
- if(*lpArgs=='\0') break;
- if( ( lpPtr = smtpSkipWord( lpClient, lpArgs, (LPSTR)"from" )) != NULL )
- {
- lpClient->bHaveFrom=TRUE;
- // No long name crashes!
- if(lstrlen(lpPtr)>=sizeof(lpClient->szFrom))
- lpPtr[sizeof(lpClient->szFrom)-1] = '\0';
-
- // 8BITMIME and other ESMTP hacks
- if(lpClient->iExtendedFlags & ESMTP_EHLO_USED)
- {
- // Check for ESMTP commands after the Sender's address
- lpWalk=lpPtr;
- while((*lpWalk!='>') && *lpWalk ) lpWalk++;
- if((*lpWalk)&&(*(lpWalk+1)))
- {
- if(*(++lpWalk)==' ')
- {
- while(*lpWalk==' ') *lpWalk++ = '\0';
- lpMark=lpWalk;
- while((*lpWalk!='=') && *lpWalk ) lpWalk++;
- if(*lpWalk) *lpWalk++ = '\0';
- if(lstrcmpi(lpMark, "BODY") == 0)
- {
- lpMark=lpWalk;
- while((*lpWalk!=' ') && *lpWalk ) lpWalk++;
- if(*lpWalk) *lpWalk++ = '\0';
- if(lstrcmpi(lpMark, "8BITMIME") == 0)
- {
- lpClient->iExtendedFlags |= ESMTP_8BITMIME;
- bSentReply=TRUE;
- smtpSendMessage(lpClient, 250, MSG_SENDEROK_8BITMIME_S,
- (LPSTR)lpPtr);
- } // if 8BITMIME found
- } // if BODY= found
- } // if address is followed by a space
- } // if something was found after the address
- } // if extended commands are in effect
-
- lstrcpy(lpClient->szFrom,
- lpPtr);
- if(!bSentReply) smtpSendMessage(lpClient, 250, MSG_SENDEROK_S,
- lpPtr);
- //DEBUGIT("CMDMAIL End (Extended)");
- return(FALSE);
- }
- // a 501 error was already sent
- //DEBUGIT("CMDMAIL End (Already Sender)");
- return(FALSE);
- }
- //DEBUGIT("CMDHELO End (Normal)");
- } break;
-
- // RCPT - Client is identifying recipient's ID
- case CMDRCPT:
- {
- LPSTR lpPtr;
-
- //DEBUGIT("CMDRCPT Begin");
- if( *lpArgs == '\0' ) break;
- if( ( lpPtr = smtpSkipWord( lpClient, lpArgs, (LPSTR)"to" )) != NULL )
- {
- // No long name crashes!
- if(lstrlen(lpPtr)>=sizeof(lpClient->szTo))
- lpPtr[sizeof(lpClient->szTo)-1] = '\0';
- lstrcpy(lpClient->szTo,
- lpPtr);
- smtpSendMessage( lpClient, 250, MSG_RECIPIENTOK_S,
- lpPtr );
- //DEBUGIT("CMDRCPT End (Recipient ok)");
- return(FALSE);
- }
- // A 501 error was already sent
- //DEBUGIT("CMDRCPT End (???)");
- return(FALSE);
- } break;
-
- // DATA - Client is sending actual mail message
- case CMDDATA:
- {
- HFILE hfFile;
- char szFile[MAXFILENAME];
- OFSTRUCT ofOpenFileStruct;
-
- //DEBUGIT("CMDDATA Begin");
- if(!lpClient->bHaveFrom)
- {
- smtpSendMessage(lpClient, 503, MSG_NEEDMAIL);
- //DEBUGIT("CMDDATA End (Need mail?)");
- return(FALSE);
- }
- // Open a temporary file
- GetTempFileName(0, (LPSTR)STRING_PREFIX, 0, (LPSTR)szFile);
- hfFile=OpenFile((LPSTR)szFile, (OFSTRUCT FAR *)&ofOpenFileStruct,
- OF_CREATE | OF_WRITE | OF_SHARE_EXCLUSIVE);
-
- if(hfFile==HFILE_ERROR)
- {
- smtpSendMessage(lpClient, 503, MSG_NOTEMP);
- //DEBUGIT("CMDDATA End (No temporary file)");
- return(FALSE);
- }
- // Ok, everything is ready to start the message.
- lpClient->iState=STATE_WAIT_FOR_DOT;
- lpClient->hfFile=hfFile;
- lstrcpy(lpClient->szFile,
- (LPSTR)szFile);
-
- smtpMakeHeader(lpClient, hfFile, lpClient->szPeer,
- lpClient->szFrom,
- lpClient->szTo);
-
- if(lpClient->iExtendedFlags & ESMTP_8BITMIME)
- smtpSendMessage(lpClient, 354, MSG_SEND8BITMIME);
- else
- smtpSendMessage(lpClient, 354, MSG_SENDDATA);
-
- //DEBUGIT("CMDDATA End");
- return(FALSE);
- }
-
- case CMDRSET:
- {
- //DEBUGIT("CMDRSET Begin");
- lpClient->iState=STATE_WAIT_FOR_COMMAND;
- lpClient->iExtendedFlags=ESMTP_NONE;
- lpClient->bHaveFrom=FALSE;
- lpClient->szFrom[0]='\0';
- lpClient->szTo[0]='\0';
- smtpSendMessage(lpClient, 250, MSG_RESET);
- //DEBUGIT("CMDRSET End");
- return(FALSE);
- }
-
- case CMDVRFY:
- {
- //DEBUGIT("CMDVRFY Begin");
- smtpSendMessage(lpClient, 250, MSG_IDONTDOTHATYET);
- //DEBUGIT("CMDVRFY Begin");
- return(FALSE);
- }
-
- case CMDHELP:
- {
- //DEBUGIT("CMDHELP Begin");
- if(*lpArgs=='\0')
- {
- smtpSendHelp(lpClient, NULL);
- }
- else smtpSendHelp(lpClient, lpArgs);
- //DEBUGIT("CMDHELP End");
- return(FALSE);
- } break;
-
- case CMDNOOP:
- {
- //DEBUGIT("CMDNOOP Begin");
- smtpSendMessage(lpClient, 200, MSG_OK);
- //DEBUGIT("CMDNOOP Begin");
- return(FALSE);
- }
-
- case CMDQUIT:
- {
- //DEBUGIT("CMDQUIT Begin");
- smtpSendMessage(lpClient, 221, MSG_GOODBYE_S,
- (LPSTR)szLocalHostName);
- smtpDestroyClient(lpClient);
- bConnectionQuit=TRUE;
- //DEBUGIT("CMDQUIT End");
- return(FALSE);
- }
-
- case CMDVERB:
- {
- //DEBUGIT("CMDVERB Begin");
- smtpSendMessage(lpClient, 200, MSG_VERBOSEMODE);
- //DEBUGIT("CMDVERB End");
- return(FALSE);
- }
-
- case CMDONEX:
- {
- //DEBUGIT("CMDONEX Begin");
- smtpSendMessage(lpClient, 200, MSG_ONETRANSACTION);
- //DEBUGIT("CMDONEX End");
- return(FALSE);
- }
-
- case CMDTICK:
- {
- //DEBUGIT("CMDTICK Begin");
- smtpSendMessage(lpClient, 250, MSG_OK);
- //DEBUGIT("CMDTICK End");
- return(FALSE);
- }
-
- case CMDXWIN3:
- {
- //DEBUGIT("CMDXWIN3 Begin");
- smtpSendMessage(lpClient, 250, MSG_WIN3OK);
- //DEBUGIT("CMDXWIN3 End");
- return(FALSE);
- }
-
- case CMDDBGQSHOW:
- {
- //DEBUGIT("CMDDBGQSHOW Begin");
- smtpSendMessage(lpClient, 200, MSG_SHOWQ);
- //DEBUGIT("CMDDBGQSHOW End");
- return(FALSE);
- }
-
- case CMDDBGDEBUG:
- {
- //DEBUGIT("CMDDBGDEBUG Begin");
- smtpSendMessage(lpClient, 200, MSG_DEBUGSET);
- //DEBUGIT("CMDDBGDEBUG End");
- return(FALSE);
- }
-
- case CMDMULT:
- {
- //DEBUGIT("CMDMULT Begin");
- smtpSendMessage(lpClient, 250, MSG_OK);
- //DEBUGIT("CMDMULT End");
- return(FALSE);
- }
-
- case CMDERROR:
- //DEBUGIT("CMDERROR");
- default:
- break;
- }
- smtpSendMessage(lpClient, 500, MSG_UNKNOWN);
- //DEBUGIT("smtpParser() End");
- return(FALSE);
- } /* smtpParser() */
-
-
- /* void smtpMakeHeader(LPSMTPCLIENT, HFILE, LPSTR, LPSTR, LPSTR);
- Purpose: To create the "header" portion of the mail
- file.
- Given: Client pointer, Open (and valid) file handle,
- Peer name, From and To strings.
- Returns: Nothing.
- */
- void smtpMakeHeader(LPSMTPCLIENT lpClient, HFILE hfFile, LPSTR lpPeer,
- LPSTR lpFrom, LPSTR lpTo)
- {
- int iSize;
- char szTime[30];
- char szBuffer[MAXLINE];
- LPSOCKADDR_IN lpsaHostAddr;
-
- //DEBUGIT("smtpMakeHeader() Begin");
- lpsaHostAddr=(LPSOCKADDR_IN)&(lpClient->saPeer);
-
- netGetTimeAndDate((LPSTR)szTime, sizeof(szTime));
-
- iSize=wsprintf((LPSTR)szBuffer, "\r\nFrom %s %s\r\n",
- lpFrom, (LPSTR)szTime);
- _lwrite(hfFile, (LPSTR)szBuffer, iSize);
-
- iSize=wsprintf((LPSTR)szBuffer, "X-Envelope-To: %s\r\n",
- lpTo);
- _lwrite(hfFile, szBuffer, iSize);
-
- iSize=wsprintf((LPSTR)szBuffer, "Return-Path: %s\r\n",
- lpFrom);
- _lwrite(hfFile, (LPSTR)szBuffer, iSize);
-
- if(lpClient->iExtendedFlags & ESMTP_8BITMIME)
- {
- iSize=wsprintf((LPSTR)szBuffer,
- "Received: from %s [%s] by %s (1.0/WINSMTPSRV/8BITMIME)\r\n",
- lpPeer,
- inet_ntoa(lpsaHostAddr->sin_addr),
- /* inet_ntoa() and [%s] or this and [%d.%d.%d.%d], take your pick
- lpsaHostAddr->sin_addr.S_un.S_un_b.s_b1,
- lpsaHostAddr->sin_addr.S_un.S_un_b.s_b2,
- lpsaHostAddr->sin_addr.S_un.S_un_b.s_b3,
- lpsaHostAddr->sin_addr.S_un.S_un_b.s_b4,
- */
- (LPSTR)szLocalHostName);
- }
- else
- {
- iSize=wsprintf((LPSTR)szBuffer,
- "Received: from %s [%s] by %s (1.61/WINSMTPSRV)\r\n",
- lpPeer,
- inet_ntoa(lpsaHostAddr->sin_addr),
- (LPSTR)szLocalHostName);
- }
-
- _lwrite(hfFile, (LPSTR)szBuffer, iSize);
-
- // Log incoming to/from
- wsprintf((LPSTR)szBuffer, "Message from: %s to: %s",
- lpFrom, lpTo);
- SendDlgItemMessage(hWndDlg, IDL_LOG, LB_ADDSTRING, 0,
- (LPARAM)(LPCSTR)szBuffer);
- //DEBUGIT("smtpMakeHeader() End");
- return;
- } /* smtpMakeHeader */
-
-
- /* void smtpSendHelp(LPSMTPCLIENT, LPSTR);
- Purpose: To give the remote user help (not batch, obviously)
- Given: Client Index, Topic
- Returns: Nothing.
- */
- void smtpSendHelp(LPSMTPCLIENT lpClient,LPSTR lpTopic)
- {
- LPSTR lpLine;
- int iLoop;
- WORD wTopic;
- char szBuffer[MAXSNDBUFF];
-
- //DEBUGIT("smtpSendHelp() Begin");
- if(lpTopic!=NULL)
- {
- lpLine=lpTopic;
-
- // pLine points to the HELP parameters
- iLoop=0;
- wTopic=CMDHELP;
- while(smtpCodesTable[iLoop].SMTPCommand != NULL)
- {
- if(lstrcmp((LPSTR)smtpCodesTable[iLoop].SMTPCommand,
- lpLine)==0)
- {
- wTopic=(WORD)smtpCodesTable[iLoop].SMTPCode;
- break;
- }
- iLoop++;
- }
- }
- else wTopic=CMDHELP;
-
- smtpSendMessage(lpClient, 214, wTopic);
-
- // Kludge
- if(lpTopic==NULL)
- {
- lstrcpy((LPSTR)szBuffer, "HELP");
- }
- else
- {
- lstrcpy((LPSTR)szBuffer, (LPSTR)smtpCodesTable[iLoop].SMTPCommand);
- AnsiUpper((LPSTR)szBuffer);
- }
-
- smtpSendMessage(lpClient, 214, MSG_END_HELP_S, (LPSTR)szBuffer);
- //DEBUGIT("smtpSendHelp() End");
- return;
- } /* smtpSendHelp */
-
-
- /* LPSTR smtpSkipWord(LPSMTPCLIENT, LPSTR, LPSTR);
- Purpose: To skip over words not neccisary on an SMTP line.
- Given: Client pointer, string to examine, word to skip
- Returns: NULL if error, rest of line if not
- */
- LPSTR smtpSkipWord(LPSMTPCLIENT lpClient, LPSTR lpString, LPSTR lpWord)
- {
- LPSTR lpTemp;
-
- //DEBUGIT("smtpSkipWord() Begin");
- while((*lpString==' ')||(*lpString=='\t')) lpString++;
- lpTemp=lpString;
- while((*lpString!='\0')&&(*lpString!=':')&&
- !((*lpString==' ')||(*lpString=='\t'))) lpString++;
- while((*lpString==' ')||(*lpString=='\t')) *(lpString++)=='\0';
- if(*lpString!=':')
- {
- smtpSendMessage(lpClient, 501, MSG_SYNTAXERROR);
- return(NULL);
- }
- *(lpString++)='\0';
- while((*lpString==' ')||(*lpString=='\t')) lpString++;
- if(lstrcmpi(lpTemp, lpWord))
- {
- smtpSendMessage(lpClient, 501, MSG_SYNTAXERROR);
- return(NULL);
- }
- //DEBUGIT("smtpSkipWord() End");
- return(lpString);
- } /* smtpSkipWord */
-
-
- /* void smtpAppendToFile(LPSMTPCLIENT, LPSTR, LPSTR);
- Purpose: To copy one file to the end of another.
- Given: Pointer to a SMTPCLIENT for error messages,
- Filename of the file to append to,
- Filename of the file to append from.
- Returns: Nothing.
- */
- void smtpAppendToFile(LPSMTPCLIENT lpClient, LPSTR lpTo, LPSTR lpFrom)
- {
- HFILE hTo, hFrom;
- char szBuffer[MAXSNDBUFF];
- int iSize;
- OFSTRUCT ofToFileStruct,
- ofFromFileStruct;
-
- //DEBUGIT("smtpAppendToFile() Begin");
- // Open the MAIL file for reading
- hTo=OpenFile(lpTo, (OFSTRUCT FAR *)&ofToFileStruct,
- OF_WRITE | OF_SHARE_EXCLUSIVE);
- // Does the main MAIL file exist?
- if(hTo==HFILE_ERROR)
- {
- // No? Create one.
- hTo=OpenFile(lpTo, (OFSTRUCT FAR *)&ofToFileStruct,
- OF_CREATE | OF_WRITE | OF_SHARE_EXCLUSIVE);
- // Serious error!
- if(hTo==HFILE_ERROR)
- {
- smtpSendMessage(lpClient, 503, MSG_MAILOPEN);
- smtpError(IDS_COULDNTOPEN_S, lpTo);
- //DEBUGIT("smtpAppendToFile() End (File error 1)");
- return;
- }
- }
-
- // Open the temporary file
- hFrom=OpenFile(lpFrom, (OFSTRUCT FAR *)&ofToFileStruct,
- OF_READ | OF_SHARE_DENY_WRITE);
- if(hFrom==HFILE_ERROR)
- {
- smtpSendMessage(lpClient, 503, MSG_TEMPOPEN);
- smtpError(IDS_COULDNTOPEN_S, lpFrom);
- _lclose(hTo);
- //DEBUGIT("smtpAppendToFile() End (File error 2)");
- return;
- }
-
- // Seek to the end of the main MAIL file
- if(_llseek(hTo, 0, 2)==HFILE_ERROR)
- {
- smtpSendMessage(lpClient, 503, MSG_SEEKERROR);
- smtpError(IDS_FILEERROR_S, lpTo);
- _lclose(hTo);
- _lclose(hFrom);
- //DEBUGIT("smtpAppendToFile() End (File error 3)");
- return;
- }
-
- // Copy the temporary file to the end of the MAIL file
- while(iSize=_lread(hFrom, (LPSTR)szBuffer, sizeof(szBuffer)))
- {
- if((iSize==HFILE_ERROR)||
- (_lwrite(hTo, (LPSTR)szBuffer, iSize)==HFILE_ERROR)) break;
- }
- // Close 'em both
- _lclose(hTo);
- _lclose(hFrom);
-
- // Icon Flag!
- bMailArrived=TRUE;
- SetProp(hWndDlg, "icon", LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONFULL)));
- RedrawWindow(hWndDlg, NULL, NULL, RDW_INTERNALPAINT);
-
- // Tell user mail just came
- MessageBeep(MB_ICONEXCLAMATION);
-
- // Wait a bit and check to see if this mail still exists
- SetTimer(hWndDlg, (UINT)ID_TIMER, (UINT)TIME_CHECK, NULL);
-
- // Delete the temporary file
- if(!lpClient) return;
- if(lpClient->iMessageType!=CMDSAML)
- {
- OpenFile(lpFrom, (OFSTRUCT FAR *)&ofFromFileStruct,
- OF_DELETE);
- }
- //DEBUGIT("smtpAppendToFile() End");
- return;
- } /* smtpAppendToFile() */
-
-
- /* BOOL smtpMailCheck(LPSTR);
- Purpose: To check to see if the main mail file still exists.
- Given: Filename of the main file to check for.
- Returns: Nothing.
- Other: Modifies mail flag
- */
- BOOL smtpMailCheck(LPSTR lpFilename)
- {
- OFSTRUCT ofFile;
- HICON hIcon;
-
- if(OpenFile(lpFilename, (OFSTRUCT FAR *)&ofFile,
- OF_EXIST | OF_SHARE_COMPAT) != HFILE_ERROR)
- {
- if(!bMailArrived)
- {
- bMailArrived=TRUE;
-
- hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONFULL));
- SetProp(hWndDlg, "icon", hIcon);
- RedrawWindow(hWndDlg, NULL, NULL, RDW_INTERNALPAINT);
- }
- }
- else
- {
- if(bMailArrived)
- {
- bMailArrived=FALSE;
- hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONEMPTY));
- SetProp(hWndDlg, "icon", hIcon);
- RedrawWindow(hWndDlg, NULL, NULL, RDW_INTERNALPAINT);
- }
- }
- return(bMailArrived);
- } /* smtpMailCheck() */
-
-
- /* BOOL smtpDisplayFile(LPSMTPCLIENT, LPSTR);
- Purpose: To display a mail message to the screen for
- SEND and SAML.
- Given: Pointer to a related SMTPCLIENT struct, filename
- Return: TRUE if error, FALSE if not.
- */
- BOOL smtpDisplayFile(LPSMTPCLIENT lpClient, LPSTR lpFilename)
- {
- char szCommand[256];
- OFSTRUCT ofFile;
-
- //DEBUGIT("smtpDisplayFile() Begin");
- // Beep user to tell them mail came.
- MessageBeep(MB_ICONEXCLAMATION);
-
- // "Fork" off a notepad to handle it
- wsprintf((LPSTR)szCommand, "notepad %s", lpFilename);
- if(WinExec((LPSTR)szCommand, SW_SHOW)<32)
- {
- smtpAppendToFile(lpClient, (LPSTR)szLocalMailPath, lpFilename);
- }
-
- // Delete the temporary file
- if((lpClient->iMessageType==CMDSAML)||
- (lpClient->iMessageType==CMDSEND))
- {
- OpenFile(lpFilename, (OFSTRUCT FAR *)&ofFile,
- OF_DELETE);
- }
- //DEBUGIT("smtpDisplayFile() End");
- return(FALSE);
- } /* smtpDisplayFile() */
-
-
- /* LPSMTPCLIENT smtpAddClient(SOCKET);
- Purpose: Allocate a client structure and initilize it.
- Given: SOCKET of a connection.
- Returns: A negative number on error, or a
- valid SMTPCLIENT index into
- smtpClientsTable
- Reusability notes:
- SMTPCLIENT smtpClientsTable;
- PHASE_INIT,3 MAXBUFF, MAXCLIENTS;
- */
- LPSMTPCLIENT smtpAddClient(SOCKET sSocket)
- {
- int iRcvSize;
- int iSizeofRcvSize;
- HANDLE hInput, hOutput;
- HCLIENT hClient;
- LPSTR lpInput, lpOutput;
- LPSMTPCLIENT lpClient, lpWalker;
-
- //DEBUGIT("smtpAddClient() Begin");
- // Find the receiver buffer size
- iSizeofRcvSize=sizeof(iRcvSize);
- getsockopt(sSocket, SOL_SOCKET, SO_RCVBUF, (LPSTR)&iRcvSize,
- (LPINT)&iSizeofRcvSize );
-
- // Make sure we can handle a certain size line at a time
- if(iRcvSize<MAXSNDBUFF) iRcvSize=MAXSNDBUFF;
-
- // Make sure we can handle up to 2 buffers at a time
- iRcvSize=iRcvSize*2;
-
- // Allocate the receiver buffer
- hInput=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- iRcvSize);
- if(!hInput) return(NULL);
- lpInput=GlobalLock(hInput);
- if(!lpInput)
- {
- GlobalFree(hInput);
- return(NULL);
- }
-
- // Allocate the sending buffer
- // The size is permanent, we only need dynamic with incoming
- hOutput=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- MAXSNDBUFF);
- if(!hOutput)
- {
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
- lpOutput=GlobalLock(hOutput);
- if(!lpOutput)
- {
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
-
- // Allocate a SMTPCLIENT element
- hClient=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- sizeof(SMTPCLIENT));
- if(!hClient)
- {
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
- lpClient=(LPSMTPCLIENT)GlobalLock(hClient);
- if(!lpClient)
- {
- GlobalFree(hClient);
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
-
- lpClient->sSocket=sSocket;
- lpClient->bHaveFrom=FALSE;
- lpClient->hfFile=HFILE_ERROR;
- lpClient->hClient=hClient;
-
- lpClient->lpOutputBuffer=lpOutput;
- lpClient->hOutputBuffer=hOutput;
- // iOutputSize is MAXSNDBUFF
- lpClient->lpInputBuffer=lpInput;
- lpClient->hInputBuffer=hInput;
- lpClient->iInputSize=iRcvSize;
-
- lpClient->fifoOutputStart=0;
- lpClient->fifoOutputStop=0;
- lpClient->fifoInputStart=0;
- lpClient->fifoInputStop=0;
- lpClient->iState=STATE_WAIT_FOR_COMMAND;
- lpClient->iExtendedFlags=ESMTP_NONE;
-
- lpClient->lpNextClient=NULL;
- lpClient->lpPrevClient=NULL;
-
- // If this is the main listening socket, initialize List
- if(!smtpClientsHead)
- {
- smtpClientsHead=lpClient;
- }
- else
- {
- lpWalker=smtpClientsHead;
- while(lpWalker->lpNextClient) lpWalker=lpWalker->lpNextClient;
- lpWalker->lpNextClient=lpClient; // Add new tail segment
- lpClient->lpPrevClient=lpWalker; // Tell tail who's its parent
- }
-
- //DEBUGIT("smtpAddClient() End");
- return(lpClient);
- } /* smtpAddClient */
-
-
- /* LPSMTPCLIENT smtpSocketToClient(SOCKET sSocket) */
- LPSMTPCLIENT smtpSocketToClient(SOCKET sSocket)
- {
- LPSMTPCLIENT lpClient;
-
- if((!lpClient)||(sSocket==SOCKET_ERROR)) return(NULL);
- lpClient=smtpClientsHead;
-
- while(lpClient!=NULL)
- {
- if(lpClient->sSocket==sSocket) return(lpClient);
- lpClient=lpClient->lpNextClient;
- }
- return(lpClient);
- } /* smtpSocketToClient() */
-
-
- /* BOOL smtpDestroyClient(LPSMTPCLIENT);
- Purpose: To release a SMTPCLIENT structure.
- Given: Linked list element pointer
- Returns: TRUE if error, FALSE if all OK
- Reusability notes:
- */
- BOOL smtpDestroyClient(LPSMTPCLIENT lpClient)
- {
- BOOL bLinger = FALSE;
- LPSMTPCLIENT lpNext, lpPrev;
-
- //DEBUGIT("smtpDestroyClient() Begin");
- if(!lpClient) return(TRUE);
-
- // This code was removed as "dead" code. The setsockopt() just sets
- // the SO_LINGER option to what it already should be by default
- // (thanks Bob (rcq@ftp.com))
- // setsockopt(lpClient->sSocket,
- // SOL_SOCKET, SO_LINGER, (char FAR *)&bLinger,
- // sizeof(BOOL));
- // This shutdown isn't needed either...
- // shutdown(lpClient->sSocket, 2);
- closesocket(lpClient->sSocket);
-
- smtpLog(LOG_HIGH | LOG_TIME, LOG_DISCONNECT_S, (LPSTR)lpClient->szPeer);
-
- // Hack Alert! This is a hack, this is only a hack. If this were
- // real winsock compliant code, it shouldn't have to do this!
- // But it doesn't hurt, and Lanera seems to need it?
- // Since this is non-standard, it is now no longer needed - but I
- // doubt if it will work on Lanera's stack anymore..
- //if(lpClient!=smtpClientsHead)
- //{
- // WSAAsyncSelect(smtpClientsHead->sSocket, hWndMain, NET_ACTIVITY,
- // FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE);
- //}
-
- // Is the DATA temporary file still open?
- if(lpClient->hfFile!=HFILE_ERROR)
- {
- _lclose(lpClient->hfFile);
- // Take it as valid - but don't send any messages
- smtpAppendToFile(NULL, szLocalMailPath,
- lpClient->szFile);
- }
-
- // Patch out THIS segment.
- lpNext=lpClient->lpNextClient;
- lpPrev=lpClient->lpPrevClient;
- if(lpPrev) lpPrev->lpNextClient=lpNext;
-
- // Free all of the memory
- GlobalUnlock(lpClient->hInputBuffer);
- GlobalFree(lpClient->hInputBuffer);
- GlobalUnlock(lpClient->hOutputBuffer);
- GlobalFree(lpClient->hOutputBuffer);
- GlobalUnlock(lpClient->hClient);
- GlobalFree(lpClient->hClient);
-
- //DEBUGIT("smtpDestroyClient() End");
- return(FALSE);
- } /* smtpDestroyClient */
-
-
- /* void smtpSendMessage(LPSMTPCLIENT, int, int, ...);
- Purpose: To send a resource/reply message.
- Given: index into smtpClientsTable
- SMTP reply number (211, 503)
- Resource ID of the reply string.
- ... arguments
- Returns: Nothing.
- Other: If the Resource ID String has a '\n' in it,
- this routine will send it line at a time.
- */
- void smtpSendMessage(LPSMTPCLIENT lpClient, int SMTPCode, int ResourceID, ...)
- {
- int iCount;
- char szString[MAXSNDBUFF];
- char szLine[MAXSNDBUFF];
- LPSTR lpArg1, lpArg2, lpArg3;
- PSTR pStart, pStop;
- va_list vaArgs;
-
- //DEBUGIT("smtpSendMessage() Begin");
- if(!lpClient) return;
-
- va_start( vaArgs, ResourceID);
-
- if(!LoadString(hInst, ResourceID, (LPSTR)szLine, sizeof(szLine)))
- return;
-
- lpArg1=va_arg(vaArgs, LPSTR);
- lpArg2=va_arg(vaArgs, LPSTR);
- lpArg3=va_arg(vaArgs, LPSTR);
-
- wsprintf((LPSTR)szString, (LPSTR)szLine, lpArg1, lpArg2, lpArg3);
-
- pStart=pStop=szString;
- do /* Line loop for embedded '\n's */
- {
- while((*pStop!='\0')&&(*pStop!='\n')) pStop++;
- if((*pStop!='\0'))
- {
- *(pStop++)='\0';
- wsprintf((LPSTR)szLine, "%d-%s", SMTPCode, (LPSTR)pStart);
- pStart=pStop;
- }
- else
- {
- wsprintf((LPSTR)szLine, "%d %s", SMTPCode, (LPSTR)pStart);
- }
- clientSendLine(lpClient, (LPSTR)szLine, lstrlen((LPSTR)szLine));
- //DEBUGIT((LPSTR)szLine);
- smtpLog(LOG_HIGH, LOG_SENT_S, (LPCSTR)szLine);
- } while(*pStop!='\0');
- //DEBUGIT("smtpSendMessage() End");
- } /* smtpSendMessage */
-
-
- /* int clientSendLine(LPSMTPCLIENT, LPSTR, int);
- Purpose: Send 1 line to the caller if it exists.
- Given: SMTPCLIENT index, Line pointer,
- Line size. (for binary "string" sends if needed)
- Returns: 0 if everything isn't ok.
- >0 tells the caller how many characters it sent.
- Reusability requirements:
- Globals: SMTPCLIENT smtpClientsTable[]
- Defines: MAXCLIENTS, MAXBUFF
- Other: THIS ROUTINE ADDS A CR/LF PAIR!
- */
- int clientSendLine(LPSMTPCLIENT lpClient, LPSTR lpLine, int iLine)
- {
- LPSTR lpBuffer;
- int fifoStart;
- int fifoStop;
- int fifoWalker;
- int iDest;
-
- /* Catch illegal arguements */
- if((!lpClient)||(lpLine==NULL)||(iLine==0))
- return(0);
-
- /* Make things easier to deal with */
- lpBuffer=lpClient->lpOutputBuffer;
- fifoStart=lpClient->fifoOutputStart;
- fifoWalker=fifoStart;
- fifoStop=lpClient->fifoOutputStop;
-
- /* Make sure there is enough room - Egad */
- if(( (fifoStop<fifoStart) &&
- (((fifoStop+iLine+2)&MAXSNDBUFF)>=fifoStart)
- ) ||
- ( (fifoStop>=fifoStart) &&
- (((fifoStop+iLine+2)/MAXSNDBUFF)==1) &&
- (((fifoStop+iLine+2)%MAXSNDBUFF)>=fifoStart)
- ))
- return(0);
-
- /* There is room at the end! Copy it in! */
- iDest=0;
- fifoWalker=fifoStop;
- while(iDest<iLine)
- {
- lpBuffer[fifoWalker]=lpLine[iDest];
- fifoWalker=(fifoWalker+1)%MAXSNDBUFF;
- iDest++;
- }
- lpBuffer[fifoWalker]='\r'; // Append CR on output
- fifoWalker=(fifoWalker+1)%MAXSNDBUFF;
- lpBuffer[fifoWalker]='\n'; // Append LF on output
- fifoWalker=(fifoWalker+1)%MAXSNDBUFF;
-
- lpClient->fifoOutputStop=fifoWalker;
- // This is important
- netSendData(lpClient);
- return(iDest); // Tell em how many we copied!
- } /* clientSendLine */
-
-
- /* int clientReceiveLine(LPSMTPCLIENT, LPSTR, int);
- Purpose: Receive 1 line for the caller if it exists.
- Given: SMTPCLIENT pointer, Line buffer pointer,
- Line buffer size.
- Returns: -1 if no string found in buffer
- 0 if just CR or NL
- >0 tells the caller how many characters it was.
- Reusability requirements:
- None!
- Notes: This routines takes into account backspaces,
- deletes, multiple CRs and LFs.
- */
- int clientReceiveLine(LPSMTPCLIENT lpClient, LPSTR lpLine, int iLine)
- {
- LPSTR lpBuffer;
- int iCount;
- int fifoStart;
- int fifoStop;
- int fifoWalker;
- int iDest;
- int iMax;
-
- if((!lpClient)||(lpLine==NULL)||(iLine==0))
- return(-1);
-
- /* Make things easier to deal with */
- lpBuffer=lpClient->lpInputBuffer;
- fifoStart=lpClient->fifoInputStart;
- fifoWalker=fifoStart;
- fifoStop=lpClient->fifoInputStop;
- iMax=lpClient->iInputSize;
-
- if(fifoStart==fifoStop) return(-1);
-
- /* Search buffer for a LF or CR BEFORE the end of the buffer! */
- while((lpBuffer[fifoWalker]!='\n')&&
- (lpBuffer[fifoWalker]!='\r'))
- {
- fifoWalker=(fifoWalker+1)%iMax;
- if(fifoWalker==fifoStop)
- return(-1);
- }
-
- /* We found the end of a string! Copy it out. */
- *lpLine='\0';
-
- iDest=0;
- fifoWalker=fifoStart;
- while((lpBuffer[fifoWalker]!='\n')&&
- (lpBuffer[fifoWalker]!='\r'))
- {
- if((lpBuffer[fifoWalker]=='\b')|| // Backspace (^H)
- (lpBuffer[fifoWalker]=='\177')) // Delete (^?)
- { // Interactive User is talking to us (and making mistakes)
- if((--iDest)<0) iDest=0; // Backup if we can
- fifoWalker=(fifoWalker+1)%iMax; // Step over ^H or ^?
- continue; // for ^H^H... case
- }
- lpLine[iDest]=lpBuffer[fifoWalker];
- fifoWalker=(fifoWalker+1)%iMax;
- iDest++;
- if(iDest>=iLine)
- return(-1); // Not enough string space!!!
- }
- lpLine[iDest]='\0';
-
- // Step past the '\r'
- if((fifoWalker!=fifoStop)&&
- (lpBuffer[fifoWalker]=='\r')) fifoWalker=(fifoWalker+1)%iMax;
-
- // Step past the '\n'
- if((fifoWalker!=fifoStop)&&
- (lpBuffer[fifoWalker]=='\n')) fifoWalker=(fifoWalker+1)%iMax;
-
- lpClient->fifoInputStart=fifoWalker;
- smtpLog(LOG_HIGH, LOG_RECEIVED_S, (LPCSTR)lpLine);
- return(iDest); // Tell em how many we copied!
- } /* clientReceiveLine */
-
-
- /* int clientReceiveBlock(int, LPSTR, int);
- Purpose: Receive entire FIFO block for the caller if it exists.
- Given: SMTPCLIENT index, Block buffer pointer,
- Block buffer size.
- Returns: 0 if everything isn't ok. (no characters waiting)
- >0 tells the caller how many characters it was.
- Reusability requirements:
- Globals: SMTPCLIENT smtpClientsTable[]
- Defines: MAXCLIENTS, MAXBUFF
- Notes: This kind of defeats the idea of FIFO, but it does
- allow for 8 bit binary transfers.
- Since it was easier to implement 8BITMIME termination
- in here, I have left it so. This is not good design.
- */
- int clientReceiveBlock(LPSMTPCLIENT lpClient, LPSTR lpLine, int iLine)
- {
- LPSTR lpBuffer;
- int fifoStart;
- int fifoStop;
- int fifoWalker;
- int iDest;
- int iMax;
-
- if((!lpClient)||(lpLine==NULL)||(iLine==0))
- return(0);
-
- // Make things easier to deal with
- lpBuffer=lpClient->lpInputBuffer;
- fifoStart=lpClient->fifoInputStart;
- fifoStop=lpClient->fifoInputStop;
- iMax=lpClient->iInputSize;
-
- if(fifoStart==fifoStop) return(0);
-
- iDest=0;
- fifoWalker=fifoStart;
- while(fifoWalker!=fifoStop)
- {
- if(lpBuffer[fifoWalker]=='.')
- {
- // Check for presence of, and validity of "\r\n.\r\n"
- // Elegant, yet ugly
- // Possible bug: What if the above sequence comes split?
- if(((((fifoWalker-2)%iMax) != fifoStart) &&
- (lpBuffer[(fifoWalker-2)%iMax]=='\r'))
- &&((((fifoWalker-1)%iMax) != fifoStart) &&
- (lpBuffer[(fifoWalker-1)%iMax]=='\n'))
- &&((((fifoWalker+1)%iMax) != fifoStop) &&
- (lpBuffer[(fifoWalker+1)%iMax]=='\r'))
- &&((((fifoWalker+2)%iMax) != fifoStop) &&
- (lpBuffer[(fifoWalker+2)%iMax]=='\n'))
- )
- { // End of message
- if(lpClient->hfFile!=HFILE_ERROR)
- {
- _lclose(lpClient->hfFile);
- }
- lpClient->hfFile=HFILE_ERROR;
- smtpAppendToFile(lpClient, szLocalMailPath,
- lpClient->szFile);
- lpClient->iState=STATE_WAIT_FOR_COMMAND;
- smtpSendMessage(lpClient, 250, MSG_OK);
- fifoWalker=(fifoWalker+2)%iMax;
- break;
- }
- } // Pass EVERYTHING else through.
- lpLine[iDest]=lpBuffer[fifoWalker];
- fifoWalker=(fifoWalker+1)%iMax;
- iDest++;
- }
- lpLine[iDest]='\0'; // Zero terminate it, for luck
-
- lpClient->fifoInputStart=fifoWalker;
-
- smtpLog(LOG_HIGH, LOG_RECEIVED_S, (LPCSTR)lpLine);
- return(iDest); // Tell em how many we copied!
- } /* clientReceiveBlock */
-
- /**** End of WSMTPSRV.C ****/
-