home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / VIREX312.ZIP / VIREXX.CMD
OS/2 REXX Batch file  |  1993-03-16  |  38KB  |  1,079 lines

  1. /* Virexx.cmd*/
  2. echo off
  3. parse upper arg path file ext maxmec node
  4. lpath = STRIP(path)
  5. lfile = STRIP(file)
  6. lext = STRIP(ext)
  7. lmaxmec = STRIP(maxmec)
  8. lnode = STRIP(node)
  9.      
  10. /*    Rexx program for virus checking uploaded files for Maximus 2.01wb
  11.               Doug Cullen  1:157/603.52@fidonet 12 Oct. 92
  12.               Revised 24 Jan. 93
  13.               Mucho further revision 4 Feb. 93
  14.       Rev to do generic scans and scan nested compressed files.
  15.           Also added Node variable for multinode BBS's.
  16.           Cleaned up code for various errors.
  17.           Working directories deleted at the completion.
  18.           Modifications by Dave Sloan 81:950/10@OS2net March 12,1992
  19. */
  20. /* ---------------------------------------------------------------------------*/
  21. /*   - - - - - - - - - -   C O N F I G U R A T I O N - - - - - - - - - - -    */
  22. /* -----  Set these variables for your System ------------------------------- */
  23.  
  24. /* 1) LISTS  (lists of file extensions and how to deal with them)                                                                */
  25. /* ***** THESE MUST BE UPPER CASE OR THEY WONT WORK !!!!!    ****** */
  26.  
  27. arc_list='.ZIP .LZH .ARC .ARJ .ZOO'     /* list of defined achives */
  28. reject_list='.GIF .TIF .# .## .###'     /* list of file extensions to reject */
  29.                                         /* # extensions prevent confusion */
  30.                                         /* numbers that are translated later */
  31. pass_list='.C .BAT .CMD '               /* list of file extensions to pass */
  32.                                         /* automatically */
  33. series_list='.# .## .### .A##'          /* list of file extensions to pass */
  34.                                         /* #'s will match any NUMBER */
  35.  
  36. /* 2) VARIABLES */
  37.  
  38. bbsname = 'Tech Talk Toll'              /* Your BBS name */
  39. oldest = 8001                           /* date for oldest file YYMM */
  40.                                         /* 8001 = jan 80 use 0000 to disable */
  41. descblanks = 31                         /* # of blanks to add to file desc. */
  42.                                         /* to align properly*/
  43.                                         /* align left edge*/
  44.  
  45.  
  46. /* 3) PATHS (paths to various files and directories needed by VIREXX */
  47. /* ****NOTE**** Change only UPPER CASE PARTS*/
  48. maxpath      = 'C:\MAX'                  /* Path to Maximus*/
  49. badfiledir   = 'C:\MAX\BADFILES'         /* path to copy bad files to*/
  50. testfiledir  = 'C:\MAX\filete'lnode      /* dir for testing lnode = 1,2 ect.*/
  51.           /* Sample virexx1.cmd for node 1
  52. @echo off
  53. c:
  54. cd\max
  55. virexx %1 %2 %3 %4 1
  56. */
  57. miscpath     = 'C:\FILE\MISCUTIL'        /* Path to uploaded files.bbs*/
  58.                                          /* NO FOLLOWING BACKSLASH*/
  59.                                          /* Must be UPPER case !!!!*/
  60. logname     = 'D:\LOG\vire'lnode'.log'   /* Virexx Log*/
  61. maxlog      = 'C:\MAX\'node              /* path to max log file*/
  62. logfile     = 'D:\LOG\vire'lnode'.log'   /* path and name of Virexx log*/
  63. file_bad    = lmaxmec'file_bad.bbs'       /* path to bad file message*/
  64. file_ok     = lmaxmec'file_ok.bbs'        /* path to good file message*/
  65. commentfile = 'C:\ARC\TECHZIP.FIL'       /* bbs add file for zip comment*/
  66. database    = 'C:\MAX\filedata.fil'      /* database of additional file info*/
  67. userfile    = 'C:\MAX\lastus0'lnode'.bbs' /* name of lastuser file lastus01 when lnode = 1*/
  68. debugfile   = 'C:\MAX\debug.txt'          /* to  debug = 1*/
  69. /* 4) COMMANDS (Command lines for various programs called by VIREXX)*/
  70. /*    NOTE: Virexx appends the filename to the end of the archiver commands*/
  71. /*    so the space at the end is important*/
  72.  
  73. lh_command='lh x /o /i '                /* command to extract .lzh file*/
  74.                                         /* this ones for 32bit LH2 2.12*/
  75. zip_command1 ='pkunzip -o '             /* command to extract .ZIP files*/
  76.                                         /* with version 1.x signature*/
  77.                                         /* this ones for PKUNZIP2 1.02*/
  78. zip_command2 ='unzip -o '               /* command to extract .ZIP files*/
  79.                                         /* with version 2.x signature*/
  80.                                         /* this ones for InfoZip unzip 5.0*/
  81. arj_command ='unarj e '                 /* unarj command for Robert Jungs*/
  82.                                         /* Demo version 2.10 Unarj*/
  83. /* arj_command ='gnunarj x '*/          /* unarj command for 32bit GNU port*/
  84.                                         /* of R. Jungs Demo Unarj 2.30*/
  85. arc_command ='arc2 xo '                 /* command to extract archive using*/
  86.                                         /* SEA's ARC2 ver 6.00*/
  87. zoo_command ='zoo e:O '                 /* command to extract archive using*/
  88.                                         /* ZOO 2.1 (renamed to ZOO2.exe)*/
  89. comment_command = 'pkzip -z -k '        /* command to add comment to .zip file*/
  90.  
  91. zipdir = ''                    /* path to arcive subdirectory */
  92.  
  93. /* 5) SWITCHES (switches for various functions. Use 1 for ON, 0 for OFF)*/
  94.  
  95. mlog       = 0                          /* Add VIREXX entry to MAXLOG*/
  96. sdi        = 0                          /* enter FILE_ID.DIZ or DESC.SDI to*/
  97.                                         /* files.bbs if found.*/
  98. zipcomment = 1                          /* Add bbs comment to .zip files*/
  99. dbase      = 1                          /* write entry to file database*/
  100. debug      = 0                          /* turns on extra output to assist*/
  101.                                         /* in debugging problems*/
  102. /* -------------------------------------------------------------------------- */
  103. /*    - - - - -  E N D    O F    C O N F I G U R A T I O N  - - - - - - -     */
  104. /* ---------------------------- Main Program -------------------------------- */
  105. /*trace all*/
  106. if debug then do
  107.   file = LINEOUT(debugfile,'parameters 'lpath' 'lfile' 'lext' 'lnode' 'lmaxmec)
  108.   file = LINEOUT(debugfile,'initialzing')
  109. end
  110. call initialize                        /* initialize program */
  111. fullname = lpath||lfile||lext          /* full pathname to file(s) */
  112.  
  113. /* Look for all files with the specified name*/
  114. call SysFileTree fullname,'lfile','FSO'
  115. /* If any exist then process them*/
  116. if lfile.0 > 0 then do
  117.  
  118. /* Setup to trap errors and inform user to inform sysop*/
  119. status = 'INCOMPLETE'
  120. if lfile.0 = 1 then
  121.   call bbsmsg
  122. status = 'GOOD'
  123.  
  124. /* Perform check for all of the files*/
  125. /* This version is made for generic scans of subdirectories*/
  126. do filecnt = 1 to lfile.0
  127.  
  128. /* Get the first/next file to process*/
  129. fullname = TRANSLATE(lfile.filecnt)     /* full pathname to file */
  130. filename = FILESPEC('NAME',fullname)    /* file name */
  131. lpath    = DELSTR(fullname, POS(filename, fullname))
  132. dot = POS('.',filename)
  133. lfile = DELSTR(filename, dot)
  134. lext = DELSTR(filename, 1, dot - 1)
  135.  
  136. select
  137.   when lext =  miscpath then do   /* file had no extension */
  138.     if debug then
  139.       file = LINEOUT(debugfile,'no file extension')
  140.     'COPY 'fullname badfiledir     /* move to badfile dir    */
  141.     'ERASE 'fullname
  142.     status = 'NOEXT'
  143.   end   /* do */
  144.  
  145.   /* expand files in test directories*/
  146.   when POS(lext,arc_list)>0 then
  147.     call unarchive
  148.  
  149.   when  POS(lext,pass_list)>0 then do
  150.     if debug then
  151.       file = LINEOUT(debugfile,'AutoPass 'fullname)
  152.     'COPY 'fullname testfiledir
  153.     status = 'PASS'
  154.   end /* do */
  155.  
  156.   when  POS(lext,reject_list)>0 then do
  157.     if debug then
  158.       file = LINEOUT(debugfile,'Rejecting 'fullname)
  159.     'ERASE 'fullname
  160.     status = 'REJECT'
  161.   end /* do */
  162.  
  163.   when lext = '.EXE' || lext = '.COM' then do
  164.     if debug then
  165.       file = LINEOUT(debugfile,'rejecting 'fullname' exe or com')
  166.     'COPY 'fullname testfiledir
  167.     'COPY 'fullname badfiledir
  168.     'ERASE 'fullname
  169.     status = 'EXE'
  170.   end /* do */
  171.  
  172.   otherwise do
  173.     trans_ext=TRANSLATE(lext,'##########','1234567890')
  174.     if debug then
  175.       file = LINEOUT(debugfile,'extension is now 'trans_ext)
  176.     if POS(trans_ext,series_list) then do
  177.       if debug then
  178.         file = LINEOUT(debugfile,'AutoPass serial file 'fullname)
  179.       status = 'PASS'
  180.       'COPY 'fullname' 'testfiledir
  181.     end /* do */
  182.     else do
  183.       if debug then
  184.         file = LINEOUT(debugfile,fullname' is UNKNOWN type')
  185.       status = 'UNKNOWN'
  186.       'COPY 'fullname' 'badfiledir
  187.       'ERASE 'fullname
  188.     end /* else */
  189.   end /* do */
  190. end /* select */
  191.  
  192. if status = 'GOOD' | status = 'EXE' then do
  193.   if debug then
  194.     file = LINEOUT(debugfile,"checking oldfiles")
  195.   if oldest <> '0000' then
  196.     call checkdate       /* check for old files       */
  197.                                                  /* unless turned off         */
  198.   if debug then
  199.     file = LINEOUT(debugfile,"checking descriptions")
  200.   if sdi then
  201.     call checkdesc          /* check for file descriptions       */
  202.   if debug then
  203.     file = LINEOUT(debugfile,"calling scanner")
  204.   call scanner                    /* scan for virii if the file unpacks OK */
  205. end /* do */
  206.  
  207. if status = 'PASS' then do
  208.   if debug then
  209.     file = LINEOUT(debugfile,"calling scanner")
  210.   call scanner                   /* scan for virii if the file unpacks OK */
  211. end /* do */
  212. if lfile.0 = 1 then do
  213.   if debug then
  214.     file = LINEOUT(debugfile,"doing filestats")
  215.   call filestats
  216.   if debug then
  217.     file = LINEOUT(debugfile,"sending BBS file")
  218.   call sendmsg                   /* send appropriate msg to user   */
  219. end
  220. if debug then
  221.   file = LINEOUT(debugfile,"updating database")
  222. if dbase then call databaseout                 /* add fileinfo to data base      */
  223.  
  224. if zipcomment & lext = '.ZIP' then do
  225.   if debug then
  226.     file = LINEOUT(debugfile,"adding zip comment")
  227.   if status = 'GOOD' then
  228.     zipdir||comment_command' 'fullname' < 'commentfile
  229. end /* do */
  230. if debug then
  231.   file = LINEOUT(debugfile,"cleaning up test directories")
  232. call cleanupdir                  /* clean up test directory               */
  233. if debug then
  234.   file = LINEOUT(debugfile,'cleaning up')
  235. end /* Loop for all files*/
  236. end /* Files exist*/
  237. cleanup:
  238.   call RxFuncDrop 'SysFileTree'
  239.   file = LINEOUT(debugfile)
  240. exit
  241.  
  242. /* ------------ end -  main program ------------------ */
  243.  
  244. /*     Possible Status Values
  245.  
  246.         GOOD     = No problems
  247.         BAD      = Failed to Unarchive 
  248.         INFECTED = Failed Virus Scan 
  249.         UNKNOWN  = File extension was not of any type defined
  250.         EXE      = File was .exe or .com (I treat these with a great 
  251.                     deal of suspicion! )
  252.         NOEXT    = file had no extension i.e. 'filename.'
  253.         OLD      = archive contained files older than oldest date
  254.         PASS     = Scan and PASS thru (use for other extension you
  255.                    want to pass automatically (GIF, TIF or whatever)
  256.         REJECT   = file was in the reject list.  Deleted and the user
  257.                    is sent a warning note
  258. */
  259.  
  260. /* ----- Subroutine Initialize ----------------------- */
  261. initialize:
  262.  if lext = '' then
  263.    call USAGE
  264.  dontask = '/N'
  265.  call RxFuncAdd 'SysFileTree','RexxUtil','SysFileTree'
  266.  call RxFuncAdd 'SysMkDir','RexxUtil','SysMkDir'
  267.  call RxFuncAdd 'SysRmDir','RexxUtil','SysRmDir'
  268.                                    /* make sure Rexxutils loaded */
  269.  call SysFileTree testfiledir,'dir','DO'
  270.  if dir.0 = 0 then
  271.    call SysMkDir testfiledir
  272.  call SysFileTree badfiledir,'dir','DO'
  273.  if dir.0 = 0 then
  274.    call SysMkDir badfiledir
  275.  if stream(testfiledir||'\*.*','c','query exist')  <> '' then
  276.    'ERASE 'testfiledir'\*.* 'dontask   /* cleanup test dir */
  277.  testfiledir.0 = 0 /* No arcs within arcs yet*/
  278.  parse value DATE('N') with dd mmm yyyy      /* dd   = day
  279.                                                 mmm  = month
  280.                                                 yyyy = year */
  281.  dd = RIGHT(dd,2,'0')
  282.  archsize = 0
  283.  logdate = ' 'dd' 'mmm' 'TIME()' VIRX'
  284.  uldate = dd'-'mmm'-'yyyy
  285.  logentry = '+'logdate' checking 'filename   /* build up log entry */
  286.  file = LINEOUT(logfile,logentry)            /* and write log entry */  
  287.  file = LINEOUT(logfile)
  288.  nested = NO                                 /* clear nested */
  289.  ZIPTYPE =''
  290.  
  291.  /* get user name from lastuser file */
  292.  tempname=STRIP(CHARIN(userfile,1,36),,'00'x)
  293.  username=tempname
  294.  if \(SUBWORD(tempname,3,1)='') then
  295.    username=SUBWORD(tempname,1,1)' 'SUBWORD(tempname,2,2)
  296. /* check that dirs exist - if not make them */
  297.  
  298.  
  299. return
  300.  
  301. /* ----- End - Initialize ---------------------------- */
  302.  
  303. /* ----- Subroutine Unarchive ------------------------ */
  304.  
  305. unarchive:
  306.  ffname = fullname
  307.  fname = filename
  308.  if debug then
  309.    file = LINEOUT(debugfile,'unarchiving 'fname)
  310.  testdir = testfiledir
  311.  signature = CHARIN(ffname,1,6)
  312.  temp = stream(ffname,'c','close')
  313.  Select
  314.  
  315.    when (substr(signature,1,5) = 'PK') then do  /* version 2.x zip file    */
  316.      call unzip2
  317.    end /* do */
  318.  
  319.    when (substr(signature,1,4) = 'PK') then do  /* version 1.x zip file    */
  320.      call unzip1
  321.    end /* do */
  322.  
  323.    when (substr(signature,3,3) = '-lh'  ) then do      /* .lzh file          */
  324.      call unlzh
  325.    end /* do */
  326.  
  327.    when (substr(signature,1,2) = '`Ω'   ) then do      /* .arj file          */
  328.      call unarj
  329.    end /* do */
  330.  
  331.    when (substr(signature,1,3) = 'ZOO'  ) then do      /* .zoo file          */
  332.      call unzoo
  333.    end /* do */
  334.  
  335.    when lext = '.ARC' then do                            /* .arc file           */
  336.      call unarc
  337.    end /* do */
  338.  
  339.    otherwise do
  340.      status = 'BAD'
  341.    end /* do */
  342.  
  343. end /* select */
  344.  
  345. if status = 'GOOD' then
  346.   call checknested
  347. else
  348.   if status = 'BAD' then do
  349.     'COPY 'fullname badfiledir
  350.     'ERASE 'fullname
  351.   end /* do */
  352.  
  353.  
  354. return
  355.  
  356. /* ----------- End - unarchive -----------------------------*/
  357.  
  358. /* ------- look for description files ---------------------- */
  359. /* ------- (FILE_ID.DIZ or DESC.SDI)inside archive --------- */
  360.  
  361. checkdesc:
  362.  fileinfo = testfiledir'\file_id.diz'
  363.  if stream(fileinfo,'c','query exist') <> '' then do 
  364.    i = 0
  365.    do until lines(fileinfo)=0
  366.      i = i + 1
  367.      mytext.i = LINEIN(fileinfo)
  368.      mytext.1 = STRIP(mytext.i)
  369.      bbsfile = lpath||'files.bbs'
  370.      if i = 1 then
  371.        file =  LINEOUT(bbsfile,filename' 'mytext.i)
  372.      else
  373.        file =  LINEOUT(bbsfile,COPIES(' ',descblanks)||mytext.i)
  374.      desc = 'DONE'
  375.    end /* do */
  376.    file = LINEOUT(bbsfile)
  377.    file = LINEOUT(fileinfo)
  378.  end /* do */
  379.  if desc <> 'DONE' then do
  380.    fileinfo = testfiledir'\desc.sdi'
  381.    if stream(fileinfo,'c','query exist') <> ''then do 
  382.      i = 0
  383.      do until lines(fileinfo)=0
  384.        i = i + 1
  385.        mytext.i = LINEIN(fileinfo)
  386.        mytext.i = STRIP(mytext.i)
  387.        bbsfile = lpath||'files.bbs'
  388.        if i = 1 then
  389.          file = LINEOUT(bbsfile,filename' 'mytext.i)
  390.        else
  391.          file = LINEOUT(bbsfile,COPIES(' ',descblanks)||mytext.i)
  392.      end /* do */
  393.      file = LINEOUT(bbsfile)
  394.      file = LINEOUT(fileinfo)
  395.    end /* do */
  396.  end 
  397. return
  398. /* ------ end of checkdesc ------------- */
  399.  
  400. /* - Run McAffees Scan on testfiledir - */
  401.  
  402. scanner:
  403.   scancmd='os2scan 'testfiledir'\*.* /a /d /NOEXPIRE'
  404.                                         /* command line for your*/
  405.                                         /* virus scanner*/
  406.   /* Test the files in the main package*/
  407.   scancmd
  408.   if RC>0 then do
  409.     if RC=1 then
  410.       status = 'INFECTED'
  411.     else
  412.       status = 'ERROR'
  413.   end
  414.   /* Test the subdirectories*/
  415.   if testfiledir.0 > 0 then do
  416.  
  417.     push testfiledir
  418.     do ii = 1 to testfiledir.0
  419.       testfiledir = testfiledir.ii
  420.       scancmd='os2scan 'testfiledir'\*.* /a /d /NOEXPIRE'
  421.  
  422.       scancmd
  423.       if RC>0 then do
  424.         if RC=1 then
  425.           status = 'INFECTED'
  426.         else
  427.           status = 'ERROR'
  428.         leave
  429.       end
  430.  
  431.     end
  432.     pull testfiledir
  433.   end
  434.  
  435. return
  436.  
  437. /* ----------end --  scanner ------------- */
  438.  
  439. /* -  clean up testfile dir when we're done - */
  440.  
  441. cleanupdir:
  442.   workdrive
  443.   'CD\'
  444.   if stream(testfiledir||'\*.*','c','query exist')  <> '' then
  445.     'ERASE 'testfiledir'\*.* 'dontask   /* cleanup test dir     */
  446.   if testfiledir.0 > 0 then do
  447.     do ii = 1 to testfiledir.0
  448.       if stream(testfiledir.ii||'\*.*','c','query exist') <> '' then do
  449.         'ERASE 'testfiledir.ii'\*.* 'dontask  /* cleanup 2nd test dir */
  450.       end
  451.       call SysRmDir testfiledir.ii
  452.     end
  453.   end
  454.   /* Remove test subdirectory if complete*/
  455.   if filecnt = lfile.0 then
  456.     call SysRmDir testfiledir
  457. return
  458. /* ------- end -- cleanupdir ---------------- */  
  459.  
  460. /*  ----------- Subroutine SendMsg --------------------------- */
  461. /*  enter appropriate messages to log(s) and bbs user          */
  462.  
  463. sendmsg:
  464.  fileentry =''
  465.  select 
  466.    when status = 'BAD' then do
  467.      logentry = '!'logdate filename' failed extract - moved to badfiles'
  468.      fileentry =  filename" failed to extract from archive - uploaded by: "username
  469.    end /* do */
  470.    when status = 'EXE' then do
  471.      logentry = '!'logdate' 'filename' suspicious  - moved to badfiles'
  472.      fileentry = filename" exec, moved to prevent trojan, virii ...-uploaded by: "username
  473.    end /* do */
  474.    when status = 'UNKNOWN' then do 
  475.      logentry = '!'logdate' 'filename' UNKNOWN type - moved to badfiles'
  476.      fileentry = filename" of unknown type, moved - uploaded by: "username
  477.    end /* do */
  478.    when status = 'INFECTED' then do
  479.      logentry = '!'logdate' 'filename' INFECTED!!! - moved to badfiles'
  480.      fileentry = filename" INFECTED - triggered scanner -uploaded by: "username
  481.    end /* do */
  482.    when status = 'GOOD' then do
  483.      logentry = '+'logdate' 'filename' OK credit given' 
  484.      file = LINEOUT(logfile,RIGHT('Filesize:',32)' 'fsize' bytes, dated: 'fildate)
  485.      file = LINEOUT(logfile,RIGHT(numfiles,35)' files, Newest: 'newdate' - Oldest: 'olddate)
  486.      if ZIPTYPE \= '' then do
  487.        logentry = RIGHT('archive was ',35)' 'ZIPTYPE
  488.        file = LINEOUT(logfile,RIGHT('Uploaded by:',35)' 'username)
  489.      end
  490.      else
  491.        logentry = RIGHT('Uploaded by:',35)' 'username
  492.    end
  493.    when status = 'NOEXT' then do
  494.      logentry = '!'logdate' 'filename' had no .ext - moved to badfiles'
  495.      fileentry = filename" had no extension, moved - uploaded by:"username
  496.    end /* do */
  497.    when status = 'REJECT' then do
  498.      logentry = '!'logdate' 'filename' was in reject list - deleted'
  499.      fileentry = filename" on reject list, deleted - uploaded by:"username
  500.    end /* do */
  501.    when status = 'OLD' then do
  502.      logentry = '!'logdate' 'filename' was too old - moved to badfiles'
  503.      fileentry = filename" was older than allowed - uploaded by: "username
  504.    end /* do */
  505.    when status = 'PASS' then do
  506.      file = LINEOUT(logfile,'+'logdate' 'filename' ok - credit given (AutoPass)')
  507.      logentry = logfile,RIGHT('Uploaded by:',35)' 'username
  508.    end
  509.    otherwise do
  510.      logentry = '!'logdate' ERROR running ViREXX'
  511.      fileentry = filename "ERROR running ViREXX"
  512.    end /* do */
  513.  end /* select */
  514.  
  515.  file = LINEOUT(logfile,logentry)                /* write entry to Virexx log   */
  516.  file = LINEOUT(logfile)
  517.  
  518.  
  519. if Mlog then do
  520.   file = LINEOUT(maxlog,logentry)    /* write to Max log if enabled */
  521.   file = LINEOUT(maxlog)
  522. end
  523.  
  524. if status = 'BAD' | status = 'INFECTED' | status = 'UNKNOWN' | status = 'EXE' | status = 'NOEXT' | status = 'OLD'  then do
  525.   badfilebbs=badfiledir'\files.bbs'
  526.   file = LINEOUT(badfilebbs,fileentry)
  527.   file = LINEOUT(badfilebbs)
  528. end /* do */
  529.  
  530. call tokens                         /* load mecca tokens for .bbs output  */
  531. call bbsmsg                         /* write file_ok.bbs or file_bad.bbs  */ 
  532. return
  533.  
  534.  
  535. /* ----- check date - move to badfilesarchive if it contains ----- */
  536. /* ----- files older than oldest ----------------------------------*/
  537.  
  538. checkdate:
  539.   datelist=''
  540.   archsize = 0
  541.   numfiles = 0
  542.   SrchFile = testfiledir'\*.*'
  543.   call SysFileTree SrchFile,'file','FT'
  544.   oldestfile = ''
  545.   call TestDate
  546.   if testfiledir.0 > 0 then do
  547.     do ii = 1 to testfiledir.0
  548.       SrchFile = testfiledir.ii'\*.*'
  549.       if debug then
  550.         say SrchFile
  551.       call SysFileTree SrchFile,'file','FT'
  552.       call TestDate
  553.     end
  554.   end
  555.   DROP(file.)
  556. return   /* checkdate */
  557.  
  558. /* Get oldest and newest dates*/
  559. TestDate:
  560. do i = 1 to file.0
  561.  
  562.   fsize = WORD(file.i, 2)
  563.   archsize = archsize + fsize
  564.   numfiles = numfiles + 1
  565.  
  566.   testdate  = SUBSTR(file.i, 1, 2)||SUBSTR(file.i, 4, 2)
  567.   if testdate > oldest then do
  568.     if oldestfile <> '' then do
  569.       if testdate > newestfile then
  570.         newestfile = testdate
  571.       else
  572.       if testdate < oldestfile then
  573.         oldestfile = testdate
  574.     end /* do */
  575.     else do
  576.       oldestfile = testdate
  577.       newestfile = testdate
  578.     end /* do */
  579.   end
  580.   else do 
  581.     status = 'OLD'
  582.     'COPY 'fullname badfiledir
  583.     'ERASE 'fullname
  584.   end /* do */
  585. end  /* do */
  586. return
  587. /* ----- end -- checkdate ---- */
  588.  
  589. /* ------ Unzip - run unzip on filename ------- */
  590. unzip1:
  591.   'CD 'testdir
  592.   if debug then
  593.     file = LINEOUT(debugfile,'unzipping version 1.x file 'fname)
  594.   ZIPTYPE = 'Zip 1.x'
  595.   zipdir||zip_command1' 'ffname
  596.   if RC = 0 then do                             /* unzipped OK           */
  597.     status = 'GOOD'
  598.   end
  599.   else do                                       /* failed to unzip       */
  600.     status = 'BAD'
  601.   end  /* do */
  602. return
  603.  
  604. /* end unzip1 */
  605. /* ------ Unzip2 - run unzip on version 2.x filename ------- */
  606. unzip2:
  607.  if debug then
  608.    file = LINEOUT(debugfile,'unziping type 2.x zipfile: 'fname)
  609.  'CD 'testdir
  610.  ZIPTYPE = 'Zip 2.x'
  611.  zipdir||zip_command2' 'ffname                 /* unzip file to testdir */
  612.  if RC = 0 then do                             /* unzipped OK           */
  613.    status = 'GOOD'
  614.  end
  615.  else do                                       /* failed to unzip       */
  616.    status = 'BAD'
  617.  end  /* do */
  618. return  
  619.  
  620. /* end unzip2 */
  621. /* ------ Unzoo - run zoo on filename ------- */
  622. unzoo:
  623.   'CD 'testdir
  624.   if debug then
  625.     file = LINEOUT(debugfile,'unzooing 'fname)
  626.   zipdir||zoo_command' 'ffname
  627.   if RC = 0 then do                             /* unzipped OK           */
  628.     status = 'GOOD'
  629.   end
  630.   else do                                       /* failed to unzip       */
  631.     status = 'BAD'
  632.   end  /* do */
  633. return
  634.  
  635. /* end unzoo */
  636.  
  637.  
  638. /* ---------  unarj -- run unarj on filename --------------- */
  639. unarj:
  640.      /* written for Robert Jung's Unarj 2.10                                */
  641.      /* this section will copy the file to the test file dir and also copy  */
  642.      /* unarj to the same directory, run unarj and cleanup afterwards. If   */
  643.      /* your test dir is on a different drive be sure to fix this section   */
  644.  
  645.   'CD 'testdir
  646.   if debug then
  647.     file = LINEOUT(debugfile,'unarjing 'fname)
  648. /*     unarj e fname                                     /* unarj file        */
  649. */
  650.   zipdir||arj_command' 'ffname
  651.   if RC = 0 then do                                 /* unarjed OK       */
  652.     status = 'GOOD'
  653.   end /* do */
  654.   else do          
  655.     status = 'BAD'                              /* failed to unarj   */
  656.   end  /* do */
  657.   'CD 'maxpath
  658. return
  659.  
  660. /* end unarj */
  661.  
  662. /* ----------- unlzh -- unlzh filename ----------- */
  663.          
  664. unlzh:
  665.   /* written for LH32  2.21    */
  666.   'CD 'testdir
  667.   if debug then
  668.     file = LINEOUT(debugfile,'unlhzing 'fname)
  669.   zipdir||lh_command' 'ffname                       /* unlzh file to testdir */
  670.   if RC = 0 then do                             /* unlzh'd OK           */
  671.     status = 'GOOD'
  672.   end
  673.   else do                                       /* failed to unlzh       */
  674.     status = 'BAD'
  675.   end  /* do */
  676. return
  677.  
  678. /* end unlzh */
  679.  
  680. /* ----- unarc -- unarc filename using ARC2 ---- */
  681.  
  682. unarc:
  683.   /* written for ARC2 6.00p                                              */
  684.   /* this section will copy the file to the test file dir and also copy  */
  685.   /* arc2 to the same directory, run arc2 and cleanup afterwards. If     */
  686.   /* your test dir is on a different drive be sure to fix this section   */
  687.  
  688.   if debug then
  689.     file = LINEOUT(debugfile,'unarcing 'fname)
  690.   'COPY 'ffname testdir                          /* copy file to test dir  */
  691.   'CD 'testdir
  692.   zipdir||arc_command' 'ffname                                      /* unarc file        */
  693.   if RC = 0 then do                                 /* unarced OK        */
  694.     status = 'GOOD'
  695.     'ERASE 'fname
  696.   end
  697.   else do                                          /* failed to unarc   */
  698.     status = 'BAD'
  699.   end  /* do */
  700.   'CD 'maxpath
  701. return
  702.  
  703. /* end unarc  */
  704.  
  705. /* ---- checknested -- look for nested archives ------ */ 
  706.  
  707. checknested:
  708.   testfiledir.0 = 0                  /* testdir is where unpacked files go*/
  709.   testcnt = 0
  710.   call searchnest
  711.   if testcnt > 0 then do             /* check for 2nd level of nested*/
  712.     push testfiledir
  713.  
  714.     /* Do until no more compressed files found*/
  715.     do until testfiledir.0 = testcnt
  716.       startdir = testfiledir.0 + 1
  717.       testfiledir.0 = testcnt
  718.       
  719.       do ii = startdir to testfiledir.0
  720.         testfiledir = testfiledir.ii
  721.         call searchnest
  722.       end
  723.  
  724.     end
  725.     pull testfiledir
  726.   end /* do */
  727. return /* checknested */
  728.  
  729.  
  730.   /*     searchnest -- does the actual searching for files with   */
  731.   /*     archive type extensions                                  */
  732.  
  733.  
  734. searchnest:
  735.  
  736.   workdrive = FILESPEC("drive",testfiledir)
  737.   SrchFile = testfiledir'\*.arj'           /* look for .arj files          */
  738.   call SysFileTree SrchFile,'file','FO'
  739.   if file.0 > 0 then
  740.   do i = 1 to file.0
  741.     ffname = file.i
  742.     fname = FILESPEC("name",ffname)
  743.     /* Find path to the directory*/
  744.     fpath = FILESPEC("path",ffname)
  745.     /* Takeout last \ */
  746.     fpath = STRIP(fpath,'T','\')
  747.     /* Change to working drive*/
  748.     workdrive
  749.     /* Get to the correct subdirectory*/
  750.     'CD 'fpath
  751.     /* get the new subdirectory name*/
  752.     testdir = OVERLAY('$$$',ffname,LENGTH(ffname) - 2)
  753.     call SysMkDir testdir
  754.     /* Expand the file*/
  755.     call unarj
  756.     /* Erase the Unarjed file*/
  757.     'ERASE 'ffname
  758.     /* Add the file to the list*/
  759.     testcnt = testcnt + 1
  760.     testfiledir.testcnt = testdir
  761.   end /* do */
  762.  
  763.   SrchFile = testfiledir'\*.zip'             /* look for .zip files       */
  764.   call SysFileTree SrchFile,'file','FO'
  765.   if file.0 > 0 then
  766.   do i = 1 to file.0
  767.     ffname = file.i
  768.     fname = FILESPEC("name",ffname)
  769.     /* Find path to the directory*/
  770.     fpath = FILESPEC("path",ffname)
  771.     /* Takeout last \ */
  772.     fpath = STRIP(fpath,'T','\')
  773.     /* Change to working drive*/
  774.     workdrive
  775.     /* Get to the correct subdirectory*/
  776.     'CD 'fpath
  777.     /* get the new subdirectory name*/
  778.     testdir = OVERLAY('$$$',ffname,LENGTH(ffname) - 2)
  779. say testdir
  780.     call SysMkDir testdir
  781.     /* Expand the file*/
  782.     signature = CHARIN(ffname,1,6)
  783.     select
  784.       when (substr(signature,1,5) = 'PK') then do  /* version 2.x zip file    */
  785.         temp = stream(ffname,'c','close')
  786.         call unzip2
  787.       end /* do */
  788.  
  789.       when (substr(signature,1,4) = 'PK') then do  /* version 1.x zip file    */
  790.         temp = stream(ffname,'c','close')
  791.         call unzip1
  792.       end /* do */
  793.     end /* select */
  794.     'ERASE 'ffname
  795.     /* Add the file to the list*/
  796.     testcnt = testcnt + 1
  797.     testfiledir.testcnt = testdir
  798.   end /* do */
  799.  
  800.   SrchFile = testfiledir'\*.arc'           /* look for .arc files         */
  801.   call SysFileTree SrchFile,'file','FO'
  802.   if file.0 > 0 then
  803.   do i = 1 to file.0
  804.     ffname = file.i
  805.     fname = FILESPEC("name",ffname)
  806.     /* Find path to the directory*/
  807.     fpath = FILESPEC("path",ffname)
  808.     /* Takeout last \ */
  809.     fpath = STRIP(fpath,'T','\')
  810.     /* Change to working drive*/
  811.     workdrive
  812.     /* Get to the correct subdirectory*/
  813.     'CD 'fpath
  814.     /* get the new subdirectory name*/
  815.     testdir = OVERLAY('$$$',ffname,LENGTH(ffname) - 2)
  816.     call SysMkDir testdir
  817.     /* Expand the file*/
  818.     call unarc
  819.     'ERASE 'ffname
  820.     /* Add the file to the list*/
  821.     testcnt = testcnt + 1
  822.     testfiledir.testcnt = testdir
  823.   end /* do */
  824.  
  825.  
  826.   SrchFile = testfiledir'\*.lzh'          /* look for .lzh files           */
  827.   call SysFileTree SrchFile,'file','FO'
  828.   if file.0 > 0 then do
  829.   do i = 1 to file.0
  830.     ffname = file.i
  831.     fname = FILESPEC("name",ffname)
  832.     /* Find path to the directory*/
  833.     fpath = FILESPEC("path",ffname)
  834.     /* Takeout last \ */
  835.     fpath = STRIP(fpath,'T','\')
  836.     /* Change to working drive*/
  837.     workdrive
  838.     /* Get to the correct subdirectory*/
  839.     'CD 'fpath
  840.     /* get the new subdirectory name*/
  841.     testdir = OVERLAY('$$$',ffname,LENGTH(ffname) - 2)
  842.     call SysMkDir testdir
  843.     /* Expand the file*/
  844.       call unlzh
  845.     end
  846.     'ERASE 'ffname
  847.     /* Add the file to the list*/
  848.     testcnt = testcnt + 1
  849.     testfiledir.testcnt = testdir
  850.   end /* do */
  851.  
  852. return
  853.  
  854. /* --- end checknested ---------- */
  855. tokens:
  856. cls=' '
  857. firstname=''
  858. blue='ü'
  859. lightblue='ë'
  860. cyan='â'
  861. lightcyan='ï'
  862. green='é'
  863. lightgreen='è'
  864. brown='å'
  865. yellow='Ä'
  866. grey='ç'
  867. gray='ç'
  868. white='Å'
  869. red='ä'
  870. lightred='î'
  871. magenta=''
  872. lightmagenta='ì'
  873. blink=''
  874. steady='ì'
  875. enter=''
  876. return
  877.  
  878.  
  879.  
  880. bbsmsg:     
  881.  
  882. do i = 7 to 25    /* clear msg */
  883.   msg.i = ''
  884. end /* do */
  885.  
  886.  msg.1=cls   
  887.  msg.2="      "blue"╔═════════════════════════════════════════════════╗"
  888.  msg.3="      "blue"║             "lightcyan"ViREXX "yellow"Scan Report                  "blue"║" 
  889.  msg.4="      "blue"╟─────────────────────────────────────────────────╢"
  890.  msg.5="      "blue"║  "lightcyan"ViREXX "yellow"Archive verifier/Virus Checker "white"[beta]   "blue"║"
  891.  msg.6="      "blue"╚═════════ "lightcyan"(c) Doug Cullen, 1992,1993 "blue"════════════╝"
  892.  
  893. select
  894.   when status = 'GOOD' | status = 'TEXT'  then do
  895.    file_out = file_ok
  896.    msg.8=green"  ╒═════════════════════════╤══════════════════════════════╕"
  897.    msg.9=green"  │"lightcyan" FileName: "yellow||CENTER(filename,14)||green"│ "lightcyan"Dated :"yellow||fildate"             "green"│"
  898.    msg.10=green"  ├─────────────────────────┼──────────────────────────────┤"
  899.    msg.11=green"  │ "lightcyan"FileSize:"yellow||CENTER(filesize,8)"bytes  "green"│ "lightcyan"Extracted Size: "yellow||CENTER(archsize,8)"bytes"green"│"
  900.    msg.12=green"  ├─────────────────────────┴──────────────────────────────┤"
  901.    msg.13=green"  │ "lightcyan"Archive contains: "yellow||CENTER(numfiles,3)" files                            "green"│"
  902.    msg.14=green"  ├─────────────────────────┬──────────────────────────────┤"
  903.    msg.15=green"  │ "lightcyan"Oldest file :"yellow||CENTER(olddate,8)"   "green"│ "lightcyan"Newest file :"yellow||CENTER(newdate,8)"        "green"│"
  904.    msg.16=green"  ╘═════════════════════════╧══════════════════════════════╛"
  905.    msg.18=lightcyan "Thanks for the upload, "firstname" Everything checks out OK"
  906.    msg.20=lightcyan "Full credit given for your upload"grey
  907.   end /* GOOD */
  908.  
  909.   when status = 'PASS' then do
  910.    file_out = file_ok
  911.    msg.8="     "lightcyan"ViREXX "yellow"has scanned your file:"white filename
  912.    msg.10="     "yellow"and it PASSED.   You have "white"FULL CREDIT "yellow"for the upload"
  913.    msg.12="     "yellow
  914.    msg.14="     "yellow"Thanks for Supporting "lightcyan bbsname
  915.    msg.16="     "yellow
  916.   end /* PASS */
  917.  
  918.   when status = 'BAD' then do
  919.    file_out = file_bad
  920.    msg.8="     "lightcyan"ViREXX "yellow"has scanned your file:"white filename       
  921.    msg.10="     "yellow"and was unable to extract any files from the archive"
  922.    msg.12="     "yellow"You may want to check your file for errors. (Please "lightred"DONT "yellow"use"
  923.    msg.14="     "yellow"PKZIP 1.93a)   You won't receive any credit for the file at"
  924.    msg.16="     "yellow"this time, but the file has been moved for SYSOP inspection"grey
  925.    msg.18=enter
  926.    end /* BAD */
  927.  
  928.   when status = 'INFECTED' then do
  929.    file_out = file_bad
  930.    msg.8="     "blink red"WARNING "white"WARNING "red"WARNING "white"WARNING - "steady yellow"Your file :"white filename
  931.    msg.10="     "yellow"has caused a "red"VIRUS "yellow"warning from our system.  You won't"
  932.    msg.12="     "yellow"receive any credit for you upload at this time, but the"
  933.    msg.14="     "yellow"file has been moved for SYSOP inspection."grey
  934.    msg.16=""
  935.    msg.18=enter
  936.    end /* infected */
  937.  
  938.   when status = 'UNKNOWN' then do
  939.    file_out = file_bad
  940.    msg.8="     "lightcyan"ViREXX "yellow"was unsure what to do with your file:"white filename
  941.    msg.10="     "yellow"since it was not one of the kind we accept.  Please"
  942.    msg.12="     "yellow"limit your uploads to .ZIP, .ARC, .ARJ or .LZH files."
  943.    msg.14="     "yellow"You won't recieve any credit for your upload at this" 
  944.    msg.16="     "yellow"time, but the file has been moved for SYSOP inspection"grey
  945.    msg.18=enter
  946.   end /* UNKNOWN */
  947.  
  948.   when status = 'EXE' then do
  949.    file_out = file_bad
  950.    msg.8="      "lightcyan"Virexx "yellow"has moved your file to a holding area for the"
  951.    msg.10="      "yellow"Sysop to inspect.   This action has been taken to help"
  952.    msg.12="      "yellow"prevent the spread of "lightred"viruses, bombs "yellow"and "lightred"trojans "yellow"that"
  953.    msg.14="      "yellow"are frequently spread around in executable files. "
  954.    msg.16="      "white"Thanks for your understanding."grey
  955.    msg.18=enter
  956.   end /* EXE */
  957.  
  958.   when status = 'NOEXT' then do
  959.    file_out = file_bad
  960.    msg.8="     "lightcyan"ViREXX "yellow"was unsure of how to handle your file: "file
  961.    msg.10="     "yellow"since it had no file extension.  Please limit your"
  962.    msg.12="     "yellow"uploads to "lightgreen".ZIP, .ARC, .ARJ "yellow"or "lightgreen".LZH "yellow"files.  You won't"
  963.    msg.14="     "yellow"recieve any credit for your upload at this time, but" 
  964.    msg.16="     "yellow"the file has been moved for "white"SYSOP "yellow"inspection"grey
  965.    msg.18=enter
  966.   end /* NOEXT */
  967.  
  968.   when status = 'OLD' then do
  969.    file_out = file_bad
  970.    msg.8="     "lightcyan"ViREXX "yellow"has found that some of the files in "filename
  971.    msg.10="     "yellow"are older than we normally accept.  Sorry, but you"
  972.    msg.12="     "yellow"won't receive credit for your upload.  The file has"
  973.    msg.14="     "yellow"been moved for SYSOP inspection"
  974.    msg.18="     "grey
  975.    msg.20=enter
  976.   end /* OLD */
  977.  
  978.   when status = 'REJECT' then do
  979.    file_out = file_bad
  980.    msg.8="     "yellow"Sorry "fname" but the file you uploaded:"lightcyan filename
  981.    msg.10="     "yellow"is not accepted here at"lightmagenta bbsname
  982.    msg.12=""
  983.    msg.14="     "yellow"Please refrain from uploading similar files in the"
  984.    msg.16="     "yellow"future."
  985.    msg.18="     "lightred"Failure to heed this warning may result in Sysop action"
  986.    msg.20=grey enter
  987.   end /* REJECT */
  988.  
  989.   when status = 'INCOMPLETE' then do
  990.    file_out = file_ok
  991.    msg.8="     "yellow"The Virus check did not Complete"
  992.    msg.10="     "yellow"Please leave a message at "lightmagenta bbsname
  993.    msg.12=""
  994.    msg.14="     "yellow"Ask the sysop to check the return code in the"
  995.    msg.16="     "yellow"log file and report the problem."
  996.    msg.18="     "lightred"If a 1042 error then a program was not found in Path"
  997.    msg.20=grey enter
  998.   end /* REJECT */
  999.  
  1000.   otherwise
  1001.    nop
  1002. end /* select */
  1003.  
  1004.   'ERASE 'file_out
  1005.   do i = 1 to 20
  1006.     file = LINEOUT(file_out,msg.i)
  1007.   end /* do */
  1008.   file = LINEOUT(file_out)
  1009.  
  1010. return
  1011.  
  1012. filestats:
  1013. numfiles=0
  1014. oldmonth = ''
  1015. oldyear  = ''
  1016. newyear = ''
  1017. newmonth= ''
  1018. numonth = '010203040506070809101112'
  1019. month = 'JanFebMarAprMayJunJulAugSepOctNovDec'
  1020. SrchFile = fullname
  1021. filesize = stream(SrchFile,'c','query size')
  1022. fdate=stream(SrchFile,'c','query datetime')
  1023. parse value fdate with fm'-'fd'-'fy  hours
  1024. if fm <> '' then do
  1025.   findmth = (POS(fm,numonth) + 1) / 2
  1026.   if findmth >= 1 then
  1027.     fildate = fd'-'SUBSTR(month, 3 * findmth + 1, 3)'-'fy
  1028.   else
  1029.     fildate = fd'-xxx-'fy
  1030.   SrchFile = testfiledir'\*.*'
  1031.   call SysFileTree SrchFile,'file','FO'
  1032.   do i = 1 to file.0
  1033.     fsize=stream(file.i,'c','query size')
  1034.     archsize=archsize+fsize
  1035.     numfiles=numfiles+1
  1036.   end /* do */
  1037.  
  1038.   oldyear  = SUBSTR(oldestfile,1,2)
  1039.   newyear  = SUBSTR(newestfile,1,2)
  1040.   oldmonth = '   '
  1041.   newmonth = '   '
  1042.   findmth = (POS(SUBSTR(oldestfile,3,2),numonth) + 1) / 2 * 3 - 2
  1043.   if findmth >= 1 then
  1044.     oldmonth = SUBSTR(month, findmth, 3)
  1045.   findmth = (POS(SUBSTR(newestfile,3,2),numonth) + 1) / 2 * 3 - 2
  1046.   if findmth >= 1 then
  1047.     newmonth = SUBSTR(month, findmth, 3)
  1048.   olddate=oldmonth'-'oldyear
  1049.   newdate=newmonth'-'newyear
  1050. end
  1051. return
  1052.  
  1053. databaseout:
  1054. databaseentry=filename','fildate','uldate','filesize','archsize','numfiles','olddate','newdate','username
  1055. file = LINEOUT(database,databaseentry)
  1056. file = LINEOUT(database)
  1057. return
  1058.  
  1059. USAGE:
  1060. say ' '
  1061. say ' ViREXX.CMD - Maximus File Integrety Tester written in REXX '
  1062. say ' '
  1063. say ' USAGE: Virexx d:\path\ filename .ext d:\max\misc '
  1064. say ' '
  1065. say ' d:\path\   = path to file to be checked INCLUDING trailing \'
  1066. say ' '
  1067. say ' filename   = the name of the file with no path or extension'
  1068. say ' '
  1069. say ' .ext       = the file extension including the . '
  1070. say ' '
  1071. say 'd:\max\misc =  path to MAXIMUS misc dir withOUT trailing \'
  1072. say ' '
  1073. say ' This is the form in which max passes the parameters '
  1074. say ' '
  1075. say '(1 - 9)     =  Node Number of Line'
  1076. say ' '
  1077. signal CLEANUP
  1078. return
  1079.