/* Modified by PJM 02-Aug-2003 for conformance to the new filter */ /* rules in Weasel version 1.645 and later. As far as I can tell, */ /* the only change that this script needed, to conform to the new */ /* filtering rules, was a change on line 46 to the PARSE ARG */ /* statement. Be aware, however, that I am not the original author */ /* of this filter. It should probably not be trusted until Martin */ /* Kiewitz has checked it. */ /* Rexx Script to communicate with the actual filter */ /* Written by Kiewitz in year 2002 */ /* INCLUDE filewait */ /* INCLUDE email-code */ /* INCLUDE error-handler */ call RxFuncAdd "SysLoadFuncs", "RexxUtil", "SysLoadFuncs" call SysLoadFuncs call RxFuncAdd "XtraLoadFuncs", "XtraRexx", "XtraLoadFuncs" call XtraLoadFuncs "quiet" signal on syntax name ErrorHandler Parse Source MyOS MyInterpreter MyName DYNFILT_BaseDirectory = FileSpec("drive",MyName)||FileSpec("path",MyName) say "Weasel-DF-Client - (c) Copyright 2002 by Martin Kiewitz" /* Logic: Will analyse an e-mail and extract attachments one-by-one */ /* After each extraction, it will ask the Global Filter to check */ /* the attachment for validity. If something problematic is found, */ /* the part is cut out of the mail. Information E-Mail(s) will be */ /* generated by the Global Filter, so no more action is required */ /* WEASEL reply codes: */ /* 0 - OKAY, send message unmodified */ /* 1 - OKAY, send message, but reread receivers part */ /* 2 - IGNORE, but send OKAY to client */ /* Initialize Direct/C 6-Bit En/Decoding to MIME */ call DirectC_Set6bitTable "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" DYNFILT_Sender = "" DYNFILT_Receiver = "" DYNFILT_Subject = "" DYNFILT_JobName = "" parse arg NameFile CLIENT_MsgFile CLIENT_MsgTemp = Left(CLIENT_MsgFile,Length(CLIENT_MsgFile)-4)".tmp" CLIENT_SomeContentAllowed = 0 call EMAIL_InitRegionRead MultiPartMail = 0 MultiPartBoundary = "" ContentEncoding = "" ContentName = "" /* === First Analyse Header ================================================ */ Do Forever If EMAIL_ReadRegion(CLIENT_MsgFile)=0 Then Leave Select When EMAIL_Region="FROM" Then DYNFILT_Sender = EMAIL_RegionData When EMAIL_Region="TO" Then DYNFILT_Receiver = EMAIL_RegionData When EMAIL_Region="SUBJECT" Then DYNFILT_Subject = EMAIL_RegionData When EMAIL_Region="CONTENT-TYPE" Then Do /* Analyse Content-Type - Multi-Item Region */ Do Forever If EMAIL_GetItemFromRegionData()=0 Then Leave Select When EMAIL_ItemName="CONTENT-TYPE" Then Do Parse Value EMAIL_ItemData With EMAIL_ItemData "/" EMAIL_ItemData = Translate(EMAIL_ItemData) If EMAIL_ItemData="MULTIPART" Then MultiPartMail = 1 End When EMAIL_ItemName="BOUNDARY" Then MultiPartBoundary = "--"EMAIL_ItemData When EMAIL_ItemName="NAME" Then ContentName = EMAIL_ItemData Otherwise Nop End End End When EMAIL_Region="CONTENT-TRANSFER-ENCODING" Then ContentEncoding = Translate(EMAIL_RegionData) Otherwise Nop End End DYNFILT_Sender = EMAIL_NormalizeEmail(DYNFILT_Sender) DYNFILT_Receiver = EMAIL_NormalizeEmailList(DYNFILT_Receiver) ContentBegin = FILEWAIT_GetSeek(CLIENT_MsgFile) call CLIENT_Copy 1, ContentBegin-2 call LineOut CLIENT_MsgTemp, "X-FilteredBy: Dynamic-Filter/2 v0.1 by Kiewitz, using OS/2 Rexx" call LineOut CLIENT_MsgTemp, "" /* Now write the header to a log-file for debugging purposes (temporary) */ OrgMsgTemp = CLIENT_MsgTemp CLIENT_MsgTemp = DYNFILT_BaseDirectory"logging.txt" call FILEWAIT_ForWriteFile CLIENT_MsgTemp call LineOut CLIENT_MsgTemp, "===================================================[DEBUG] "Date("N")" "Time('N') call CLIENT_Copy 1, ContentBegin-2 call FILEWAIT_Close CLIENT_MsgTemp CLIENT_MsgTemp = OrgMsgTemp If MultiPartMail=0 Then Do /* Singlepart Mail */ If Length(ContentName)=0 Then ContentName = "NoName" call CharOut ,"* Got Content-Part ["ContentName"]..." If ContentEncoding="BASE64" Then Do call LineIn CLIENT_MsgFile /* Read in CR-Line */ ContentEnd = Stream(CLIENT_MsgFile, "c", "seek") call CLIENT_Copy ContentBegin, ContentEnd call CLIENT_ProcessAttachment ContentName, ContentEnd End else Do call CLIENT_Copy ContentBegin, FILEWAIT_GetSize(CLIENT_MsgFile) CLIENT_SomeContentAllowed = 1 say "is fine." End End else Do /* MIME Multipart Mail */ Do Forever /* Search for first occurance of boundary */ ContentEnd = Stream(CLIENT_MsgFile, "c", "seek") CurLine = LineIn(CLIENT_MsgFile) If Left(CurLine, Length(MultiPartBoundary))=MultiPartBoundary | Stream(CLIENT_MsgFile)\="READY" Then Leave End /* Copy Message Header to New Message */ call CLIENT_Copy ContentBegin, ContentEnd Do Forever /* Read-In Content-Header */ call EMAIL_InitRegionRead ContentEncoding = "" ContentName = "" Do Forever If EMAIL_ReadRegion(CLIENT_MsgFile)=0 Then Leave Select When EMAIL_Region="CONTENT-TYPE" Then Do /* Analyse Content-Type - Multi-Item Region */ Do Forever If EMAIL_GetItemFromRegionData()=0 Then Leave Select When EMAIL_ItemName="NAME" Then ContentName = EMAIL_ItemData Otherwise Nop End End End When EMAIL_Region="CONTENT-TRANSFER-ENCODING" Then ContentEncoding = Translate(EMAIL_RegionData) Otherwise Nop End End /* Got Content-Header Header */ If Length(ContentEncoding)>0 Then Do If Length(ContentName)=0 Then ContentName = "NoName" call CharOut ,"* Got Content-Part ["ContentName"]..." If ContentEncoding="BASE64" Then Do call CLIENT_ProcessAttachment ContentName, ContentBegin ContentEnd = FILEWAIT_GetSeek(CLIENT_MsgFile) End else Do /* Some Content is still left */ Do Forever /* Search for first occurance of boundary */ ContentEnd = Stream(CLIENT_MsgFile, "c", "seek") CurLine = LineIn(CLIENT_MsgFile) If Left(CurLine, Length(MultiPartBoundary))=MultiPartBoundary | Stream(CLIENT_MsgFile)\="READY" Then Leave End /* dont copy last boundary */ call CLIENT_Copy ContentBegin, ContentEnd CLIENT_SomeContentAllowed = 1 say "is fine." End ContentBegin = ContentEnd End If Stream(CLIENT_MsgFile)\="READY" Then Leave End /* Ending Boundary & CR */ call LineOut CLIENT_MsgTemp, MultiPartBoundary"--" call LineOut CLIENT_MsgTemp, "" End call FILEWAIT_Close CLIENT_MsgFile call FILEWAIT_Close CLIENT_MsgTemp If CLIENT_SomeContentAllowed Then Do /* Some Content was allowed, so send this message out */ say "* E-mail allowed to pass system" call FILEWAIT_ForReplaceFile CLIENT_MsgFile, CLIENT_MsgTemp exit 0 End else Do /* No Content got through filter, so don't send further */ say "* E-Mail got filtered completely" call SysFileDelete CLIENT_MsgTemp exit 2 End exit /* Base64 Attachment Processing, will decode data to temporary file and */ /* generate job for Dynamic Filter */ /* - Waits for result and filters out attachment, if required */ CLIENT_ProcessAttachment: Parse Arg ContentName, ContentBegin /* ContentBegin - Absolute Begin of Content-Header (incl. Boundary) */ /* DataBegin - Begin of Content-Base64-Data */ /* ContentEnd - End of Content-Base64-Data (w/o Boundary) */ DataBegin = FILEWAIT_GetSeek(CLIENT_MsgFile) /* Generate a new Job-ID */ JobMainFile = SysTempFileName(DYNFILT_BaseDirectory"Jobs\?????.job") JobBaseFile = Left(JobMainFile,Length(JobMainFile)-4) JobTempFile = JobBaseFile".tmp" /* Close file, so DirectC can access it */ call FILEWAIT_Close CLIENT_MsgFile ContentEnd = DirectC_DecodeFrom6bitViaFile(CLIENT_MsgFile, DataBegin, JobBaseFile".dta") call FILEWAIT_ForReadFile CLIENT_MsgFile call FILEWAIT_Seek CLIENT_MsgFile, ContentEnd /* Remove Drive/Path information from ContentName */ ContentName = FileSpec("name", ContentName) /* Generate .JOB file... */ call LineOut JobTempFile, DYNFILT_Sender call LineOut JobTempFile, DYNFILT_Receiver call LineOut JobTempFile, DYNFILT_Subject call LineOut JobTempFile, ContentName call FILEWAIT_Close JobTempFile call FILEWAIT_ForReplaceFile JobMainFile, JobTempFile /* Now wait for reply from Main Filter Script */ TimeOutTimer = 300 /* 60 seconds */ Do Forever call XtraSleep 200 If FILEWAIT_FileExists(JobMainFile)=0 Then Leave TimeOutTimer = TimeOutTimer-1 If TimeOutTimer=0 Then Leave End If FILEWAIT_FileExists(JobBaseFile".ok") Then Do /* File allowed... */ call SysFileDelete JobBaseFile".ok" call CLIENT_Copy ContentBegin, ContentEnd CLIENT_SomeContentAllowed = 1 say "is allowed." End else say "is bad." return CLIENT_Copy: Procedure Expose CLIENT_MsgFile CLIENT_MsgTemp Parse Arg StartPos, EndPos call FILEWAIT_Seek CLIENT_MsgFile, StartPos if (EndPos>StartPos) Then Do TempBuffer = CharIn(CLIENT_MsgFile, StartPos, EndPos-StartPos) call CharOut CLIENT_MsgTemp, TempBuffer End return