POP3Utils.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:38k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "ShBlocks.h"
  26. #include "ResLocks.h"
  27. #include "StrUtils.h"
  28. #include "SList.h"
  29. #include "BuffSock.h"
  30. #include "MD5.h"
  31. #include "MailConfig.h"
  32. #include "UsrUtils.h"
  33. #include "SvrUtils.h"
  34. #include "MessQueue.h"
  35. #include "SMAILUtils.h"
  36. #include "QueueUtils.h"
  37. #include "MiscUtils.h"
  38. #include "Maildir.h"
  39. #include "POP3Svr.h"
  40. #include "POP3Utils.h"
  41. #include "SMTPUtils.h"
  42. #include "MailSvr.h"
  43. #define UPOP_IPMAP_FILE         "pop3.ipmap.tab"
  44. #define POP3_IP_LOGFILE         ".ipconn"
  45. #define POPF_MSG_DELETED        (1 << 0)
  46. #define POPF_MSG_SENT           (1 << 1)
  47. #define POPF_MSG_TOP            (1 << 2)
  48. #define STD_POP3_TIMEOUT        STD_SERVER_TIMEOUT
  49. struct POP3MsgData {
  50. LISTLINK LL;
  51. char szMsgName[SYS_MAX_PATH];
  52. unsigned long ulMsgSize;
  53. unsigned long ulFlags;
  54. };
  55. struct POP3SessionData {
  56. SYS_INET_ADDR PeerInfo;
  57. UserInfo *pUI;
  58. HSLIST hMessageList;
  59. POP3MsgData **ppMsgArray;
  60. int iMsgListed;
  61. int iMsgCount;
  62. unsigned long ulMBSize;
  63. int iLastAccessed;
  64. int iTimeout;
  65. };
  66. static int UPopMailFileNameFilter(char const *pszFileName);
  67. static int UPopFillMessageList(char const *pszBasePath, char const *pszSubPath,
  68.        HSLIST & hMessageList, int &iMsgCount, unsigned long &ulMBSize);
  69. static int UPopBuildMessageList(UserInfo * pUI, HSLIST & hMessageList,
  70. int *piMsgCount = NULL, unsigned long *pulMBSize = NULL);
  71. static void UPopFreeMsgData(POP3MsgData * pPOPMD);
  72. static void UPopFreeMessageList(HSLIST & hMessageList);
  73. static unsigned long UPopMessagesSize(HSLIST & hMessageList);
  74. static POP3MsgData *UPopMessageFromIndex(POP3SessionData * pPOPSD, int iMsgIndex);
  75. static int UPopCheckPeerIP(UserInfo * pUI, SYS_INET_ADDR const &PeerInfo);
  76. static int UPopUpdateMailbox(POP3SessionData * pPOPSD);
  77. static int UPopCheckResponse(const char *pszResponse, char *pszMessage = NULL);
  78. static int UPopGetResponse(BSOCK_HANDLE hBSock, char *pszResponse, int iMaxChars,
  79.    int iTimeout = STD_POP3_TIMEOUT);
  80. static char *UPopExtractServerTimeStamp(char const *pszResponse, char *pszTimeStamp,
  81. int iMaxTimeStamp);
  82. static int UPopSendCommand(BSOCK_HANDLE hBSock, const char *pszCommand, char *pszResponse,
  83.    int iMaxChars, int iTimeout = STD_POP3_TIMEOUT);
  84. static int UPopDoClearTextAuth(BSOCK_HANDLE hBSock, const char *pszUsername,
  85.        const char *pszPassword, char *pszRespBuffer, int iMaxRespChars);
  86. static int UPopDoAPOPAuth(BSOCK_HANDLE hBSock, const char *pszUsername,
  87.   const char *pszPassword, char const *pszTimeStamp,
  88.   char *pszRespBuffer, int iMaxRespChars);
  89. static BSOCK_HANDLE UPopCreateChannel(const char *pszServer, const char *pszUsername,
  90.       const char *pszPassword, bool bTryAuthAPOP = false);
  91. static int UPopCloseChannel(BSOCK_HANDLE hBSock, int iHardClose = 0);
  92. static int UPopGetMailboxStatus(BSOCK_HANDLE hBSock, int &iMsgCount,
  93. unsigned long &ulMailboxSize);
  94. static int UPopGetMailboxStatus(BSOCK_HANDLE hBSock, int &iMsgCount,
  95. unsigned long &ulMailboxSize);
  96. static int UPopRetrieveMessage(BSOCK_HANDLE hBSock, int iMsgIndex, const char *pszFileName,
  97.        unsigned long *pulMsgSize);
  98. static int UPopDeleteMessage(BSOCK_HANDLE hBSock, int iMsgIndex);
  99. static int UPopGetIpLogFilePath(UserInfo * pUI, char *pszFilePath, int iMaxPath);
  100. static int UPopMailFileNameFilter(char const *pszFileName)
  101. {
  102. return ((*pszFileName != '.') ? 1 : 0);
  103. }
  104. int UPopGetMailboxSize(UserInfo * pUI, unsigned long &ulMBSize, unsigned long &ulNumMessages)
  105. {
  106. char szMBPath[SYS_MAX_PATH] = "";
  107. UsrGetMailboxPath(pUI, szMBPath, sizeof(szMBPath), 0);
  108. char szResLock[SYS_MAX_PATH] = "";
  109. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(szMBPath, szResLock,
  110.   sizeof(szResLock)));
  111. if (hResLock == INVALID_RLCK_HANDLE)
  112. return (ErrGetErrorCode());
  113. ulMBSize = 0;
  114. ulNumMessages = 0;
  115. if (MscGetDirectorySize(szMBPath, true, ulMBSize, ulNumMessages,
  116. UPopMailFileNameFilter) < 0) {
  117. ErrorPush();
  118. RLckUnlockSH(hResLock);
  119. return (ErrorPop());
  120. }
  121. RLckUnlockSH(hResLock);
  122. return (0);
  123. }
  124. int UPopCheckMailboxSize(UserInfo * pUI, unsigned long *pulAvailSpace)
  125. {
  126. unsigned long ulMBSize = 0;
  127. unsigned long ulNumMessages = 0;
  128. if (UPopGetMailboxSize(pUI, ulMBSize, ulNumMessages) < 0)
  129. return (ErrGetErrorCode());
  130. char *pszMaxMBSize = UsrGetUserInfoVar(pUI, "MaxMBSize");
  131. if (pszMaxMBSize != NULL) {
  132. unsigned long ulMaxMBSize = (unsigned long) atol(pszMaxMBSize) * 1024;
  133. if (ulMaxMBSize && (ulMBSize >= ulMaxMBSize)) {
  134. SysFree(pszMaxMBSize);
  135. ErrSetErrorCode(ERR_MAILBOX_SIZE);
  136. return (ERR_MAILBOX_SIZE);
  137. }
  138. if (pulAvailSpace != NULL)
  139. *pulAvailSpace = (ulMaxMBSize ? ulMaxMBSize - ulMBSize:
  140.   (unsigned long) -1);
  141. SysFree(pszMaxMBSize);
  142. } else if (pulAvailSpace != NULL)
  143. *pulAvailSpace = ULONG_MAX;
  144. return (0);
  145. }
  146. static int UPopFillMessageList(char const *pszBasePath, char const *pszSubPath,
  147.        HSLIST & hMessageList, int &iMsgCount, unsigned long &ulMBSize)
  148. {
  149. ///////////////////////////////////////////////////////////////////////////////
  150. //  Setup pathname to scan for messages
  151. ///////////////////////////////////////////////////////////////////////////////
  152. char szScanPath[SYS_MAX_PATH] = "";
  153. if (pszSubPath == NULL)
  154. StrSNCpy(szScanPath, pszBasePath);
  155. else
  156. SysSNPrintf(szScanPath, sizeof(szScanPath) - 1, "%s" SYS_SLASH_STR "%s",
  157.     pszBasePath, pszSubPath);
  158. char szFileName[SYS_MAX_PATH] = "";
  159. SYS_HANDLE hFind = SysFirstFile(szScanPath, szFileName);
  160. if (hFind != SYS_INVALID_HANDLE) {
  161. do {
  162. ///////////////////////////////////////////////////////////////////////////////
  163. //  Skip directories and dot-files
  164. ///////////////////////////////////////////////////////////////////////////////
  165. if (SysIsDirectory(hFind) || IsDotFilename(szFileName))
  166. continue;
  167. POP3MsgData *pPOPMD = (POP3MsgData *) SysAlloc(sizeof(POP3MsgData));
  168. if (pPOPMD == NULL) {
  169. ErrorPush();
  170. SysFindClose(hFind);
  171. return (ErrorPop());
  172. }
  173. ///////////////////////////////////////////////////////////////////////////////
  174. //  Setup message entry fields
  175. ///////////////////////////////////////////////////////////////////////////////
  176. ListLinkInit(pPOPMD);
  177. if (pszSubPath == NULL)
  178. StrSNCpy(pPOPMD->szMsgName, szFileName);
  179. else
  180. SysSNPrintf(pPOPMD->szMsgName, sizeof(pPOPMD->szMsgName) - 1,
  181.     "%s" SYS_SLASH_STR "%s", pszSubPath, szFileName);
  182. pPOPMD->ulMsgSize = SysGetSize(hFind);
  183. pPOPMD->ulFlags = 0;
  184. ///////////////////////////////////////////////////////////////////////////////
  185. //  Insert entry in message list
  186. ///////////////////////////////////////////////////////////////////////////////
  187. ListAddTail(hMessageList, (PLISTLINK) pPOPMD);
  188. ///////////////////////////////////////////////////////////////////////////////
  189. //  Update mailbox information
  190. ///////////////////////////////////////////////////////////////////////////////
  191. ulMBSize += pPOPMD->ulMsgSize;
  192. ++iMsgCount;
  193. } while (SysNextFile(hFind, szFileName));
  194. SysFindClose(hFind);
  195. }
  196. return (0);
  197. }
  198. static int UPopBuildMessageList(UserInfo * pUI, HSLIST & hMessageList,
  199. int *piMsgCount, unsigned long *pulMBSize)
  200. {
  201. char szMBPath[SYS_MAX_PATH] = "";
  202. UsrGetMailboxPath(pUI, szMBPath, sizeof(szMBPath), 0);
  203. char szResLock[SYS_MAX_PATH] = "";
  204. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szMBPath, szResLock,
  205.   sizeof(szResLock)));
  206. if (hResLock == INVALID_RLCK_HANDLE)
  207. return (ErrGetErrorCode());
  208. ///////////////////////////////////////////////////////////////////////////////
  209. //  Initialize list and mailbox size information
  210. ///////////////////////////////////////////////////////////////////////////////
  211. ListInit(hMessageList);
  212. int iMsgCount = 0;
  213. unsigned long ulMBSize = 0;
  214. if (iMailboxType == XMAIL_MAILBOX) {
  215. if (UPopFillMessageList(szMBPath, NULL, hMessageList, iMsgCount, ulMBSize) < 0) {
  216. ErrorPush();
  217. UPopFreeMessageList(hMessageList);
  218. RLckUnlockEX(hResLock);
  219. return (ErrorPop());
  220. }
  221. } else {
  222. if ((UPopFillMessageList(szMBPath, "new", hMessageList, iMsgCount, ulMBSize) < 0)
  223.     || (UPopFillMessageList(szMBPath, "cur", hMessageList, iMsgCount, ulMBSize) <
  224. 0)) {
  225. ErrorPush();
  226. UPopFreeMessageList(hMessageList);
  227. RLckUnlockEX(hResLock);
  228. return (ErrorPop());
  229. }
  230. }
  231. RLckUnlockEX(hResLock);
  232. if (piMsgCount != NULL)
  233. *piMsgCount = iMsgCount;
  234. if (pulMBSize != NULL)
  235. *pulMBSize = ulMBSize;
  236. return (0);
  237. }
  238. static void UPopFreeMsgData(POP3MsgData * pPOPMD)
  239. {
  240. SysFree(pPOPMD);
  241. }
  242. static void UPopFreeMessageList(HSLIST & hMessageList)
  243. {
  244. POP3MsgData *pPOPMD;
  245. while ((pPOPMD = (POP3MsgData *) ListRemove(hMessageList)) != INVALID_SLIST_PTR)
  246. UPopFreeMsgData(pPOPMD);
  247. }
  248. static unsigned long UPopMessagesSize(HSLIST & hMessageList)
  249. {
  250. unsigned long ulMBSize = 0;
  251. POP3MsgData *pPOPMD = (POP3MsgData *) ListFirst(hMessageList);
  252. for (; pPOPMD != INVALID_SLIST_PTR; pPOPMD = (POP3MsgData *)
  253.      ListNext(hMessageList, (PLISTLINK) pPOPMD))
  254. ulMBSize += pPOPMD->ulMsgSize;
  255. return (ulMBSize);
  256. }
  257. static POP3MsgData *UPopMessageFromIndex(POP3SessionData * pPOPSD, int iMsgIndex)
  258. {
  259. return (((iMsgIndex >= 0) && (iMsgIndex < pPOPSD->iMsgListed)) ?
  260. pPOPSD->ppMsgArray[iMsgIndex] : NULL);
  261. }
  262. int UPopAuthenticateAPOP(const char *pszDomain, const char *pszUsrName,
  263.  const char *pszTimeStamp, const char *pszDigest)
  264. {
  265. UserInfo *pUI = UsrGetUserByName(pszDomain, pszUsrName);
  266. if (pUI == NULL)
  267. return (ErrGetErrorCode());
  268. int iAuthResult = MscMD5Authenticate(pUI->pszPassword, pszTimeStamp, pszDigest);
  269. UsrFreeUserInfo(pUI);
  270. return (iAuthResult);
  271. }
  272. static int UPopCheckPeerIP(UserInfo * pUI, SYS_INET_ADDR const &PeerInfo)
  273. {
  274. char szIPMapFile[SYS_MAX_PATH] = "";
  275. UsrGetUserPath(pUI, szIPMapFile, sizeof(szIPMapFile), 1);
  276. StrNCat(szIPMapFile, UPOP_IPMAP_FILE, sizeof(szIPMapFile));
  277. if (SysExistFile(szIPMapFile) && (MscCheckAllowedIP(szIPMapFile, PeerInfo, true) < 0))
  278. return (ErrGetErrorCode());
  279. return (0);
  280. }
  281. POP3_HANDLE UPopBuildSession(const char *pszDomain, const char *pszUsrName,
  282.      const char *pszUsrPass, SYS_INET_ADDR const *pPeerInfo)
  283. {
  284. UserInfo *pUI = UsrGetUserByName(pszDomain, pszUsrName);
  285. if (pUI == NULL)
  286. return (INVALID_POP3_HANDLE);
  287. ///////////////////////////////////////////////////////////////////////////////
  288. //  Check if the account is enabled for POP3 sessions
  289. ///////////////////////////////////////////////////////////////////////////////
  290. if (!UsrGetUserInfoVarInt(pUI, "PopEnable", 1)) {
  291. UsrFreeUserInfo(pUI);
  292. ErrSetErrorCode(ERR_USER_DISABLED);
  293. return (INVALID_POP3_HANDLE);
  294. }
  295. ///////////////////////////////////////////////////////////////////////////////
  296. //  Check if peer is allowed to connect from its IP
  297. ///////////////////////////////////////////////////////////////////////////////
  298. if ((pPeerInfo != NULL) && (UPopCheckPeerIP(pUI, *pPeerInfo) < 0)) {
  299. UsrFreeUserInfo(pUI);
  300. return (INVALID_POP3_HANDLE);
  301. }
  302. if ((pszUsrPass != NULL) && (strcmp(pszUsrPass, pUI->pszPassword) != 0)) {
  303. ErrSetErrorCode(ERR_INVALID_PASSWORD);
  304. UsrFreeUserInfo(pUI);
  305. return (INVALID_POP3_HANDLE);
  306. }
  307. if (UsrPOP3Lock(pUI) < 0) {
  308. UsrFreeUserInfo(pUI);
  309. return (INVALID_POP3_HANDLE);
  310. }
  311. POP3SessionData *pPOPSD = (POP3SessionData *) SysAlloc(sizeof(POP3SessionData));
  312. if (pPOPSD == NULL) {
  313. UsrPOP3Unlock(pUI);
  314. UsrFreeUserInfo(pUI);
  315. return (INVALID_POP3_HANDLE);
  316. }
  317. pPOPSD->PeerInfo = *pPeerInfo;
  318. pPOPSD->pUI = pUI;
  319. pPOPSD->iLastAccessed = 0;
  320. pPOPSD->iTimeout = STD_POP3_TIMEOUT;
  321. if (UPopBuildMessageList(pUI, pPOPSD->hMessageList, &pPOPSD->iMsgCount,
  322.  &pPOPSD->ulMBSize) < 0) {
  323. SysFree(pPOPSD);
  324. UsrPOP3Unlock(pUI);
  325. UsrFreeUserInfo(pUI);
  326. return (INVALID_POP3_HANDLE);
  327. }
  328. pPOPSD->iMsgListed = pPOPSD->iMsgCount;
  329. ///////////////////////////////////////////////////////////////////////////////
  330. //  Build lookup array
  331. ///////////////////////////////////////////////////////////////////////////////
  332. if ((pPOPSD->ppMsgArray = (POP3MsgData **) SysAlloc((pPOPSD->iMsgCount + 1) *
  333.     sizeof(POP3MsgData *))) == NULL) {
  334. UPopFreeMessageList(pPOPSD->hMessageList);
  335. SysFree(pPOPSD);
  336. UsrPOP3Unlock(pUI);
  337. UsrFreeUserInfo(pUI);
  338. return (INVALID_POP3_HANDLE);
  339. }
  340. POP3MsgData *pPOPMD = (POP3MsgData *) ListFirst(pPOPSD->hMessageList);
  341. for (int ii = 0; (ii < pPOPSD->iMsgCount) && (pPOPMD != INVALID_SLIST_PTR);
  342.      pPOPMD = (POP3MsgData *) ListNext(pPOPSD->hMessageList, (PLISTLINK) pPOPMD), ii++)
  343. pPOPSD->ppMsgArray[ii] = pPOPMD;
  344. return ((POP3_HANDLE) pPOPSD);
  345. }
  346. void UPopReleaseSession(POP3_HANDLE hPOPSession, int iUpdate)
  347. {
  348. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  349. if (iUpdate)
  350. UPopUpdateMailbox(pPOPSD);
  351. UsrPOP3Unlock(pPOPSD->pUI);
  352. UsrFreeUserInfo(pPOPSD->pUI);
  353. UPopFreeMessageList(pPOPSD->hMessageList);
  354. SysFree(pPOPSD->ppMsgArray);
  355. SysFree(pPOPSD);
  356. }
  357. char *UPopGetUserInfoVar(POP3_HANDLE hPOPSession, const char *pszName, const char *pszDefault)
  358. {
  359. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  360. return (UsrGetUserInfoVar(pPOPSD->pUI, pszName, pszDefault));
  361. }
  362. static int UPopUpdateMailbox(POP3SessionData * pPOPSD)
  363. {
  364. char szMBPath[SYS_MAX_PATH] = "";
  365. UsrGetMailboxPath(pPOPSD->pUI, szMBPath, sizeof(szMBPath), 0);
  366. char szResLock[SYS_MAX_PATH] = "";
  367. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szMBPath, szResLock,
  368.   sizeof(szResLock)));
  369. if (hResLock == INVALID_RLCK_HANDLE)
  370. return (ErrGetErrorCode());
  371. POP3MsgData *pPOPMD = (POP3MsgData *) ListFirst(pPOPSD->hMessageList);
  372. for (; pPOPMD != INVALID_SLIST_PTR; pPOPMD = (POP3MsgData *)
  373.      ListNext(pPOPSD->hMessageList, (PLISTLINK) pPOPMD)) {
  374. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  375. char szMsgPath[SYS_MAX_PATH] = "";
  376. SysSNPrintf(szMsgPath, sizeof(szMsgPath) - 1, "%s" SYS_SLASH_STR "%s",
  377.     szMBPath, pPOPMD->szMsgName);
  378. SysRemove(szMsgPath);
  379. }
  380. }
  381. RLckUnlockEX(hResLock);
  382. return (0);
  383. }
  384. int UPopGetSessionMsgCurrent(POP3_HANDLE hPOPSession)
  385. {
  386. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  387. return (pPOPSD->iMsgCount);
  388. }
  389. int UPopGetSessionMsgTotal(POP3_HANDLE hPOPSession)
  390. {
  391. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  392. return (pPOPSD->iMsgListed);
  393. }
  394. unsigned long UPopGetSessionMBSize(POP3_HANDLE hPOPSession)
  395. {
  396. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  397. return (pPOPSD->ulMBSize);
  398. }
  399. int UPopGetSessionLastAccessed(POP3_HANDLE hPOPSession)
  400. {
  401. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  402. return (pPOPSD->iLastAccessed);
  403. }
  404. int UPopGetMessageSize(POP3_HANDLE hPOPSession, int iMsgIndex, unsigned long &ulMessageSize)
  405. {
  406. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  407. ulMessageSize = 0;
  408. POP3MsgData *pPOPMD = UPopMessageFromIndex(pPOPSD, iMsgIndex - 1);
  409. if (pPOPMD == NULL) {
  410. ErrSetErrorCode(ERR_MSG_NOT_IN_RANGE);
  411. return (ERR_MSG_NOT_IN_RANGE);
  412. }
  413. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  414. ErrSetErrorCode(ERR_MSG_DELETED);
  415. return (ERR_MSG_DELETED);
  416. }
  417. ulMessageSize = pPOPMD->ulMsgSize;
  418. return (0);
  419. }
  420. int UPopGetMessageUIDL(POP3_HANDLE hPOPSession, int iMsgIndex, char *pszMessageUIDL)
  421. {
  422. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  423. POP3MsgData *pPOPMD = UPopMessageFromIndex(pPOPSD, iMsgIndex - 1);
  424. if (pPOPMD == NULL) {
  425. ErrSetErrorCode(ERR_MSG_NOT_IN_RANGE);
  426. return (ERR_MSG_NOT_IN_RANGE);
  427. }
  428. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  429. ErrSetErrorCode(ERR_MSG_DELETED);
  430. return (ERR_MSG_DELETED);
  431. }
  432. ///////////////////////////////////////////////////////////////////////////////
  433. //  Extract message UIDL from mailbox file path
  434. ///////////////////////////////////////////////////////////////////////////////
  435. char const *pszSlash = strrchr(pPOPMD->szMsgName, SYS_SLASH_CHAR);
  436. strcpy(pszMessageUIDL, (pszSlash != NULL) ? (pszSlash + 1) : pPOPMD->szMsgName);
  437. return (0);
  438. }
  439. int UPopDeleteMessage(POP3_HANDLE hPOPSession, int iMsgIndex)
  440. {
  441. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  442. POP3MsgData *pPOPMD = UPopMessageFromIndex(pPOPSD, iMsgIndex - 1);
  443. if (pPOPMD == NULL) {
  444. ErrSetErrorCode(ERR_MSG_NOT_IN_RANGE);
  445. return (ERR_MSG_NOT_IN_RANGE);
  446. }
  447. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  448. ErrSetErrorCode(ERR_MSG_DELETED);
  449. return (ERR_MSG_DELETED);
  450. }
  451. pPOPSD->ulMBSize -= pPOPMD->ulMsgSize;
  452. --pPOPSD->iMsgCount;
  453. pPOPMD->ulFlags |= POPF_MSG_DELETED;
  454. pPOPSD->iLastAccessed = iMsgIndex;
  455. return (0);
  456. }
  457. int UPopResetSession(POP3_HANDLE hPOPSession)
  458. {
  459. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  460. POP3MsgData *pPOPMD = (POP3MsgData *) ListFirst(pPOPSD->hMessageList);
  461. for (; pPOPMD != INVALID_SLIST_PTR; pPOPMD = (POP3MsgData *)
  462.      ListNext(pPOPSD->hMessageList, (PLISTLINK) pPOPMD)) {
  463. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  464. pPOPSD->ulMBSize += pPOPMD->ulMsgSize;
  465. ++pPOPSD->iMsgCount;
  466. pPOPMD->ulFlags &= ~(POPF_MSG_DELETED | POPF_MSG_SENT | POPF_MSG_TOP);
  467. }
  468. }
  469. pPOPSD->iLastAccessed = 0;
  470. return (0);
  471. }
  472. int UPopSendErrorResponse(BSOCK_HANDLE hBSock, int iErrorCode, int iTimeout)
  473. {
  474. char const *pszError = ErrGetErrorString(iErrorCode);
  475. char *pszPOP3Error = (char *) SysAlloc(strlen(pszError) + 8);
  476. if (pszPOP3Error == NULL)
  477. return (ErrGetErrorCode());
  478. sprintf(pszPOP3Error, "-ERR %s", pszError);
  479. if (BSckSendString(hBSock, pszPOP3Error, iTimeout) < 0) {
  480. SysFree(pszPOP3Error);
  481. return (ErrGetErrorCode());
  482. }
  483. SysFree(pszPOP3Error);
  484. return (0);
  485. }
  486. int UPopSessionSendMsg(POP3_HANDLE hPOPSession, int iMsgIndex, BSOCK_HANDLE hBSock)
  487. {
  488. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  489. POP3MsgData *pPOPMD = UPopMessageFromIndex(pPOPSD, iMsgIndex - 1);
  490. if (pPOPMD == NULL) {
  491. UPopSendErrorResponse(hBSock, ERR_MSG_NOT_IN_RANGE, pPOPSD->iTimeout);
  492. ErrSetErrorCode(ERR_MSG_NOT_IN_RANGE);
  493. return (ERR_MSG_NOT_IN_RANGE);
  494. }
  495. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  496. UPopSendErrorResponse(hBSock, ERR_MSG_DELETED, pPOPSD->iTimeout);
  497. ErrSetErrorCode(ERR_MSG_DELETED);
  498. return (ERR_MSG_DELETED);
  499. }
  500. char szMsgFilePath[SYS_MAX_PATH] = "";
  501. UsrGetMailboxPath(pPOPSD->pUI, szMsgFilePath, sizeof(szMsgFilePath), 1);
  502. StrNCat(szMsgFilePath, pPOPMD->szMsgName, sizeof(szMsgFilePath));
  503. char szResponse[256] = "";
  504. sprintf(szResponse, "+OK %lu bytes", pPOPMD->ulMsgSize);
  505. if (BSckSendString(hBSock, szResponse, pPOPSD->iTimeout) < 0)
  506. return (ErrGetErrorCode());
  507. if ((pPOPMD->ulMsgSize > 0) &&
  508.     (SysSendFile(BSckGetAttachedSocket(hBSock), szMsgFilePath, 0, (unsigned long) -1,
  509.  pPOPSD->iTimeout) < 0))
  510. return (ErrGetErrorCode());
  511. if (BSckSendString(hBSock, ".", pPOPSD->iTimeout) < 0)
  512. return (ErrGetErrorCode());
  513. pPOPSD->iLastAccessed = iMsgIndex;
  514. pPOPMD->ulFlags |= POPF_MSG_SENT;
  515. return (0);
  516. }
  517. int UPopSessionTopMsg(POP3_HANDLE hPOPSession, int iMsgIndex, int iNumLines, BSOCK_HANDLE hBSock)
  518. {
  519. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  520. POP3MsgData *pPOPMD = UPopMessageFromIndex(pPOPSD, iMsgIndex - 1);
  521. if (pPOPMD == NULL) {
  522. UPopSendErrorResponse(hBSock, ERR_MSG_NOT_IN_RANGE, pPOPSD->iTimeout);
  523. ErrSetErrorCode(ERR_MSG_NOT_IN_RANGE);
  524. return (ERR_MSG_NOT_IN_RANGE);
  525. }
  526. if (pPOPMD->ulFlags & POPF_MSG_DELETED) {
  527. UPopSendErrorResponse(hBSock, ERR_MSG_DELETED, pPOPSD->iTimeout);
  528. ErrSetErrorCode(ERR_MSG_DELETED);
  529. return (ERR_MSG_DELETED);
  530. }
  531. char szMsgFilePath[SYS_MAX_PATH] = "";
  532. UsrGetMailboxPath(pPOPSD->pUI, szMsgFilePath, sizeof(szMsgFilePath), 1);
  533. StrNCat(szMsgFilePath, pPOPMD->szMsgName, sizeof(szMsgFilePath));
  534. FILE *pMsgFile = fopen(szMsgFilePath, "rb");
  535. if (pMsgFile == NULL) {
  536. UPopSendErrorResponse(hBSock, ERR_FILE_OPEN, pPOPSD->iTimeout);
  537. ErrSetErrorCode(ERR_FILE_OPEN);
  538. return (ERR_FILE_OPEN);
  539. }
  540. char szResponse[256] = "";
  541. sprintf(szResponse, "+OK message is %lu bytes", pPOPMD->ulMsgSize);
  542. if (BSckSendString(hBSock, szResponse, pPOPSD->iTimeout) < 0) {
  543. fclose(pMsgFile);
  544. return (ErrGetErrorCode());
  545. }
  546. bool bSendingMsg = false;
  547. char szMsgLine[2048] = "";
  548. while (MscGetString(pMsgFile, szMsgLine, sizeof(szMsgLine) - 1) != NULL) {
  549. if (bSendingMsg && (--iNumLines < 0))
  550. break;
  551. if (BSckSendString(hBSock, szMsgLine, pPOPSD->iTimeout) < 0) {
  552. fclose(pMsgFile);
  553. return (ErrGetErrorCode());
  554. }
  555. if (!bSendingMsg && (strlen(szMsgLine) == 0))
  556. bSendingMsg = true;
  557. if (SvrInShutdown()) {
  558. fclose(pMsgFile);
  559. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  560. return (ERR_SERVER_SHUTDOWN);
  561. }
  562. }
  563. fclose(pMsgFile);
  564. if (BSckSendString(hBSock, ".", pPOPSD->iTimeout) < 0)
  565. return (ErrGetErrorCode());
  566. pPOPSD->iLastAccessed = iMsgIndex;
  567. pPOPMD->ulFlags |= POPF_MSG_TOP;
  568. return (0);
  569. }
  570. int UPopSaveUserIP(POP3_HANDLE hPOPSession)
  571. {
  572. POP3SessionData *pPOPSD = (POP3SessionData *) hPOPSession;
  573. char szIpFilePath[SYS_MAX_PATH] = "";
  574. UPopGetIpLogFilePath(pPOPSD->pUI, szIpFilePath, sizeof(szIpFilePath));
  575. char szIP[128] = "???.???.???.???";
  576. SysInetNToA(pPOPSD->PeerInfo, szIP);
  577. FILE *pIpFile = fopen(szIpFilePath, "wt");
  578. if (pIpFile == NULL) {
  579. ErrSetErrorCode(ERR_FILE_CREATE, szIpFilePath);
  580. return (ERR_FILE_CREATE);
  581. }
  582. fprintf(pIpFile, "%sn", szIP);
  583. fclose(pIpFile);
  584. return (0);
  585. }
  586. static int UPopCheckResponse(const char *pszResponse, char *pszMessage)
  587. {
  588. if (strnicmp(pszResponse, "+OK", 3) == 0) {
  589. if (pszMessage != NULL)
  590. strcpy(pszMessage, pszResponse + ((pszResponse[3] == ' ') ? 4 : 3));
  591. return (0);
  592. } else if (strnicmp(pszResponse, "-ERR", 4) == 0) {
  593. if (pszMessage != NULL)
  594. strcpy(pszMessage, pszResponse + ((pszResponse[4] == ' ') ? 5 : 4));
  595. ErrSetErrorCode(ERR_BAD_SERVER_RESPONSE, pszResponse);
  596. return (ERR_BAD_SERVER_RESPONSE);
  597. }
  598. ErrSetErrorCode(ERR_INVALID_POP3_RESPONSE, pszResponse);
  599. return (ERR_INVALID_POP3_RESPONSE);
  600. }
  601. static int UPopGetResponse(BSOCK_HANDLE hBSock, char *pszResponse, int iMaxChars, int iTimeout)
  602. {
  603. if (BSckGetString(hBSock, pszResponse, iMaxChars, iTimeout) == NULL)
  604. return (ErrGetErrorCode());
  605. return (UPopCheckResponse(pszResponse));
  606. }
  607. static char *UPopExtractServerTimeStamp(char const *pszResponse, char *pszTimeStamp,
  608. int iMaxTimeStamp)
  609. {
  610. char const *pszStartTS = strchr(pszResponse, '<');
  611. char const *pszEndTS = strchr(pszResponse, '>');
  612. if ((pszStartTS == NULL) || (pszEndTS == NULL))
  613. return (NULL);
  614. int iLengthTS = (int) (pszEndTS - pszStartTS) + 1;
  615. if (iLengthTS <= 0)
  616. return (NULL);
  617. iLengthTS = Min(iLengthTS, iMaxTimeStamp - 1);
  618. strncpy(pszTimeStamp, pszStartTS, iLengthTS);
  619. pszTimeStamp[iLengthTS] = '';
  620. return (pszTimeStamp);
  621. }
  622. static int UPopSendCommand(BSOCK_HANDLE hBSock, const char *pszCommand, char *pszResponse,
  623.    int iMaxChars, int iTimeout)
  624. {
  625. if (BSckSendString(hBSock, pszCommand, iTimeout) <= 0)
  626. return (ErrGetErrorCode());
  627. if (UPopGetResponse(hBSock, pszResponse, iMaxChars, iTimeout) < 0)
  628. return (ErrGetErrorCode());
  629. return (0);
  630. }
  631. static int UPopDoClearTextAuth(BSOCK_HANDLE hBSock, const char *pszUsername,
  632.        const char *pszPassword, char *pszRespBuffer, int iMaxRespChars)
  633. {
  634. ///////////////////////////////////////////////////////////////////////////////
  635. //  Send USER and read result
  636. ///////////////////////////////////////////////////////////////////////////////
  637. SysSNPrintf(pszRespBuffer, iMaxRespChars - 1, "USER %s", pszUsername);
  638. if (UPopSendCommand(hBSock, pszRespBuffer, pszRespBuffer, iMaxRespChars) < 0)
  639. return (ErrGetErrorCode());
  640. ///////////////////////////////////////////////////////////////////////////////
  641. //  Send PASS and read result
  642. ///////////////////////////////////////////////////////////////////////////////
  643. SysSNPrintf(pszRespBuffer, iMaxRespChars - 1, "PASS %s", pszPassword);
  644. if (UPopSendCommand(hBSock, pszRespBuffer, pszRespBuffer, iMaxRespChars) < 0)
  645. return (ErrGetErrorCode());
  646. return (0);
  647. }
  648. static int UPopDoAPOPAuth(BSOCK_HANDLE hBSock, const char *pszUsername,
  649.   const char *pszPassword, char const *pszTimeStamp,
  650.   char *pszRespBuffer, int iMaxRespChars)
  651. {
  652. ///////////////////////////////////////////////////////////////////////////////
  653. //  Perform APOP authentication
  654. ///////////////////////////////////////////////////////////////////////////////
  655. char *pszHash = StrSprint("%s%s", pszTimeStamp, pszPassword);
  656. if (pszHash == NULL)
  657. return (ErrGetErrorCode());
  658. char szMD5[128] = "";
  659. do_md5_string(pszHash, strlen(pszHash), szMD5);
  660. SysFree(pszHash);
  661. ///////////////////////////////////////////////////////////////////////////////
  662. //  Send APOP and read result
  663. ///////////////////////////////////////////////////////////////////////////////
  664. SysSNPrintf(pszRespBuffer, iMaxRespChars - 1, "APOP %s %s", pszUsername, szMD5);
  665. if (UPopSendCommand(hBSock, pszRespBuffer, pszRespBuffer, iMaxRespChars) < 0)
  666. return (ErrGetErrorCode());
  667. return (0);
  668. }
  669. static BSOCK_HANDLE UPopCreateChannel(const char *pszServer, const char *pszUsername,
  670.       const char *pszPassword, bool bTryAuthAPOP)
  671. {
  672. SYS_INET_ADDR SvrAddr;
  673. if (MscGetServerAddress(pszServer, SvrAddr, STD_POP3_PORT) < 0)
  674. return (INVALID_BSOCK_HANDLE);
  675. SYS_SOCKET SockFD = SysCreateSocket(AF_INET, SOCK_STREAM, 0);
  676. if (SockFD == SYS_INVALID_SOCKET)
  677. return (INVALID_BSOCK_HANDLE);
  678. if (SysConnect(SockFD, &SvrAddr, sizeof(SvrAddr), STD_POP3_TIMEOUT) < 0) {
  679. SysCloseSocket(SockFD);
  680. return (INVALID_BSOCK_HANDLE);
  681. }
  682. BSOCK_HANDLE hBSock = BSckAttach(SockFD);
  683. if (hBSock == INVALID_BSOCK_HANDLE) {
  684. SysCloseSocket(SockFD);
  685. return (INVALID_BSOCK_HANDLE);
  686. }
  687. ///////////////////////////////////////////////////////////////////////////////
  688. //  Read welcome message
  689. ///////////////////////////////////////////////////////////////////////////////
  690. char szRTXBuffer[2048] = "";
  691. if (UPopGetResponse(hBSock, szRTXBuffer, sizeof(szRTXBuffer) - 1) < 0) {
  692. UPopCloseChannel(hBSock);
  693. return (INVALID_BSOCK_HANDLE);
  694. }
  695. ///////////////////////////////////////////////////////////////////////////////
  696. //  Extract TimeStamp from server respose ( if any )
  697. ///////////////////////////////////////////////////////////////////////////////
  698. char szTimeStamp[256] = "";
  699. if (!bTryAuthAPOP ||
  700.     (MscExtractServerTimeStamp(szRTXBuffer, szTimeStamp, sizeof(szTimeStamp) - 1) ==
  701.      NULL)) {
  702. ///////////////////////////////////////////////////////////////////////////////
  703. //  Try clear text authentication
  704. ///////////////////////////////////////////////////////////////////////////////
  705. if (UPopDoClearTextAuth(hBSock, pszUsername, pszPassword, szRTXBuffer,
  706. sizeof(szRTXBuffer) - 1) < 0) {
  707. UPopCloseChannel(hBSock);
  708. return (INVALID_BSOCK_HANDLE);
  709. }
  710. } else {
  711. ///////////////////////////////////////////////////////////////////////////////
  712. //  Try APOP authentication first
  713. ///////////////////////////////////////////////////////////////////////////////
  714. int iApopAuthResult = UPopDoAPOPAuth(hBSock, pszUsername, pszPassword,
  715.      szTimeStamp, szRTXBuffer,
  716.      sizeof(szRTXBuffer) - 1);
  717. if (iApopAuthResult < 0) {
  718. if (iApopAuthResult != ERR_BAD_SERVER_RESPONSE) {
  719. UPopCloseChannel(hBSock);
  720. return (INVALID_BSOCK_HANDLE);
  721. }
  722. ///////////////////////////////////////////////////////////////////////////////
  723. //  Try clear text authentication
  724. ///////////////////////////////////////////////////////////////////////////////
  725. if (UPopDoClearTextAuth(hBSock, pszUsername, pszPassword, szRTXBuffer,
  726. sizeof(szRTXBuffer) - 1) < 0) {
  727. UPopCloseChannel(hBSock);
  728. return (INVALID_BSOCK_HANDLE);
  729. }
  730. }
  731. }
  732. return (hBSock);
  733. }
  734. static int UPopCloseChannel(BSOCK_HANDLE hBSock, int iHardClose)
  735. {
  736. if (!iHardClose) {
  737. ///////////////////////////////////////////////////////////////////////////////
  738. //  Send QUIT and read result
  739. ///////////////////////////////////////////////////////////////////////////////
  740. char szRTXBuffer[2048] = "";
  741. if (UPopSendCommand(hBSock, "QUIT", szRTXBuffer, sizeof(szRTXBuffer) - 1) < 0) {
  742. BSckDetach(hBSock, 1);
  743. return (ErrGetErrorCode());
  744. }
  745. }
  746. BSckDetach(hBSock, 1);
  747. return (0);
  748. }
  749. static int UPopGetMailboxStatus(BSOCK_HANDLE hBSock, int &iMsgCount, unsigned long &ulMailboxSize)
  750. {
  751. char szRTXBuffer[2048] = "";
  752. if (UPopSendCommand(hBSock, "STAT", szRTXBuffer, sizeof(szRTXBuffer) - 1) < 0)
  753. return (ErrGetErrorCode());
  754. if (sscanf(szRTXBuffer, "+OK %d %lu", &iMsgCount, &ulMailboxSize) != 2) {
  755. ErrSetErrorCode(ERR_INVALID_POP3_RESPONSE, szRTXBuffer);
  756. return (ERR_INVALID_POP3_RESPONSE);
  757. }
  758. return (0);
  759. }
  760. static int UPopRetrieveMessage(BSOCK_HANDLE hBSock, int iMsgIndex, const char *pszFileName,
  761.        unsigned long *pulMsgSize)
  762. {
  763. FILE *pMsgFile = fopen(pszFileName, "wb");
  764. if (pMsgFile == NULL) {
  765. ErrSetErrorCode(ERR_FILE_CREATE);
  766. return (ERR_FILE_CREATE);
  767. }
  768. char szRTXBuffer[2048] = "";
  769. sprintf(szRTXBuffer, "RETR %d", iMsgIndex);
  770. if (UPopSendCommand(hBSock, szRTXBuffer, szRTXBuffer, sizeof(szRTXBuffer) - 1) < 0) {
  771. fclose(pMsgFile);
  772. return (ErrGetErrorCode());
  773. }
  774. int iLineLength = 0;
  775. int iGotNL;
  776. int iGotNLPrev = 1;
  777. unsigned long ulMsgSize = 0;
  778. for (;;) {
  779. if (BSckGetString(hBSock, szRTXBuffer, sizeof(szRTXBuffer) - 3,
  780.   STD_POP3_TIMEOUT, &iLineLength, &iGotNL) == NULL) {
  781. fclose(pMsgFile);
  782. ErrSetErrorCode(ERR_POP3_RETR_BROKEN);
  783. return (ERR_POP3_RETR_BROKEN);
  784. }
  785. ///////////////////////////////////////////////////////////////////////////////
  786. //  Check end of data condition
  787. ///////////////////////////////////////////////////////////////////////////////
  788. if (iGotNL && iGotNLPrev && (strcmp(szRTXBuffer, ".") == 0))
  789. break;
  790. ///////////////////////////////////////////////////////////////////////////////
  791. //  Correctly terminate the line
  792. ///////////////////////////////////////////////////////////////////////////////
  793. if (iGotNL)
  794. memcpy(szRTXBuffer + iLineLength, "rn", 3), iLineLength += 2;
  795. if (!fwrite(szRTXBuffer, iLineLength, 1, pMsgFile)) {
  796. fclose(pMsgFile);
  797. ErrSetErrorCode(ERR_FILE_WRITE, pszFileName);
  798. return (ERR_FILE_WRITE);
  799. }
  800. ulMsgSize += (unsigned long) iLineLength;
  801. iGotNLPrev = iGotNL;
  802. }
  803. fclose(pMsgFile);
  804. if (pulMsgSize != NULL)
  805. *pulMsgSize = ulMsgSize;
  806. return (0);
  807. }
  808. static int UPopDeleteMessage(BSOCK_HANDLE hBSock, int iMsgIndex)
  809. {
  810. char szRTXBuffer[2048] = "";
  811. sprintf(szRTXBuffer, "DELE %d", iMsgIndex);
  812. if (UPopSendCommand(hBSock, szRTXBuffer, szRTXBuffer, sizeof(szRTXBuffer) - 1) < 0)
  813. return (ErrGetErrorCode());
  814. return (0);
  815. }
  816. int UPopSyncRemoteLink(const char *pszSyncAddr, const char *pszRmtServer, const char *pszRmtName,
  817.        const char *pszRmtPassword, PopSyncReport * pSRep,
  818.        const char *pszFetchHdrTags, const char *pszAuthType,
  819.        const char *pszErrorAccount)
  820. {
  821. ///////////////////////////////////////////////////////////////////////////////
  822. //  Connection to POP3 server
  823. ///////////////////////////////////////////////////////////////////////////////
  824. BSOCK_HANDLE hBSock = UPopCreateChannel(pszRmtServer, pszRmtName, pszRmtPassword,
  825. (stricmp(pszAuthType, AUTH_TYPE_APOP) ==
  826.  0) ? true : false);
  827. if (hBSock == INVALID_BSOCK_HANDLE)
  828. return (ErrGetErrorCode());
  829. ///////////////////////////////////////////////////////////////////////////////
  830. //  Get mailbox status
  831. ///////////////////////////////////////////////////////////////////////////////
  832. int iMsgCount = 0;
  833. unsigned long ulMailboxSize = 0;
  834. if (UPopGetMailboxStatus(hBSock, iMsgCount, ulMailboxSize) < 0) {
  835. ErrorPush();
  836. UPopCloseChannel(hBSock);
  837. return (ErrorPop());
  838. }
  839. ///////////////////////////////////////////////////////////////////////////////
  840. //  Initialize the report structure with current mailbox informations
  841. ///////////////////////////////////////////////////////////////////////////////
  842. pSRep->iMsgSync = 0;
  843. pSRep->iMsgErr = iMsgCount;
  844. pSRep->ulSizeSync = 0;
  845. pSRep->ulSizeErr = ulMailboxSize;
  846. if (iMsgCount > 0) {
  847. ///////////////////////////////////////////////////////////////////////////////
  848. //  Retrieve messages
  849. ///////////////////////////////////////////////////////////////////////////////
  850. char szMsgFileName[SYS_MAX_PATH] = "";
  851. SysGetTmpFile(szMsgFileName);
  852. for (int ii = 0; ii < iMsgCount; ii++) {
  853. ///////////////////////////////////////////////////////////////////////////////
  854. //  Get the message
  855. ///////////////////////////////////////////////////////////////////////////////
  856. unsigned long ulMsgSize;
  857. if (UPopRetrieveMessage(hBSock, ii + 1, szMsgFileName, &ulMsgSize) < 0) {
  858. ErrorPush();
  859. CheckRemoveFile(szMsgFileName);
  860. UPopCloseChannel(hBSock);
  861. return (ErrorPop());
  862. }
  863. ///////////////////////////////////////////////////////////////////////////////
  864. //  Spool deliver fetched message
  865. ///////////////////////////////////////////////////////////////////////////////
  866. if (USmlDeliverFetchedMsg(pszSyncAddr, pszFetchHdrTags, szMsgFileName) <
  867.     0) {
  868. ///////////////////////////////////////////////////////////////////////////////
  869. //  If there's an error ( catch errors ) account try to deliver to this one
  870. ///////////////////////////////////////////////////////////////////////////////
  871. if ((pszErrorAccount != NULL) &&
  872.     (USmlDeliverFetchedMsg(pszErrorAccount, NULL, szMsgFileName)
  873.      == 0)) {
  874. ///////////////////////////////////////////////////////////////////////////////
  875. //  Delete remote message only if successfully delivered
  876. ///////////////////////////////////////////////////////////////////////////////
  877. UPopDeleteMessage(hBSock, ii + 1);
  878. }
  879. } else {
  880. ///////////////////////////////////////////////////////////////////////////////
  881. //  Delete remote message only if successfully delivered
  882. ///////////////////////////////////////////////////////////////////////////////
  883. UPopDeleteMessage(hBSock, ii + 1);
  884. pSRep->iMsgSync++;
  885. pSRep->ulSizeSync += ulMsgSize;
  886. }
  887. SysRemove(szMsgFileName);
  888. if (SvrInShutdown()) {
  889. UPopCloseChannel(hBSock);
  890. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  891. return (ERR_SERVER_SHUTDOWN);
  892. }
  893. }
  894. }
  895. ///////////////////////////////////////////////////////////////////////////////
  896. //  Disconnect from POP3 server
  897. ///////////////////////////////////////////////////////////////////////////////
  898. UPopCloseChannel(hBSock);
  899. ///////////////////////////////////////////////////////////////////////////////
  900. //  Update report struct to reflect final status
  901. ///////////////////////////////////////////////////////////////////////////////
  902. pSRep->iMsgErr -= pSRep->iMsgSync;
  903. pSRep->ulSizeErr =
  904.     (pSRep->ulSizeErr > pSRep->ulSizeSync) ? (pSRep->ulSizeErr - pSRep->ulSizeSync) : 0;
  905. return (0);
  906. }
  907. static int UPopGetIpLogFilePath(UserInfo * pUI, char *pszFilePath, int iMaxPath)
  908. {
  909. UsrGetUserPath(pUI, pszFilePath, iMaxPath, 1);
  910. StrNCat(pszFilePath, POP3_IP_LOGFILE, iMaxPath);
  911. return (0);
  912. }
  913. int UPopUserIpCheck(UserInfo * pUI, SYS_INET_ADDR const *pPeerInfo, unsigned int uExpireTime)
  914. {
  915. char szIpFilePath[SYS_MAX_PATH] = "";
  916. UPopGetIpLogFilePath(pUI, szIpFilePath, sizeof(szIpFilePath));
  917. ///////////////////////////////////////////////////////////////////////////////
  918. //  Load IP log file info and do expire check
  919. ///////////////////////////////////////////////////////////////////////////////
  920. SYS_FILE_INFO FI;
  921. if ((SysGetFileInfo(szIpFilePath, FI) < 0) ||
  922.     ((time_t) (FI.tMod + uExpireTime) < time(NULL))) {
  923. ErrSetErrorCode(ERR_NO_POP3_IP);
  924. return (ERR_NO_POP3_IP);
  925. }
  926. ///////////////////////////////////////////////////////////////////////////////
  927. //  Load IP from file
  928. ///////////////////////////////////////////////////////////////////////////////
  929. FILE *pIpFile = fopen(szIpFilePath, "rt");
  930. if (pIpFile == NULL) {
  931. ErrSetErrorCode(ERR_NO_POP3_IP);
  932. return (ERR_NO_POP3_IP);
  933. }
  934. char szIP[128] = "";
  935. MscFGets(szIP, sizeof(szIP) - 1, pIpFile);
  936. fclose(pIpFile);
  937. ///////////////////////////////////////////////////////////////////////////////
  938. //  Do IP matching
  939. ///////////////////////////////////////////////////////////////////////////////
  940. NET_ADDRESS PrevAddr;
  941. NET_ADDRESS CurrAddr;
  942. if ((SysInetAddr(szIP, PrevAddr) < 0) ||
  943.     (SysGetAddrAddress(*pPeerInfo, CurrAddr) < 0) ||
  944.     !SysSameAddress(PrevAddr, CurrAddr)) {
  945. ErrSetErrorCode(ERR_NO_POP3_IP);
  946. return (ERR_NO_POP3_IP);
  947. }
  948. return (0);
  949. }
  950. int UPopGetLastLoginInfo(UserInfo *pUI, PopLastLoginInfo *pInfo)
  951. {
  952. SYS_FILE_INFO FI;
  953. char szIpFilePath[SYS_MAX_PATH] = "";
  954. UPopGetIpLogFilePath(pUI, szIpFilePath, sizeof(szIpFilePath));
  955. if (SysGetFileInfo(szIpFilePath, FI) < 0)
  956. return (ErrGetErrorCode());
  957. pInfo->LTime = FI.tMod;
  958. ///////////////////////////////////////////////////////////////////////////////
  959. //  Load IP from file
  960. ///////////////////////////////////////////////////////////////////////////////
  961. FILE *pIpFile = fopen(szIpFilePath, "rt");
  962. if (pIpFile == NULL) {
  963. ErrSetErrorCode(ERR_NO_POP3_IP);
  964. return (ERR_NO_POP3_IP);
  965. }
  966. char szIP[128] = "";
  967. MscFGets(szIP, sizeof(szIP) - 1, pIpFile);
  968. fclose(pIpFile);
  969. NET_ADDRESS NetAddr;
  970. if (SysInetAddr(szIP, NetAddr) < 0)
  971. return (ErrGetErrorCode());
  972. return (SysSetupAddress(pInfo->Address, AF_INET, NetAddr, 0));
  973. }