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

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 "SList.h"
  26. #include "ShBlocks.h"
  27. #include "StrUtils.h"
  28. #include "BuffSock.h"
  29. #include "MiscUtils.h"
  30. #include "ResLocks.h"
  31. #include "BuffSock.h"
  32. #include "SvrUtils.h"
  33. #include "UsrUtils.h"
  34. #include "MessQueue.h"
  35. #include "SMAILUtils.h"
  36. #include "QueueUtils.h"
  37. #include "MailDomains.h"
  38. #include "SMTPUtils.h"
  39. #include "ExtAliases.h"
  40. #include "UsrMailList.h"
  41. #include "Filter.h"
  42. #include "MailConfig.h"
  43. #include "AppDefines.h"
  44. #include "MailSvr.h"
  45. #define FILTER_LOG_FILE             "filters"
  46. #define FILTER_STORAGE_DIR          "filters"
  47. #define FILTER_SELECT_MAX           128
  48. #define FILTER_DB_LINE_MAX          512
  49. #define FILTER_LINE_MAX             1024
  50. struct FilterMsgInfo {
  51. char szSender[MAX_ADDR_NAME];
  52. char szRecipient[MAX_ADDR_NAME];
  53. SYS_INET_ADDR LocalAddr;
  54. SYS_INET_ADDR RemoteAddr;
  55. char szSpoolFile[SYS_MAX_PATH];
  56. char szAuthName[MAX_ADDR_NAME];
  57. };
  58. static int FilLogExec(FilterMsgInfo const &FMI, char const * const *ppszExec,
  59.       int iExecResult, int iExitCode, char const *pszType,
  60.       char const *pszInfo);
  61. static int FilLoadMsgInfo(SPLF_HANDLE hFSpool, FilterMsgInfo & FMI);
  62. static void FilFreeMsgInfo(FilterMsgInfo & FMI);
  63. static int FilGetFilePath(char const *pszMode, char *pszFilePath, int iMaxPath);
  64. static int FilAddFilter(char **ppszFilters, int &iNumFilters, char const *pszFilterName);
  65. static int FilSelectFilters(char const *pszFilterFilePath, char const *pszMode,
  66.     FilterMsgInfo const &FMI, char **ppszFilters, int iMaxFilters);
  67. static void FilFreeFilters(char **ppszFilters, int iNumFilters);
  68. static int FilGetFilterPath(char const *pszFileName, char *pszFilePath, int iMaxPath);
  69. static int FilPreExec(FilterMsgInfo const &FMI, FilterTokens *pToks, char **ppszPEError);
  70. static int FilApplyFilter(char const *pszFilterPath, SPLF_HANDLE hFSpool,
  71.   QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, FilterMsgInfo const &FMI,
  72.   char const *pszType);
  73. static int FilFilterMacroSubstitutes(char **ppszCmdTokens, SPLF_HANDLE hFSpool,
  74.      FilterMsgInfo const &FMI);
  75. int FilLogFilter(FilterLogInfo const *pFLI)
  76. {
  77. char szTime[256] = "";
  78. MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
  79. RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR FILTER_LOG_FILE);
  80. if (hResLock == INVALID_RLCK_HANDLE)
  81. return (ErrGetErrorCode());
  82. char szLocIP[128] = "???.???.???.???";
  83. char szRmtIP[128] = "???.???.???.???";
  84. MscFileLog(FILTER_LOG_FILE, ""%s""
  85.    "t"%s""
  86.    "t"%s""
  87.    "t"%s""
  88.    "t"%s""
  89.    "t"%s""
  90.    "t"%s""
  91.    "t"%d""
  92.    "t"%d""
  93.    "t"%s""
  94.    "n", pFLI->pszSender, pFLI->pszRecipient, SysInetNToA(pFLI->LocalAddr, szLocIP),
  95.    SysInetNToA(pFLI->RemoteAddr, szRmtIP), szTime, pFLI->pszType, pFLI->pszInfo,
  96.    pFLI->iExecResult, pFLI->iExitCode, pFLI->ppszExec[0]);
  97. RLckUnlockEX(hResLock);
  98. return (0);
  99. }
  100. static int FilLogExec(FilterMsgInfo const &FMI, char const * const *ppszExec,
  101.       int iExecResult, int iExitCode, char const *pszType,
  102.       char const *pszInfo)
  103. {
  104. FilterLogInfo FLI;
  105. FLI.pszSender = FMI.szSender;
  106. FLI.pszRecipient = FMI.szRecipient;
  107. FLI.LocalAddr = FMI.LocalAddr;
  108. FLI.RemoteAddr = FMI.RemoteAddr;
  109. FLI.ppszExec = ppszExec;
  110. FLI.iExecResult = iExecResult;
  111. FLI.iExitCode = iExitCode;
  112. FLI.pszType = pszType;
  113. FLI.pszInfo = pszInfo != NULL ? pszInfo: "";
  114. return (FilLogFilter(&FLI));
  115. }
  116. static int FilLoadMsgInfo(SPLF_HANDLE hFSpool, FilterMsgInfo & FMI)
  117. {
  118. UserInfo *pUI;
  119. char const *const *ppszInfo = USmlGetInfo(hFSpool);
  120. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  121. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  122. char const *pszSpoolFile = USmlGetSpoolFilePath(hFSpool);
  123. int iFromDomains = StrStringsCount(ppszFrom);
  124. int iRcptDomains = StrStringsCount(ppszRcpt);
  125. char szUser[MAX_ADDR_NAME] = "";
  126. char szDomain[MAX_ADDR_NAME] = "";
  127. ZeroData(FMI);
  128. if ((iFromDomains > 0) &&
  129.     (USmtpSplitEmailAddr(ppszFrom[iFromDomains - 1], szUser, szDomain) == 0)) {
  130. if ((pUI = UsrGetUserByNameOrAlias(szDomain, szUser)) != NULL) {
  131. UsrGetAddress(pUI, FMI.szSender);
  132. UsrFreeUserInfo(pUI);
  133. } else
  134. StrSNCpy(FMI.szSender, ppszFrom[iFromDomains - 1]);
  135. } else
  136. SetEmptyString(FMI.szSender);
  137. if ((iRcptDomains > 0) &&
  138.     (USmtpSplitEmailAddr(ppszRcpt[iRcptDomains - 1], szUser, szDomain) == 0)) {
  139. if ((pUI = UsrGetUserByNameOrAlias(szDomain, szUser)) != NULL) {
  140. UsrGetAddress(pUI, FMI.szRecipient);
  141. UsrFreeUserInfo(pUI);
  142. } else
  143. StrSNCpy(FMI.szRecipient, ppszRcpt[iRcptDomains - 1]);
  144. } else
  145. SetEmptyString(FMI.szRecipient);
  146. if ((MscGetServerAddress(ppszInfo[smiServerAddr], FMI.LocalAddr) < 0) ||
  147.     (MscGetServerAddress(ppszInfo[smiClientAddr], FMI.RemoteAddr) < 0))
  148. return (ErrGetErrorCode());
  149. StrSNCpy(FMI.szSpoolFile, pszSpoolFile);
  150. if (USmlMessageAuth(hFSpool, FMI.szAuthName, sizeof(FMI.szAuthName) - 1) < 0)
  151. SetEmptyString(FMI.szAuthName);
  152. return (0);
  153. }
  154. static void FilFreeMsgInfo(FilterMsgInfo & FMI)
  155. {
  156. }
  157. char *FilGetFilterRejMessage(char const *pszSpoolFile)
  158. {
  159. FILE *pFile;
  160. char szRejFilePath[SYS_MAX_PATH] = "";
  161. char szRejMsg[512] = "";
  162. SysSNPrintf(szRejFilePath, sizeof(szRejFilePath) - 1, "%s.rej", pszSpoolFile);
  163. if ((pFile = fopen(szRejFilePath, "rb")) == NULL)
  164. return NULL;
  165. MscFGets(szRejMsg, sizeof(szRejMsg) - 1, pFile);
  166. fclose(pFile);
  167. SysRemove(szRejFilePath);
  168. return (SysStrDup(szRejMsg));
  169. }
  170. static int FilGetFilePath(char const *pszMode, char *pszFilePath, int iMaxPath)
  171. {
  172. char szMailRootPath[SYS_MAX_PATH] = "";
  173. CfgGetRootPath(szMailRootPath, sizeof(szMailRootPath));
  174. SysSNPrintf(pszFilePath, iMaxPath - 1, "%sfilters.%s.tab", szMailRootPath, pszMode);
  175. return (0);
  176. }
  177. static int FilAddFilter(char **ppszFilters, int &iNumFilters, char const *pszFilterName)
  178. {
  179. for (int ii = 0; ii < iNumFilters; ii++)
  180. if (strcmp(ppszFilters[ii], pszFilterName) == 0)
  181. return (0);
  182. if ((ppszFilters[iNumFilters] = SysStrDup(pszFilterName)) == NULL)
  183. return (ErrGetErrorCode());
  184. iNumFilters++;
  185. return (0);
  186. }
  187. static int FilSelectFilters(char const *pszFilterFilePath, char const *pszMode,
  188.     FilterMsgInfo const &FMI, char **ppszFilters, int iMaxFilters)
  189. {
  190. ///////////////////////////////////////////////////////////////////////////////
  191. //  Share lock the filter table file
  192. ///////////////////////////////////////////////////////////////////////////////
  193. char szResLock[SYS_MAX_PATH] = "";
  194. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(pszFilterFilePath, szResLock,
  195.   sizeof(szResLock)));
  196. if (hResLock == INVALID_RLCK_HANDLE)
  197. return (ErrGetErrorCode());
  198. ///////////////////////////////////////////////////////////////////////////////
  199. //  Get local and remote IP addresses
  200. ///////////////////////////////////////////////////////////////////////////////
  201. NET_ADDRESS LocalAddr;
  202. NET_ADDRESS RemoteAddr;
  203. SysGetAddrAddress(FMI.LocalAddr, LocalAddr);
  204. SysGetAddrAddress(FMI.RemoteAddr, RemoteAddr);
  205. ///////////////////////////////////////////////////////////////////////////////
  206. //  Open the filter database. Fail smootly if the file does not exist
  207. ///////////////////////////////////////////////////////////////////////////////
  208. FILE *pFile = fopen(pszFilterFilePath, "rt");
  209. if (pFile == NULL) {
  210. RLckUnlockSH(hResLock);
  211. return (0);
  212. }
  213. int iNumFilters = 0;
  214. char szLine[FILTER_DB_LINE_MAX] = "";
  215. while ((iNumFilters < iMaxFilters) &&
  216.        (MscGetConfigLine(szLine, sizeof(szLine) - 1, pFile) != NULL)) {
  217. char **ppszTokens = StrGetTabLineStrings(szLine);
  218. if (ppszTokens == NULL)
  219. continue;
  220. int iFieldsCount = StrStringsCount(ppszTokens);
  221. if ((iFieldsCount >= filMax) &&
  222.     StrIWildMatch(FMI.szSender, ppszTokens[filSender]) &&
  223.     StrIWildMatch(FMI.szRecipient, ppszTokens[filRecipient])) {
  224. AddressFilter AFRemote;
  225. AddressFilter AFLocal;
  226. if ((MscLoadAddressFilter(&ppszTokens[filRemoteAddr], 1, AFRemote) == 0)
  227.     && MscAddressMatch(AFRemote, RemoteAddr) &&
  228.     (MscLoadAddressFilter(&ppszTokens[filLocalAddr], 1, AFLocal) == 0) &&
  229.     MscAddressMatch(AFLocal, LocalAddr)) {
  230. FilAddFilter(ppszFilters, iNumFilters, ppszTokens[filFileName]);
  231. }
  232. }
  233. StrFreeStrings(ppszTokens);
  234. }
  235. fclose(pFile);
  236. RLckUnlockSH(hResLock);
  237. return (iNumFilters);
  238. }
  239. static void FilFreeFilters(char **ppszFilters, int iNumFilters)
  240. {
  241. for (iNumFilters--; iNumFilters >= 0; iNumFilters--)
  242. SysFree(ppszFilters[iNumFilters]);
  243. }
  244. static int FilGetFilterPath(char const *pszFileName, char *pszFilePath, int iMaxPath)
  245. {
  246. char szMailRootPath[SYS_MAX_PATH] = "";
  247. CfgGetRootPath(szMailRootPath, sizeof(szMailRootPath));
  248. SysSNPrintf(pszFilePath, iMaxPath - 1, "%s%s%s%s",
  249.     szMailRootPath, FILTER_STORAGE_DIR, SYS_SLASH_STR, pszFileName);
  250. return (0);
  251. }
  252. int FilExecPreParse(FilterExecCtx *pCtx, char **ppszPEError)
  253. {
  254. int i;
  255. char **ppszEToks;
  256. char const *pszEx = pCtx->pToks->ppszCmdTokens[0];
  257. if ((pCtx->pToks->iTokenCount < 1) || (*pszEx != '!'))
  258. return (0);
  259. pCtx->pToks->iTokenCount--;
  260. pCtx->pToks->ppszCmdTokens++;
  261. if ((ppszEToks = StrTokenize(pszEx + 1, ",")) == NULL)
  262. return (ErrGetErrorCode());
  263. for (i = 0; ppszEToks[i] != NULL; i++) {
  264. char *pszVar = ppszEToks[i], *pszVal;
  265. if ((pszVal = strchr(pszVar, '=')) != NULL)
  266. *pszVal++ = '';
  267. if (strcmp(pszVar, "aex") == 0) {
  268. if (!IsEmptyString(pCtx->pszAuthName)) {
  269. StrFreeStrings(ppszEToks);
  270. *ppszPEError = SysStrDup("EXCL");
  271. return (-1);
  272. }
  273. }
  274. }
  275. StrFreeStrings(ppszEToks);
  276. return (0);
  277. }
  278. static int FilPreExec(FilterMsgInfo const &FMI, FilterTokens *pToks, char **ppszPEError)
  279. {
  280. FilterExecCtx FCtx;
  281. FCtx.pToks = pToks;
  282. FCtx.pszAuthName = FMI.szAuthName;
  283. return (FilExecPreParse(&FCtx, ppszPEError));
  284. }
  285. static int FilApplyFilter(char const *pszFilterPath, SPLF_HANDLE hFSpool,
  286.   QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, FilterMsgInfo const &FMI,
  287.   char const *pszType)
  288. {
  289. ///////////////////////////////////////////////////////////////////////////////
  290. //  Share lock the filter file
  291. ///////////////////////////////////////////////////////////////////////////////
  292. char szResLock[SYS_MAX_PATH] = "";
  293. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(pszFilterPath, szResLock,
  294.   sizeof(szResLock)));
  295. if (hResLock == INVALID_RLCK_HANDLE)
  296. return (ErrGetErrorCode());
  297. ///////////////////////////////////////////////////////////////////////////////
  298. //  This should not happen but if it happens we let the message pass through
  299. ///////////////////////////////////////////////////////////////////////////////
  300. FILE *pFiltFile = fopen(pszFilterPath, "rt");
  301. if (pFiltFile == NULL) {
  302. RLckUnlockSH(hResLock);
  303. return (0);
  304. }
  305. ///////////////////////////////////////////////////////////////////////////////
  306. //  Filter this message
  307. ///////////////////////////////////////////////////////////////////////////////
  308. char szFiltLine[FILTER_LINE_MAX] = "";
  309. while (MscGetConfigLine(szFiltLine, sizeof(szFiltLine) - 1, pFiltFile) != NULL) {
  310. char **ppszCmdTokens = StrGetTabLineStrings(szFiltLine);
  311. if (ppszCmdTokens == NULL)
  312. continue;
  313. int iFieldsCount = StrStringsCount(ppszCmdTokens);
  314. if (iFieldsCount < 1) {
  315. StrFreeStrings(ppszCmdTokens);
  316. continue;
  317. }
  318. ///////////////////////////////////////////////////////////////////////////////
  319. //  Perform pre-exec filtering (like exec exclude if authenticated, ...)
  320. ///////////////////////////////////////////////////////////////////////////////
  321. char *pszPEError = NULL;
  322. FilterTokens Toks;
  323. Toks.ppszCmdTokens = ppszCmdTokens;
  324. Toks.iTokenCount = iFieldsCount;
  325. if (FilPreExec(FMI, &Toks, &pszPEError) < 0) {
  326. if (bFilterLogEnabled)
  327. FilLogExec(FMI, Toks.ppszCmdTokens, -1,
  328.    -1, pszType, pszPEError);
  329. if (pszPEError != NULL)
  330. SysFree(pszPEError);
  331. StrFreeStrings(ppszCmdTokens);
  332. continue;
  333. }
  334. ///////////////////////////////////////////////////////////////////////////////
  335. //  Do filter line macro substitution
  336. ///////////////////////////////////////////////////////////////////////////////
  337. FilFilterMacroSubstitutes(Toks.ppszCmdTokens, hFSpool, FMI);
  338. ///////////////////////////////////////////////////////////////////////////////
  339. //  Time to fire the external executable ...
  340. ///////////////////////////////////////////////////////////////////////////////
  341. int iExitCode = -1;
  342. int iExitFlags = 0;
  343. int iExecResult = SysExec(Toks.ppszCmdTokens[0], &Toks.ppszCmdTokens[0],
  344.   iFilterTimeout, FILTER_PRIORITY, &iExitCode);
  345. ///////////////////////////////////////////////////////////////////////////////
  346. //  Log the operation, if requested.
  347. ///////////////////////////////////////////////////////////////////////////////
  348. if (bFilterLogEnabled)
  349. FilLogExec(FMI, Toks.ppszCmdTokens, iExecResult,
  350.    iExitCode, pszType, NULL);
  351. if (iExecResult == 0) {
  352. SysLogMessage(LOG_LEV_MESSAGE,
  353.       "Filter run: Sender = "%s" Recipient = "%s" Filter = "%s" Retcode = %dn",
  354.       FMI.szSender, FMI.szRecipient, Toks.ppszCmdTokens[0],
  355.       iExitCode);
  356. ///////////////////////////////////////////////////////////////////////////////
  357. //  Separate code from flags
  358. ///////////////////////////////////////////////////////////////////////////////
  359. iExitFlags = iExitCode & FILTER_FLAGS_MASK;
  360. iExitCode &= ~FILTER_FLAGS_MASK;
  361. if ((iExitCode == FILTER_OUT_EXITCODE) ||
  362.     (iExitCode == FILTER_OUT_NN_EXITCODE) ||
  363.     (iExitCode == FILTER_OUT_NNF_EXITCODE)) {
  364. fclose(pFiltFile);
  365. RLckUnlockSH(hResLock);
  366. ///////////////////////////////////////////////////////////////////////////////
  367. //  Filter out message
  368. ///////////////////////////////////////////////////////////////////////////////
  369. char *pszRejMsg = FilGetFilterRejMessage(FMI.szSpoolFile);
  370. if (iExitCode == FILTER_OUT_EXITCODE)
  371. QueUtNotifyPermErrDelivery(hQueue, hMessage, NULL,
  372.    (pszRejMsg !=
  373.     NULL) ? pszRejMsg :
  374.    ErrGetErrorString
  375.    (ERR_FILTERED_MESSAGE),
  376.    NULL, true);
  377. else if (iExitCode == FILTER_OUT_NN_EXITCODE)
  378. QueCleanupMessage(hQueue, hMessage,
  379.   !QueUtRemoveSpoolErrors());
  380. else
  381. QueCleanupMessage(hQueue, hMessage, false);
  382. StrFreeStrings(ppszCmdTokens);
  383. if (pszRejMsg != NULL)
  384. SysFree(pszRejMsg);
  385. ErrSetErrorCode(ERR_FILTERED_MESSAGE);
  386. return (ERR_FILTERED_MESSAGE);
  387. } else if (iExitCode == FILTER_MODIFY_EXITCODE) {
  388. ///////////////////////////////////////////////////////////////////////////////
  389. //  Filter modified the message, we need to reload the spool handle
  390. ///////////////////////////////////////////////////////////////////////////////
  391. if (USmlReloadHandle(hFSpool) < 0) {
  392. ErrorPush();
  393. fclose(pFiltFile);
  394. RLckUnlockSH(hResLock);
  395. SysLogMessage(LOG_LEV_MESSAGE,
  396.       "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  397.       FMI.szSender, FMI.szRecipient,
  398.       Toks.ppszCmdTokens[0]);
  399. QueUtErrLogMessage(hQueue, hMessage,
  400.    "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  401.    FMI.szSender, FMI.szRecipient,
  402.    Toks.ppszCmdTokens[0]);
  403. QueCleanupMessage(hQueue, hMessage, true);
  404. StrFreeStrings(ppszCmdTokens);
  405. return (ErrorPop());
  406. }
  407. }
  408. } else {
  409. SysLogMessage(LOG_LEV_ERROR,
  410.       "Filter error (%d): Sender = "%s" Recipient = "%s" Filter = "%s"n",
  411.       iExecResult, FMI.szSender, FMI.szRecipient,
  412.       Toks.ppszCmdTokens[0]);
  413. QueUtErrLogMessage(hQueue, hMessage,
  414.    "Filter error (%d): Sender = "%s" Recipient = "%s" Filter = "%s"n",
  415.    iExecResult, FMI.szSender, FMI.szRecipient,
  416.    Toks.ppszCmdTokens[0]);
  417. }
  418. StrFreeStrings(ppszCmdTokens);
  419. ///////////////////////////////////////////////////////////////////////////////
  420. //  Filter list processing break required ?
  421. ///////////////////////////////////////////////////////////////////////////////
  422. if (iExitFlags & FILTER_FLAGS_BREAK) {
  423. fclose(pFiltFile);
  424. RLckUnlockSH(hResLock);
  425. return (1);
  426. }
  427. }
  428. fclose(pFiltFile);
  429. RLckUnlockSH(hResLock);
  430. return (0);
  431. }
  432. int FilFilterMessage(SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  433.      QMSG_HANDLE hMessage, char const *pszMode)
  434. {
  435. ///////////////////////////////////////////////////////////////////////////////
  436. //  Get filter file path and returns immediately if no file is defined
  437. ///////////////////////////////////////////////////////////////////////////////
  438. char szFilterFilePath[SYS_MAX_PATH] = "";
  439. FilGetFilePath(pszMode, szFilterFilePath, sizeof(szFilterFilePath));
  440. if (!SysExistFile(szFilterFilePath))
  441. return (0);
  442. ///////////////////////////////////////////////////////////////////////////////
  443. //  Load the message info
  444. ///////////////////////////////////////////////////////////////////////////////
  445. FilterMsgInfo FMI;
  446. if (FilLoadMsgInfo(hFSpool, FMI) < 0)
  447. return (ErrGetErrorCode());
  448. ///////////////////////////////////////////////////////////////////////////////
  449. //  Select applicable filters
  450. ///////////////////////////////////////////////////////////////////////////////
  451. int iNumFilters;
  452. char *pszFilters[FILTER_SELECT_MAX];
  453. if ((iNumFilters = FilSelectFilters(szFilterFilePath, pszMode, FMI, pszFilters,
  454.     CountOf(pszFilters))) < 0) {
  455. ErrorPush();
  456. FilFreeMsgInfo(FMI);
  457. return (ErrorPop());
  458. }
  459. ///////////////////////////////////////////////////////////////////////////////
  460. //  Sequentially apply each selected filter
  461. ///////////////////////////////////////////////////////////////////////////////
  462. for (int ii = 0; ii < iNumFilters; ii++) {
  463. int iFilterResult;
  464. char szFilterPath[SYS_MAX_PATH] = "";
  465. FilGetFilterPath(pszFilters[ii], szFilterPath, sizeof(szFilterPath));
  466. if ((iFilterResult =
  467.      FilApplyFilter(szFilterPath, hFSpool, hQueue, hMessage,
  468.     FMI, pszMode)) < 0) {
  469. ErrorPush();
  470. FilFreeFilters(pszFilters, iNumFilters);
  471. FilFreeMsgInfo(FMI);
  472. return (ErrorPop());
  473. }
  474. ///////////////////////////////////////////////////////////////////////////////
  475. //  A return code greater than zero means exit filter processing loop soon
  476. ///////////////////////////////////////////////////////////////////////////////
  477. if (iFilterResult > 0)
  478. break;
  479. }
  480. FilFreeFilters(pszFilters, iNumFilters);
  481. FilFreeMsgInfo(FMI);
  482. return (0);
  483. }
  484. static int FilFilterMacroSubstitutes(char **ppszCmdTokens, SPLF_HANDLE hFSpool,
  485.      FilterMsgInfo const &FMI)
  486. {
  487. char const *const *ppszInfo = USmlGetInfo(hFSpool);
  488. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  489. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  490. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  491. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  492. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  493. int iFromDomains = StrStringsCount(ppszFrom);
  494. int iRcptDomains = StrStringsCount(ppszRcpt);
  495. FileSection FS;
  496. ///////////////////////////////////////////////////////////////////////////////
  497. //  This function retrieve the spool file message section and sync the content.
  498. //  This is necessary before passing the file name to external programs
  499. ///////////////////////////////////////////////////////////////////////////////
  500. if (USmlGetMsgFileSection(hFSpool, FS) < 0)
  501. return (ErrGetErrorCode());
  502. for (int ii = 0; ppszCmdTokens[ii] != NULL; ii++) {
  503. if (strcmp(ppszCmdTokens[ii], "@@FROM") == 0) {
  504. char *pszNewValue =
  505. SysStrDup((iFromDomains > 0) ? ppszFrom[iFromDomains - 1] : "");
  506. if (pszNewValue == NULL)
  507. return (ErrGetErrorCode());
  508. SysFree(ppszCmdTokens[ii]);
  509. ppszCmdTokens[ii] = pszNewValue;
  510. } else if (strcmp(ppszCmdTokens[ii], "@@RCPT") == 0) {
  511. char *pszNewValue =
  512. SysStrDup((iRcptDomains > 0) ? ppszRcpt[iRcptDomains - 1] : "");
  513. if (pszNewValue == NULL)
  514. return (ErrGetErrorCode());
  515. SysFree(ppszCmdTokens[ii]);
  516. ppszCmdTokens[ii] = pszNewValue;
  517. } else if (strcmp(ppszCmdTokens[ii], "@@RFROM") == 0) {
  518. char *pszNewValue = SysStrDup(FMI.szSender);
  519. if (pszNewValue == NULL)
  520. return (ErrGetErrorCode());
  521. SysFree(ppszCmdTokens[ii]);
  522. ppszCmdTokens[ii] = pszNewValue;
  523. } else if (strcmp(ppszCmdTokens[ii], "@@RRCPT") == 0) {
  524. char *pszNewValue = SysStrDup(FMI.szRecipient);
  525. if (pszNewValue == NULL)
  526. return (ErrGetErrorCode());
  527. SysFree(ppszCmdTokens[ii]);
  528. ppszCmdTokens[ii] = pszNewValue;
  529. } else if (strcmp(ppszCmdTokens[ii], "@@FILE") == 0) {
  530. char *pszNewValue = SysStrDup(FS.szFilePath);
  531. if (pszNewValue == NULL)
  532. return (ErrGetErrorCode());
  533. SysFree(ppszCmdTokens[ii]);
  534. ppszCmdTokens[ii] = pszNewValue;
  535. } else if (strcmp(ppszCmdTokens[ii], "@@MSGID") == 0) {
  536. char *pszNewValue = SysStrDup(pszMessageID);
  537. if (pszNewValue == NULL)
  538. return (ErrGetErrorCode());
  539. SysFree(ppszCmdTokens[ii]);
  540. ppszCmdTokens[ii] = pszNewValue;
  541. } else if (strcmp(ppszCmdTokens[ii], "@@MSGREF") == 0) {
  542. char *pszNewValue = SysStrDup(pszSmtpMessageID);
  543. if (pszNewValue == NULL)
  544. return (ErrGetErrorCode());
  545. SysFree(ppszCmdTokens[ii]);
  546. ppszCmdTokens[ii] = pszNewValue;
  547. } else if (strcmp(ppszCmdTokens[ii], "@@LOCALADDR") == 0) {
  548. char *pszNewValue = SysStrDup(ppszInfo[smiServerAddr]);
  549. if (pszNewValue == NULL)
  550. return (ErrGetErrorCode());
  551. SysFree(ppszCmdTokens[ii]);
  552. ppszCmdTokens[ii] = pszNewValue;
  553. } else if (strcmp(ppszCmdTokens[ii], "@@REMOTEADDR") == 0) {
  554. char *pszNewValue = SysStrDup(ppszInfo[smiClientAddr]);
  555. if (pszNewValue == NULL)
  556. return (ErrGetErrorCode());
  557. SysFree(ppszCmdTokens[ii]);
  558. ppszCmdTokens[ii] = pszNewValue;
  559. } else if (strcmp(ppszCmdTokens[ii], "@@USERAUTH") == 0) {
  560. char *pszNewValue = SysStrDup(IsEmptyString(FMI.szAuthName) ? "-":
  561.       FMI.szAuthName);
  562. if (pszNewValue == NULL)
  563. return (ErrGetErrorCode());
  564. SysFree(ppszCmdTokens[ii]);
  565. ppszCmdTokens[ii] = pszNewValue;
  566. }
  567. }
  568. return (0);
  569. }