/* ** $VER: SortMail.br 4.5 (24.7.99) ** by Eirik Nicolai Synnes ** ** Some code borrowed from AddSOUP.thor by Magne Østlyngen ** and AddAmiNetList.br by Petter Nilsen ** ** See SortMail.guide for documentation ** */ options results options failat 31 signal on syntax signal on break_c signal on halt parse arg arguments /* ** Initialize some variables */ version = subword(sourceline(2), 4, 1) cfgfile = 'SortMail.cfg' trigskipped = 0 globals = 'sigl thorport progwin globcfg. globdata. thorpath stdout msgs. data. cursys. BBSREAD.LASTERROR THOR.LASTERROR msgfile globals' /* ** See if I'm run from Thor */ if (left(address(), 5) = 'THOR.') then thorport = address() else do say 'As of the Thor 2.5 release SortMail can only be run from Thor.' say 'Please read SortMail.guide for more information.' exit(0) end /* ** Find Thor's path and open BBSREAD ARexx port */ if ~(open(tp, 'ENV:THOR/THORPATH', 'R')) then displayerror(30, 'SortMail', 'Couldn''t find Thor''s path.') thorpath = readln(tp) close(tp) if ~(show('P', 'BBSREAD')) then do address(command) 'Run >NIL: `GetEnv THOR/THORPath`bin/LoadBBSRead' 'WaitForPort BBSREAD' if (rc ~= 0) then displayerror(30, 'SortMail', 'Couldn''t open BBSREAD''s ARexx port.') end /* ** See if another copy of SortMail is already running */ if ~(getclip('SM_Active') = '') then call notify('Another copy of SortMail is probably running.\nDo you want to continue?', 'Yes|No') if (result = 0) then exit(0) call setclip('SM_Active', 'True') /* ** Determine how SortMail was started */ address(thorport) 'CURRENTSYSTEM STEM 'cursys if (rc = 1) then call displayerror(20, 'SortMail', 'SortMail has to be run from inside a system.') if (rc > 1) then call displayerror(30, 'SortMail', 'CURRENTSYSTEM: 'THOR.LASTERROR) if (cursys.CONFNAME = '') then do if (getclip('SM_Notified') = '') then do call notify('As of Thor 2.5 mail is automatically sorted at the\ntime of import. This makes it unnecessary to run\nSortMail.br when entering a system.\n\nPlease remove the SortMail.br entry in this system''s\nconfiguration. You can find it in System\nConfiguration -> Files/Paths -> Entering System.\n\nSortMail.guide has more information.', 'Ok') call setclip('SM_Notified', 'Done') end signal cleanup end /* ** Display some progress info */ address(thorport) 'OPENPROGRESS TITLE "SortMail.br 'version'" PT "Initializing..." AT "_Abort" PCW 30' if (rc ~= 0) then call displayerror(30, 'SortMail', 'OPENPROGRESS: 'THOR.LASTERROR) progwin = result /* ** Get system information */ address(bbsread) 'GETBBSDATA "'cursys.BBSNAME'" 'bbsdata if ~(rc = 0) then call displayerror(30, 'SortMail', 'GETBBSDATA, 'cursys.BBSNAME': 'BBSREAD.LASTERROR) if (right(bbsdata.BBSPATH, 1) ~= ':') & ~(right(bbsdata.BBSPATH, 1) = '/') then bbsdata.BBSPATH = bbsdata.BBSPATH || '/' address(thorport) 'GETGLOBALCONFIG 'globcfg if ~(rc = 0) then call displayerror(30, 'SortMail', 'GETGLOBALCONFIG: 'THOR.LASTERROR) address(bbsread) 'GETGLOBALDATA 'globdata if ~(rc = 0) then call displayerror(30, 'SortMail', 'GETGLOBALDATA: 'BBSREAD.LASTERROR) if (strip(globdata.TMPDIR, 'B') = '') then globdata.TMPDIR = bbsdata.BBSPATH if (right(globdata.TMPDIR, 1) ~= ':') & ~(right(globdata.TMPDIR, 1) = '/') then globdata.TMPDIR = globdata.TMPDIR || '/' msgfile = globdata.TMPDIR || 'SortMail.' || pragma('ID') || '-' || time('S') || '.tmp' stdout = globdata.TMPDIR || 'ParseUUCP.' || pragma('ID') || '-' || time('S') || '.tmp' /* ** Get list of messages and do your stuff with them */ call getmsgarray() call procmsgs() /* ** Beat it */ signal cleanup /* ** Some error detection stuff */ error: syntax: select when (symbol('BBSREAD.LASTERROR') = 'VAR') then displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br: 'BBSREAD.LASTERROR) when (symbol('THOR.LASTERROR') = 'VAR') then displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br: 'THOR.LASTERROR) otherwise displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br returned 'rc': 'errortext(rc)) end break_c: halt: cleanup: /* ** Close progressbar if open */ if (symbol('progwin') = 'VAR') & (progwin ~= 0) then do address(thorport) 'CURRENTSYSTEM STEM 'cursys if (rc > 1) then call displayerror(30, 'SortMail', 'CURRENTSYSTEM: 'THOR.LASTERROR) 'CLOSEPROGRESS REQ 'progwin progwin = 0 end /* ** Delete temporary file if it is there */ if (exists(msgfile)) then do address(command) 'Delete QUIET FORCE "' || msgfile || '"' if (rc ~= 0) then displayerror(20, 'SortMail', 'Couldn''t delete temporary file:\n' || msgfile) end if (exists(stdout)) then do address(command) 'Delete QUIET FORCE "' || stdout || '"' if (rc ~= 0) then displayerror(20, 'SortMail', 'Couldn''t delete temporary file:\n' || stdout) end /* ** Remove ARexx clip and temporary files */ call setclip('SM_Active') if (exists('T:SortMail.result')) then address command 'Delete T:SortMail.result QUIET' /* ** Have a jolly nice day */ exit(0) /**************************************************************************** *********************** Get list of messages to process *********************** ****************************************************************************/ getmsgarray: interpret 'procedure expose 'globals CDNT_MAILFOLDER = 3 /* This conference is a virtual mail folder */ /* ** Get conference data for incoming conference */ address(bbsread) 'GETCONFDATA "'cursys.BBSNAME'" "'cursys.CONFNAME'" STEM 'confdata if (rc ~= 0) then call displayerror(30, 'SortMail', 'GETCONFDATA: 'BBSREAD.LASTERROR) if ~((confdata.CONFNETTYPE = CDNT_MAILFOLDER) | (upper(cursys.CONFNAME) = 'EMAIL')) then do call notify('SortMail.br can only be run from the EMail conference\nor email folders. Newsgroups can only be sorted when\nmessages are imported into the database.', 'Ok') signal cleanup end /* ** Build message stem */ address(thorport) 'GETMSGLISTSELECTED STEM 'msgs if ~(rc = 0) then do address(thorport) 'CURRENTMSG STEM 'msg if (rc ~= 0) then do if (THOR.LASTERROR = 'No current message.') then call displayerror(20, 'SortMail', 'You must either have a message\ndisplayed in Thor''s main window\nor select one or more messages\nin the message list window to\nrun SortMail.br.') else call displayerror(30, 'SortMail', 'CURRENTMSG: 'THOR.LASTERROR) end msgs.1 = msg.MSGNR; msgs.count = 1 end /* ** Exit if there are no messages to process */ if (msgs.count = 0) then signal cleanup return(0) /**************************************************************************** ************************** Process messages on system ************************* ****************************************************************************/ procmsgs: interpret 'procedure expose 'globals options results trigcount = 0; failcount = 0; killcount = 0; localcount = 0; owncount = 0 MDB_DELETED = 5 /* Message is deleted. */ MDB_KEEP = 7 /* Keep message. Message will not be deleted during conference packing. */ MDB_MARKED = 10 /* Message is marked. */ MDB_SUPERMARKED = 13 /* Message will not be unmarked as long as this flag is set. */ do i = 1 to msgs.count failed = 0; dodelmsg = 0; dodeluser = 0; islocal = 1; gothit = 0 drop data. head. text. msgs.i.delete = 0 /* Update progressreport */ progtext = 'Saving 'i' of 'msgs.count' messages' address(thorport) 'UPDATEPROGRESS REQ 'progwin' TOTAL 'msgs.count' CURRENT 'i' PT "'progtext'"' if (rc = 5) then break else if (rc > 0) then call displayerror(rc, 'SortMail', 'UPDATEPROGRESS: 'THOR.LASTERROR, msgs.i) /* ** Read message data stem */ address(bbsread) 'READBRMESSAGE "'cursys.BBSNAME'" "'cursys.CONFNAME'" 'msgs.i' DATASTEM 'data if ~(rc = 0) then do call displayerror(30, 'SortMail', 'READBRMESSAGE: 'BBSREAD.LASTERROR, msgs.i) iterate i end /* ** If messsage is deleted or superunread then skip it */ if (bittst(data.FLAGS, MDB_DELETED)) then iterate i /* ** Save message to disk */ address(thorport) 'SAVEMESSAGE "' || cursys.BBSNAME || '" "'cursys.CONFNAME'" MSGNR ' || msgs.i || ' FILE "' || msgfile || '"' if ~(rc = 0) then do call displayerror(20, 'SortMail', 'SAVEMESSAGE: 'THOR.LASTERROR, msgs.i) msgs.i.delete = 0 iterate i end else do if (bittst(data.FLAGS, MDB_KEEP)) then msgs.i.delete = 0 else msgs.i.delete = 1 end end /* ** Run ParseUUCP */ 'UPDATEPROGRESS REQ 'progwin' TOTAL '0' CURRENT '0' PT "Running ParseUUCP..."' address(command) thorpath || 'bin/ParseUUCP >"' || stdout || '" "' || cursys.BBSNAME || '" "' || msgfile || '" PUBSCREEN "' || globcfg.PUBSCREENNAME || '" ' parseres = rc stdoutmsg = '' if(open(in, stdout, 'R')) then do do while ~(eof(in)) line = readln(in) if (line ~= "") then stdoutmsg = stdoutmsg || line || '\n' end call close(in) end if ~(parseres = 0) then do if (stdoutmsg = '') then stdoutmsg = 'No error message given!' call displayerror(parseres, 'ParseUUCP', stdoutmsg) end else if ~(stdoutmsg = '') then call displayerror(5, 'ParseUUCP', 'ParseUUCP message:\n' || stdoutmsg) address(thorport) 'UPDATECONFWINDOW' if (notify('Do you want to delete the\nprocessed messages?', 'Yes|No')) then do address(bbsread) do i = 1 to msgs.count /* Delete message */ if (msgs.i.delete) then do 'UPDATEBRMESSAGE "'cursys.BBSNAME'" "'cursys.CONFNAME'" 'msgs.i' SETDELETED' if (rc ~= 0) then displayerror(30, 'SortMail', 'UPDATEBRMESSAGE: 'BBSREAD.LASTERROR, msgs.i) end end address(thorport) 'UPDATECONFWINDOW' end return(0) /**************************************************************************** *********************** Display requester / type message ********************** ****************************************************************************/ notify: interpret 'procedure expose 'globals parse arg message, choices seperator = index(choices, '|') if (seperator > 0) then do firstchoice = substr(choices, 1, seperator - 1) secondchoice = substr(choices, seperator + 1) end address(bbsread) 'BUFMODE ENDCOPYBACK' message = substitute(message, '"', '*"') address(thorport) 'REQUESTNOTIFY "'message'" "'choices'"' reqres = result address(bbsread) 'BUFMODE COPYBACK' return(reqres) /**************************************************************************** *********************** Display error and return or quit ********************** ****************************************************************************/ displayerror: interpret 'procedure expose 'globals parse arg returned, caller, errmsg, msgno if (msgno ~= '') then errhead = caller' returned 'returned' on message #'msgno':' else errhead = caller' returned 'returned' in line 'sigl':' select when (returned > 0) & (returned < 20) then do call notify(errhead || '\n' || errmsg, 'Continue|Abort') if (result = 0) then signal cleanup end when (returned > 19) then do call notify(errhead || '\n' || errmsg, 'Abort') signal cleanup end otherwise nop end drop THOR.LASTERROR BBSREAD.LASTERROR return(0) /**************************************************************************** ********************* Substitute a string within a string ********************* ******** Shamelessly ripped from Troels Walsted Hansen's UUDecode.thor ******** ****************************************************************************/ substitute: interpret 'procedure expose 'globals parse arg str, org, new lastfound = 0 found = index(str, org) do while found > lastfound secondpart = substr(str, found + length(org)) firstpart = substr(str, 1, length(str) - length(substr(str, found))) str = firstpart || new || secondpart lastfound = found + length(new) found = index(str, org, lastfound) end return(str)