home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / awget167.zip / awgetd.cmd < prev    next >
OS/2 REXX Batch file  |  2001-06-11  |  53KB  |  1,807 lines

  1. /* Auto WGet Daemon
  2.  *
  3.  * Great idea and first release (C) 1998 Steve Trubachev
  4.  * Final release (C) 1998-2001 Dmitry A.Steklenev
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  *
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  *
  18.  * 3. All advertising materials mentioning features or use of this
  19.  *    software must display the following acknowledgment:
  20.  *    "This product includes software developed by Dmitry A.Steklenev".
  21.  *
  22.  * 4. Redistributions of any form whatsoever must retain the following
  23.  *    acknowledgment:
  24.  *    "This product includes software developed by Dmitry A.Steklenev".
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS "AS IS"
  27.  * AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  29.  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  30.  * AUTHOR OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  31.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  32.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  33.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  35.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  37.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38.  *
  39.  * $Id: awgetd.cms,v 1.67 2001/05/11 09:45:01 glass Exp $
  40.  */
  41.  
  42. globals = "cfg. local. msg. sys. color. dir. jobs. job. plugins."
  43.  
  44. if translate( value( "AWGET_TRACE",, "OS2ENVIRONMENT" )) == "YES" then do
  45.    call  value "AWGET_TRACE", "", "OS2ENVIRONMENT"
  46.    trace intermediate
  47.    trace results
  48. end
  49.  
  50. call AwInit
  51.  
  52. cls
  53. say color.bold  || "Auto WGet Daemon " || color.usual || "Version 1.6.7"
  54. say color.usual || "Great idea and first release (C) 1998 Steve Trubachev"
  55. say color.usual || "Final release (C) 1998-2001 Dmitry A.Steklenev"
  56. say color.usual || ""
  57.  
  58. /* wait while 'TCP/IP Startup' running */
  59. '@inetwait 30000'
  60.  
  61. call MsgRead "awgmsg"
  62. call CfgRead
  63. cfg.download = CfgCheckDownload( cfg.download )
  64. call CfgShow ; say
  65. call DirRead
  66. call DirShow ; say
  67. call PlgRead "global"
  68.  
  69. sys_running  = cfg.home'\'sys.running
  70. sys_killing  = cfg.home'\'sys.killing
  71. sys_pushing  = cfg.home'\'sys.pushing
  72. jobs.0       = 0
  73.  
  74. /* activate plugins before opening any file */
  75. call PlgStart
  76.  
  77. /* check up absence of the second copy of a demon */
  78. 'del "'sys_running'" "'sys_killing'" /F 1>nul 2>nul'
  79.  
  80. if stream( sys_running, 'c', 'query exist' ) \= "" then do
  81.    call LogPut err, msg.already_running
  82.    exit 1
  83. end
  84. call lineout sys_running, "I'm alive!"
  85.  
  86. /* create termination queue */
  87. rc = AwTQCreate( sys.tqueue, "sys.tqueue_handle" )
  88.  
  89. if rc \= 0 then do
  90.    call LogPut err, msg.error_in "AwTQCreate, rc="rc,, SysGetMessage(rc)
  91.    exit 1
  92. end
  93.  
  94. signal on syntax
  95. signal on halt
  96.  
  97. /* update WPS objects */
  98. call AwUpdateWPS
  99. /* prune log files */
  100. call AwPrune
  101.  
  102. /* recover interrupted downloads */
  103. rc = SysFileTree( dir.running"\*", 'running', 'FO'  )
  104. do i = 1 to running.0
  105.    call AwRecover running.i
  106. end
  107.  
  108. 'del "'dir.jobs'\*.job" /F 1>nul 2>nul'
  109. drop running.
  110.  
  111. call PlgBroadcast "INIT "cfg.home
  112.  
  113. /*------------------------------------------------------------------
  114.  * Sheduling of downloading
  115.  *------------------------------------------------------------------*/
  116. do while stream( sys_killing, 'c', 'query exist' ) == ""
  117.  
  118.   /* check up changes of the configuration file */
  119.   if CfgCheckChanges() then do
  120.      call AwUpdateWPS
  121.      call PlgBroadcast "CONF "sys.config_file
  122.   end
  123.  
  124.   if PlgBroadcast( "SCAN "dir.todo ) then do
  125.  
  126.      /* scan DeskTop's objects */
  127.      if cfg.use_desktop then do
  128.         rc = SysFileTree( dir.desktop"\*" ,'desktop','FO' )
  129.         do i = 1 to desktop.0
  130.           if IsURLFile( desktop.i ) then
  131.              call AwRecover desktop.i
  132.         end
  133.      end
  134.  
  135.      /* build objects todo list */
  136.      call AwBuildToDo
  137.  
  138.      /* check up internet connection */
  139.      if todo.0 > 0 | jobs.0 > 0 then
  140.         call pppCheck
  141.  
  142.      /* scheduling... */
  143.      do scheduled = 1 to todo.0,
  144.         while sys.connected & jobs.0 < cfg.downloads_simultaneously
  145.  
  146.         if \IsURLFile(todo.scheduled) then do
  147.            call LogPut err, msg.bad_url, todo.scheduled
  148.            call AwFailed todo.scheduled, 1
  149.            iterate
  150.         end
  151.  
  152.         call AwSchedule todo.scheduled
  153.      end
  154.   end
  155.  
  156.   /* analyzing termination queue */
  157.   do cfg.scan_interval,
  158.      while stream( sys_killing, 'c', 'query exist' ) == ""
  159.  
  160.      rc = AwTQRead( sys.tqueue_handle, "term" )
  161.      if rc \= 0 then
  162.         call LogPut err, msg.error_in "AwTQRead, rc="rc,, SysGetMessage(rc)
  163.  
  164.      have_errors = 0
  165.      do i = 1 to term.0
  166.         call AwComplete term.i.ses_id, term.i.ses_rc
  167.         have_errors = have_errors | term.i.ses_rc \= 0
  168.      end
  169.  
  170.      /* check up running objects */
  171.      if jobs.0 > 0 then call AwCheckRunning
  172.  
  173.      call SysSleep 1
  174.      sys.active_time = sys.active_time + 1
  175.  
  176.      /* Fast restart after succesfull download */
  177.      if term.0 > 0 & scheduled <= todo.0 & \have_errors then
  178.         leave
  179.  
  180.      /* Fast restart on demand */
  181.      if stream( sys_pushing, 'c', 'query exist' ) \= "" then do
  182.         'del "'sys_pushing'" /F 1>nul 2>nul'
  183.         if rc == 0 then leave
  184.      end
  185.   end
  186.  
  187.   drop todo.
  188.  
  189.   if jobs.0 == 0 & sys.active_time > 10800 then do /* 3 hours */
  190.      call AwPrune
  191.      sys.active_time = 0
  192.   end
  193. end
  194.  
  195. halt:
  196.  
  197.   /* close termination queue */
  198.   rc = AwTQClose( sys.tqueue_handle )
  199.   if rc \= 0 then
  200.      call LogPut err, msg.error_in "AwTQClose, rc="rc,, SysGetMessage(rc)
  201.  
  202.   rc = stream( sys_running, 'c', 'close' )
  203.   'del 'sys_running' /F 1>nul 2>nul'
  204.   exit 0
  205.  
  206. syntax:
  207.  
  208.   parse source . . program .
  209.  
  210.   if sourceline() >= SIGL then
  211.      sourceline = strip(sourceline(SIGL))
  212.   else
  213.      sourceline = ""
  214.  
  215.   call LogPut err, condition('C') rc "running" filespec( "name", program )", line " ||,
  216.                    SIGL errortext(rc) condition('D'),, sourceline
  217.   exit 256
  218.  
  219. /*------------------------------------------------------------------
  220.  * Update WPS objects
  221.  *------------------------------------------------------------------*/
  222. AwUpdateWPS: procedure expose (globals)
  223.  
  224.   if \SysSetObjectData( "<AWG2_EVTLOG>", "PARAMETERS="cfg.log_file  ) then
  225.      call LogPut err, msg.error_in "SysSetObjectData"
  226.   if \SysSetObjectData( "<AWG2_ERRLOG>", "PARAMETERS="cfg.error_log ) then
  227.      call LogPut err, msg.error_in "SysSetObjectData"
  228.  
  229.   tools = AwGetObjectPath( "<AWG2_TOOLS>" )
  230.   if tools \= "" &,
  231.      stream( tools"\awget.cfg", "c", "query exists" ) == "" then do
  232.  
  233.      call CfgCreateLocal tools
  234.      call SysSetObjectData tools"\awget.cfg",,
  235.           "ICONFILE="cfg.home"\Icons\awgedit.ico;" ||,
  236.           "TEMPLATE=YES;"
  237.   end
  238.  
  239. return
  240.  
  241. /*------------------------------------------------------------------
  242.  * Builds todo List
  243.  *------------------------------------------------------------------*/
  244. AwBuildToDo: procedure expose (globals) todo.
  245.  
  246.    rc = SysFileTree( dir.todo"\*", 'todo', 'FTS' )
  247.  
  248.    /* Sort list by file date */
  249.    do i = todo.0 to 1 by -1
  250.       do j = 2 to i
  251.          m = j - 1
  252.          if todo.m > todo.j then
  253.             todo.j = value( "todo.m", todo.j )
  254.       end
  255.    end
  256.  
  257.    /* Remove file's attributes and reserved file names */
  258.    j = 0; do i = 1 to todo.0
  259.       parse value todo.i with . . . object
  260.       name = translate( filespec( "name", object ))
  261.       if name \= "AWGET.CFG" then do
  262.          j = j + 1
  263.          todo.j = strip(object)
  264.       end
  265.    end
  266.    todo.0 = j
  267. return
  268.  
  269. /*------------------------------------------------------------------
  270.  * Check up running objects
  271.  *------------------------------------------------------------------*/
  272. AwCheckRunning: procedure expose (globals)
  273.  
  274.    do i = 1 to jobs.0
  275.       if stream( jobs.i.object, "c", "query exist" ) == "" then do
  276.          if JobRead( jobs.i.file ) then do
  277.             job.object = ""
  278.             call JobSave jobs.i.file
  279.          end
  280.          rc = AwStopSession( jobs.i.sid )
  281.          if rc \= 0 then
  282.             call LogPut err, msg.error_in "AwStopSession, rc="rc,, SysGetMessage(rc)
  283.          iterate
  284.       end
  285.       if \sys.connected then do
  286.          rc = AwStopSession( jobs.i.sid )
  287.          if rc \= 0 then
  288.             call LogPut err, msg.error_in "AwStopSession, rc="rc,, SysGetMessage(rc)
  289.       end
  290.    end
  291. return
  292.  
  293. /*------------------------------------------------------------------
  294.  * Recover interrupted file
  295.  *------------------------------------------------------------------*/
  296. AwRecover: procedure expose (globals)
  297.  
  298.   parse arg object, touch
  299.   object_name = filespec( "name", object )
  300.   object_home = WpsGetEA( object, "AWG_FOLDER" )
  301.  
  302.   if object_home == "" | \DirExist(object_home) then do
  303.      object_home = dir.todo
  304.      call WpsPutEA object, "AWG_FOLDER", object_home
  305.   end
  306.  
  307.   if WpsMove( object, object_home"\"object_name, touch ) \= "" then
  308.      call WpsRefresh object_home
  309. return
  310.  
  311. /*------------------------------------------------------------------
  312.  * Move file to "Failed" or delete it
  313.  *------------------------------------------------------------------*/
  314. AwFailed: procedure expose (globals)
  315.  
  316.   parse arg object, keep
  317.   object_name = filespec( "name" , object )
  318.  
  319.   if keep == 0 then
  320.      call WpsDestroy object
  321.   else do
  322.      call WpsPutEA object, "AWG_ATTEMPTS", ""
  323.      call WpsMove object, dir.failed"\"object_name
  324.      call WpsRefresh dir.failed
  325.   end
  326. return
  327.  
  328. /*------------------------------------------------------------------
  329.  * Move file to "Done" or delete it
  330.  *------------------------------------------------------------------*/
  331. AwDone: procedure expose (globals)
  332.  
  333.   parse arg object, keep
  334.  
  335.   object_name = filespec( "name" , object )
  336.  
  337.   if keep == 0 then
  338.      call WpsDestroy object
  339.   else do
  340.      call WpsPutEA object, "AWG_ATTEMPTS", ""
  341.      call WpsMove object, dir.done"\"object_name
  342.      call WpsRefresh dir.done
  343.   end
  344. return
  345.  
  346. /*------------------------------------------------------------------
  347.  * Schedule file
  348.  *------------------------------------------------------------------*/
  349. AwSchedule: procedure expose (globals)
  350.  
  351.   parse arg object
  352.  
  353.   object_home = DirPath( object )
  354.   call CfgReadLocal object_home
  355.   schedule_it = (local.schedule == "")
  356.  
  357.   if \schedule_it then do
  358.      schedule_plan = local.schedule
  359.      curtime       = substr( time(), 1, 2 ) || substr( time(), 4, 2 )
  360.  
  361.      do while schedule_plan \= ""
  362.         parse value schedule_plan with hb":"mb"-"he":"me","schedule_plan
  363.         begtime = strip(hb)||strip(mb)
  364.         endtime = strip(he)||strip(me)
  365.  
  366.         if ( curtime >= begtime & curtime <= endtime ) |,
  367.            ( curtime >= begtime & begtime >= endtime ) |,
  368.            ( curtime <= endtime & begtime >= endtime ) then do
  369.  
  370.            schedule_it = 1
  371.            leave
  372.         end
  373.      end
  374.   end
  375.  
  376.   if schedule_it then do
  377.      call WpsPutEA object, "AWG_FOLDER", object_home
  378.      run = WpsMove( object, dir.running"\"filespec( "name", object ))
  379.  
  380.      if run \= "" then do
  381.         call WpsRefresh dir.running
  382.         call AwDownload run
  383.      end
  384.   end
  385. return
  386.  
  387. /*------------------------------------------------------------------
  388.  * Starts download session
  389.  *------------------------------------------------------------------*/
  390. AwDownload: procedure expose (globals)
  391.  
  392.   parse arg job.object
  393.  
  394.   job.url                  = GetURLFromFile(job.object)
  395.   job.download             = local.download
  396.   job.downloads_utility    = local.downloads_utility
  397.   job.downloads_parameters = local.downloads_parameters
  398.   job.downloads_rc         = 0
  399.   job.downloads_info       = ""
  400.   job.message_done         = local.message_done
  401.   job.message_error        = local.message_error
  402.  
  403.   new_job = JobSave()
  404.  
  405.   if PlgBroadcast( "SEXE "new_job ) then do
  406.  
  407.      rc = AwStartSession( ShortenURL( job.url, 57 ), 'cmd.exe',,
  408.                           '/c awgexec.cmd 'new_job, "bh", sys.tqueue,,
  409.                           "ses_id" )
  410.      if rc \= 0 then
  411.         call LogPut err, msg.error_in "AwStartSession, rc="rc,,
  412.                                                        SysGetMessage(rc)
  413.      end
  414.   else
  415.      rc = 1
  416.  
  417.   if rc \= 0 then do
  418.      call AwRecover job.object, "touch"
  419.     '@del "'new_job'" /F'
  420.      end
  421.   else do
  422.      i = jobs.0 + 1
  423.      jobs.i.file   = new_job
  424.      jobs.i.object = job.object
  425.      jobs.i.sid    = ses_id
  426.      jobs.0 = i
  427.  
  428.      attempts = WpsGetEA( job.object, "AWG_ATTEMPTS" )
  429.      if attempts \= "" then
  430.         call LogPut msg, msg.download_start" (#"attempts+1")", DecodeURL(job.url)
  431.      else
  432.         call LogPut msg, msg.download_start, DecodeURL(job.url)
  433.  
  434.      if local.messages then
  435.         call beep 4000, 50
  436.   end
  437. return
  438.  
  439. /*------------------------------------------------------------------
  440.  * Completes download session
  441.  *------------------------------------------------------------------*/
  442. AwComplete: procedure expose (globals)
  443.  
  444.   parse arg ses_id, ses_rc
  445.  
  446.   /* find job in jobs list */
  447.   do pos = 1 to jobs.0 while jobs.pos.sid \= ses_id ; end
  448.   if pos > jobs.0 then do
  449.      call LogPut err, msg.unknown_sid",sid="rc
  450.      return
  451.   end
  452.  
  453.   call PlgBroadcast "SEND "jobs.pos.file
  454.  
  455.   /* remove job from jobs list */
  456.   job_rc = JobRead( jobs.pos.file )
  457.   '@del "'jobs.pos.file'" /F'
  458.  
  459.   if pos <= jobs.0 then do
  460.      do i = pos to jobs.0
  461.         j = i + 1
  462.         jobs.i.sid    = jobs.j.sid
  463.         jobs.i.object = jobs.j.object
  464.         jobs.i.file   = jobs.j.file
  465.      end
  466.  
  467.      drop jobs.pos
  468.      jobs.0 = jobs.0 - 1
  469.   end
  470.  
  471.   if \job_rc then return
  472.  
  473.   /* read local configuration file */
  474.   object_home = WpsGetEA( job.object, "AWG_FOLDER" )
  475.  
  476.   if object_home == "" | \DirExist(object_home) then
  477.      object_home = dir.todo
  478.  
  479.   call CfgReadLocal object_home
  480.  
  481.   /* if download completed succesfully */
  482.   if ses_rc == 0 then do
  483.      call AwDone job.object, local.keep_done_url
  484.      call LogPut msg, msg.download_done, DecodeURL(job.url)
  485.      end
  486.   /* if download interrupted */
  487.   else do
  488.      attempts = WpsGetEA( job.object, "AWG_ATTEMPTS" )
  489.  
  490.      if attempts == "" then
  491.         attempts = 0
  492.      if ses_rc \= 255 then
  493.         attempts = attempts + 1
  494.  
  495.      if ses_rc == 256 & job.downloads_info == "" then
  496.         job.downloads_info = "Syntax error in AWGet module. See errors log."
  497.  
  498.      /* fatal conditions */
  499.      if attempts >= local.downloads_attempts | ses_rc = 256 then do
  500.         call AwFailed job.object, local.keep_failed_url
  501.         call LogPut err, msg.download_error, DecodeURL(job.url),,
  502.                                              job.downloads_info
  503.         end
  504.      else do
  505.      /* go to next attempt */
  506.         if job.object \= "" then do
  507.            call WpsPutEA  job.object, "AWG_ATTEMPTS", attempts
  508.            if ses_rc \= 255 then
  509.               call AwRecover job.object, "touch"
  510.            else
  511.               call AwRecover job.object
  512.         end
  513.         call LogPut msg, msg.download_stop, DecodeURL(job.url),,
  514.                                             job.downloads_info
  515.         return
  516.      end
  517.   end
  518.  
  519.   if local.messages then do
  520.      if ses_rc == 0 then do
  521.         message = msg.download_done
  522.         command = job.message_done
  523.         end
  524.      else do
  525.         message = msg.download_error
  526.         command = job.message_error
  527.      end
  528.  
  529.      command = replace( command, "%m", message )
  530.      command = replace( command, "%u", DecodeURL(job.url))
  531.      command = replace( command, "%r", job.downloads_rc )
  532.      command = replace( command, "%i", job.downloads_info )
  533.      command = replace( command, "%d", job.download )
  534.      command = replace( command, "%p", translate(job.download, "/", "\" ))
  535.      command = replace( command, "%f", GetFileFromURL(job.url))
  536.  
  537.      '@'command
  538.   end
  539.  
  540. return
  541.  
  542. /*------------------------------------------------------------------
  543.  * Prunes log files
  544.  *------------------------------------------------------------------*/
  545. AwPrune: procedure expose (globals)
  546.  
  547.   logs.1 = cfg.log_file
  548.   logs.2 = cfg.error_log
  549.   logs.0 = 2
  550.   pruned = 0
  551.   today  = date("B")
  552.  
  553.   do i = 1 to logs.0
  554.      if stream( logs.i, "c", sys.open_read ) \= "READY:" then
  555.         iterate
  556.  
  557.      do prune = 0 while lines(logs.i) > 0
  558.         entry = linein( logs.i )
  559.         if today - DateBase(entry) <= cfg.log_keep then do
  560.            entrys.1 = entry
  561.            entrys.0 = 1
  562.            leave
  563.         end
  564.      end
  565.  
  566.      if prune > 0 then do
  567.         if pruned == 0 then
  568.            say color.info || "*** "msg.prune_start || color.usual
  569.  
  570.         do keep = 2 while lines(logs.i) > 0
  571.            entrys.keep = linein(logs.i)
  572.         end
  573.         entrys.0 = keep - 1
  574.  
  575.         call stream logs.i, "c", "close"
  576.  
  577.         if stream( logs.i, "c", "query exists" ) \= "" then
  578.            "@del " logs.i
  579.  
  580.         if stream( logs.i, "c", sys.open_write ) == "READY:" then do
  581.            do keep = 1 to entrys.0
  582.               call lineout logs.i, entrys.keep
  583.            end
  584.            call stream logs.i, "c", "close"
  585.         end
  586.         pruned = pruned + prune
  587.         end
  588.      else
  589.         call stream logs.i, "c", "close"
  590.   end
  591.  
  592.   if pruned > 0 then
  593.      call LogPut inf, replace(msg.prune_done,"%u",pruned)
  594. return
  595.  
  596. /* $Id: init.cms,v 1.26 2001/05/11 09:45:01 glass Exp $ */
  597.  
  598. /*------------------------------------------------------------------
  599.  * Initialization
  600.  *------------------------------------------------------------------*/
  601. AwInit: procedure expose (globals)
  602.  
  603.   if RxFuncQuery('SysLoadFuncs') then do
  604.      call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  605.      call SysLoadFuncs
  606.   end
  607.  
  608.   parse source os what program tail
  609.   lpath = substr( program, 1, lastpos( "\", program ))
  610.   dll   = lpath || "awget.dll"
  611.  
  612.   if RxFuncQuery('AwLoadFuncs') then do
  613.      call RxFuncAdd  'AwLoadFuncs', dll, 'AwLoadFuncs'
  614.      call AwLoadFuncs
  615.   end
  616.  
  617.   '@echo off'
  618.  
  619.   sys.config_file = value( "ETC",, "OS2ENVIRONMENT" )"\awget.cfg"
  620.   sys.connected   = 1
  621.   sys.active_time = 0
  622.  
  623.   /* enable ANSI extended screen and keyboard control */
  624.   '@ansi on > nul'
  625.  
  626.   color.brown   = "1B"x"[0;33m"
  627.   color.red     = "1B"x"[1;31m"
  628.   color.green   = "1B"x"[1;32m"
  629.   color.yellow  = "1B"x"[1;33m"
  630.   color.blue    = "1B"x"[1;34m"
  631.   color.magenta = "1B"x"[1;35m"
  632.   color.cyan    = "1B"x"[1;36m"
  633.   color.white   = "1B"x"[1;37m"
  634.   color.gray    = "1B"x"[0m"
  635.  
  636.   color.usual   = color.gray
  637.   color.bold    = color.white
  638.   color.error   = color.red
  639.   color.info    = color.green
  640.   color.debug   = color.brown
  641.  
  642.   /* known download utilites */
  643.  
  644.   sys.utils.0      = 2
  645.   sys.utils.1.prog = wget.exe
  646.   sys.utils.1.name = "GNU WGet"
  647.   sys.utils.1.parm = '-c -t 10 -w 30 -P "%p" "%u"'
  648.   sys.utils.2.prog = curl.exe
  649.   sys.utils.2.name = "cURL"
  650.   sys.utils.2.parm = '-y 300 -Y 1 -v -C - -o "%p/%f" "%u"'
  651.  
  652.   sys.utils.default.prog = sys.utils.1.prog
  653.   sys.utils.default.name = sys.utils.1.name
  654.   sys.utils.default.parm = sys.utils.1.parm
  655.  
  656.   /* service semaphores */
  657.  
  658.   sys.running = "$live$"
  659.   sys.killing = "$stop$"
  660.   sys.pushing = "$push$"
  661.   sys.tqueue  = "$term$"
  662.  
  663.   /* stream's open modes */
  664.  
  665.   parse version version .
  666.   if version = "OBJREXX" then do
  667.      sys.open_read  = "OPEN READ  SHAREREAD"
  668.      sys.open_write = "OPEN WRITE SHAREREAD"
  669.      end
  670.   else do
  671.      sys.open_read  = "OPEN READ"
  672.      sys.open_write = "OPEN WRITE"
  673.   end
  674. return
  675.  
  676. /* $Id: nls.cms,v 1.13 2001/05/11 08:54:34 glass Exp $ */
  677.  
  678. /*------------------------------------------------------------------
  679.  * Read messages
  680.  *------------------------------------------------------------------*/
  681. MsgRead: procedure expose (globals)
  682.  
  683.   parse arg msgfile
  684.   parse source OS2 what msgpath
  685.  
  686.   msgfile = filespec( "disk", msgpath ) ||,
  687.             filespec( "path", msgpath ) || "NLS\" || msgfile
  688.  
  689.   country = MsgCountryID()
  690.  
  691.   if stream( msgfile"."country, "c", "query exists" ) == "" then
  692.      country = "001"
  693.  
  694.   msgfile = msgfile"."country
  695.   rc = stream( msgfile, "C", sys.open_read )
  696.  
  697.   if rc \= "READY:" then do
  698.      say  color.error || "■■■ Error on open NLS file: "msgfile
  699.      exit 1
  700.   end
  701.  
  702.   do while lines(msgfile) > 0
  703.      line = strip(linein(msgfile))
  704.  
  705.      do while right(line,1) == "\"
  706.         line = left( line, length(line)-1 )
  707.         line = line || strip(linein(msgfile))
  708.      end
  709.  
  710.      if line \= "" & left(line,1) \= "#" then do
  711.         parse value line with id "=" msg
  712.  
  713.         id  = strip(id )
  714.         msg = strip(msg)
  715.  
  716.         i = pos( "\n", msg )
  717.         do while i > 0
  718.            msg = substr( msg, 1, i-1 ) || '0D0A'x || substr( msg, i+2 )
  719.            i = pos( "\n", msg )
  720.         end
  721.  
  722.         msg.id = msg
  723.      end
  724.   end
  725.  
  726.   rc = stream( msgfile, "C", "CLOSE" )
  727. return
  728.  
  729. /*------------------------------------------------------------------
  730.  * Returns Country Identifier
  731.  *------------------------------------------------------------------*/
  732. MsgCountryID: procedure expose (globals)
  733.  
  734.   country = strip( SysIni( "BOTH", "PM_National", "iCountry" ),, '0'x )
  735.  
  736.   if country == "ERROR:" then
  737.      country =  "001"
  738.   else
  739.      country =  right( country, 3, "0" )
  740.  
  741. return country
  742.  
  743.  
  744. /* $Id: config.cms,v 1.29 2001/05/11 08:54:34 glass Exp $ */
  745.  
  746. /*------------------------------------------------------------------
  747.  * Returns Confguration Keys
  748.  *------------------------------------------------------------------*/
  749. CfgKeys: procedure expose (globals)
  750.  
  751. return "HOME "                      ||,
  752.        "DOWNLOAD "                  ||,
  753.        "DOWNLOADS_SIMULTANEOUSLY "  ||,
  754.        "DOWNLOADS_ATTEMPTS "        ||,
  755.        "DOWNLOADS_UTILITY "         ||,
  756.        "DOWNLOADS_PARAMETERS "      ||,
  757.        "SCAN_INTERVAL "             ||,
  758.        "LOG_FILE "                  ||,
  759.        "ERROR_LOG "                 ||,
  760.        "LOG_KEEP "                  ||,
  761.        "MESSAGE_DONE "              ||,
  762.        "MESSAGE_ERROR "             ||,
  763.        "MESSAGES "                  ||,
  764.        "CHECK_CONNECTION "          ||,
  765.        "USE_DESKTOP "               ||,
  766.        "KEEP_FAILED_URL "           ||,
  767.        "KEEP_DONE_URL "
  768.  
  769. /*------------------------------------------------------------------
  770.  * Get Configuration
  771.  *------------------------------------------------------------------*/
  772. CfgRead: procedure expose (globals)
  773.  
  774.   cfg.home                     = "."
  775.   cfg.download                 = "."
  776.   cfg.downloads_simultaneously = 3
  777.   cfg.downloads_attempts       = 15
  778.   cfg.downloads_utility        = sys.utils.default.prog
  779.   cfg.downloads_parameters     = sys.utils.default.parm
  780.   cfg.scan_interval            = 30
  781.   cfg.log_file                 = "nul"
  782.   cfg.error_log                = "nul"
  783.   cfg.log_keep                 = 15
  784.   cfg.message_done             = 'start /n pmpopup2.exe "%m:~~%u" "Auto WGet Daemon" /BELL /B1:"OK" /T:900 /F:"8.Helv"'
  785.   cfg.message_error            = 'start /n pmpopup2.exe "%m:~~%u~%i" "Auto WGet Daemon" /BELL /B1:"OK" /T:900 /F:"8.Helv"'
  786.   cfg.messages                 = 1
  787.   cfg.check_connection         = 0
  788.   cfg.use_desktop              = 0
  789.   cfg.keep_failed_url          = 1
  790.   cfg.keep_done_url            = 0
  791.  
  792.   rc = stream( sys.config_file, "C", sys.open_read )
  793.  
  794.   do while lines(sys.config_file) > 0
  795.      parse value linein(sys.config_file) with command "=" argument
  796.  
  797.      command  = translate(strip(command))
  798.      argument = strip(argument)
  799.  
  800.      select
  801.         when command == "HOME",
  802.            | command == "DOWNLOAD",
  803.            | command == "DOWNLOADS_SIMULTANEOUSLY",
  804.            | command == "DOWNLOADS_ATTEMPTS",
  805.            | command == "DOWNLOADS_UTILITY",
  806.            | command == "DOWNLOADS_PARAMETERS",
  807.            | command == "SCAN_INTERVAL",
  808.            | command == "LOG_FILE",
  809.            | command == "ERROR_LOG",
  810.            | command == "LOG_KEEP",
  811.            | command == "MESSAGE_DONE",
  812.            | command == "MESSAGE_ERROR" then
  813.  
  814.              cfg.command = argument
  815.  
  816.         when command == "MESSAGES",
  817.            | command == "CHECK_CONNECTION",
  818.            | command == "USE_DESKTOP",
  819.            | command == "KEEP_FAILED_URL",
  820.            | command == "KEEP_DONE_URL" then
  821.  
  822.              cfg.command = (argument == "1")
  823.         otherwise
  824.      end
  825.   end
  826.  
  827.   rc = stream( sys.config_file, "C", "CLOSE" )
  828.   cfg.file_date = stream( sys.config_file, "C", "QUERY DATETIME" )
  829. return
  830.  
  831. /*------------------------------------------------------------------
  832.  * Show Configuration
  833.  *------------------------------------------------------------------*/
  834. CfgShow: procedure expose (globals)
  835.  
  836.   key_list = CfgKeys()
  837.   do i = 1 to words(key_list)
  838.  
  839.      key = word(key_list,i)
  840.  
  841.      if  key \= "LOG_FILE"      &,
  842.          key \= "ERROR_LOG"     &,
  843.          key \= "MESSAGE_DONE"  &,
  844.          key \= "MESSAGE_ERROR" &,
  845.          cfg.key \= ""          &,
  846.          cfg.key \= "nul" then do
  847.  
  848.          say color.usual || "*** "msg.key  || ": " || color.bold || cfg.key
  849.      end
  850.   end
  851.  
  852.   call charout , color.usual
  853. return ""
  854.  
  855. /*------------------------------------------------------------------
  856.  * Check Configuration Changes
  857.  *------------------------------------------------------------------*/
  858. CfgCheckChanges: procedure expose (globals)
  859.  
  860.   changed = (cfg.file_date \= stream( sys.config_file, "C", "QUERY DATETIME" ))
  861.  
  862.   if changed then do
  863.      call LogPut inf, msg.config_changed
  864.      call CfgRead
  865.      cfg.download = CfgCheckDownload( cfg.download )
  866.      call CfgShow
  867.      changed = 1
  868.   end
  869.  
  870. return changed
  871.  
  872. /*------------------------------------------------------------------
  873.  * Check Download Directory
  874.  *------------------------------------------------------------------*/
  875. CfgCheckDownload: procedure expose (globals)
  876.  
  877.   parse arg download
  878.   download = translate( download, "\", "/" )
  879.  
  880.   if right( download, 1 ) = "\" then
  881.      download = left( download, length(download) - 1 )
  882.  
  883.   if download \= "." then do
  884.      setlocal
  885.      download = directory( download )
  886.      endlocal
  887.   end
  888.  
  889.   if download == "" then do
  890.      call LogPut err, msg.bad_downldir
  891.      download = "."
  892.   end
  893.  
  894. return download
  895.  
  896. /*------------------------------------------------------------------
  897.  * Read Local Configuration
  898.  *------------------------------------------------------------------*/
  899. CfgReadLocal: procedure expose (globals)
  900.  
  901.   parse arg home
  902.  
  903.   if right( home, 1 ) \= "\" then
  904.      home = home"\"
  905.  
  906.   cfg_file = home"awget.cfg"
  907.   cfg_date = stream( cfg_file, "C", "QUERY DATETIME" )
  908.  
  909.   if local.config_home \= home |,
  910.      local.file_date   \=  cfg.file_date" "cfg_date then do
  911.  
  912.      key_list = CfgKeys()
  913.      do i = 1 to words(key_list)
  914.         key = word(key_list,i)
  915.         local.key = cfg.key
  916.      end
  917.  
  918.      local.schedule    = ""
  919.      local.config_home = home
  920.      local.file_date   = ""
  921.  
  922.      rc = stream( cfg_file, "C", sys.open_read )
  923.  
  924.      do while lines(cfg_file) > 0
  925.         parse value linein(cfg_file) with command "=" argument
  926.  
  927.         command  = translate(strip(command))
  928.         argument = strip(argument)
  929.  
  930.         select
  931.            when command == "DOWNLOAD",
  932.               | command == "DOWNLOADS_ATTEMPTS",
  933.               | command == "SCHEDULE",
  934.               | command == "MESSAGE_DONE",
  935.               | command == "MESSAGE_ERROR" then
  936.  
  937.                 local.command = argument
  938.  
  939.            when command == "MESSAGES",
  940.               | command == "KEEP_FAILED_URL",
  941.               | command == "KEEP_DONE_URL" then
  942.  
  943.                 local.command = (argument == "1")
  944.            otherwise
  945.         end
  946.      end
  947.  
  948.      rc = stream( cfg_file, "C", "CLOSE" )
  949.      local.file_date = cfg.file_date" "cfg_date
  950.   end
  951. return
  952.  
  953. /*------------------------------------------------------------------
  954.  * Create Local Configuration
  955.  *------------------------------------------------------------------*/
  956. CfgCreateLocal: procedure expose (globals)
  957.  
  958.   parse arg home
  959.  
  960.   if right( home, 1 ) \= "\" then
  961.      home = home"\"
  962.  
  963.   cfg_file = home"awget.cfg"
  964.  
  965.   if stream( cfg_file, "C", "QUERY EXISTS" ) \= "" then
  966.      "@del " cfg_file
  967.  
  968.   rc = stream( cfg_file, "C", sys.open_write )
  969.  
  970.   key_list =  "DOWNLOAD "            ||,
  971.               "DOWNLOADS_ATTEMPTS "  ||,
  972.               "SCHEDULE "            ||,
  973.               "MESSAGE_DONE "        ||,
  974.               "MESSAGE_ERROR "       ||,
  975.               "MESSAGES "            ||,
  976.               "KEEP_FAILED_URL "     ||,
  977.               "KEEP_DONE_URL "
  978.  
  979.   do i = 1 to words(key_list)
  980.      key     = word(key_list,i)
  981.      comment = "CFG_"  || key
  982.      body    = "# "replace( msg.comment, "0D0A"x, "0D0A"x || "# " ) ||,
  983.                "0D0A"x || "0D0A"x || "#" key "=" || "0D0A"x
  984.  
  985.      call lineout cfg_file, body
  986.   end
  987.  
  988.   rc = stream( cfg_file, "C", "CLOSE" )
  989. return
  990.  
  991.  
  992. /* $Id: logs.cms,v 1.21 2001/05/11 08:54:34 glass Exp $ */
  993.  
  994. /*------------------------------------------------------------------
  995.  * Open log file
  996.  *------------------------------------------------------------------*/
  997. LogOpen: procedure expose (globals)
  998.  
  999.   parse arg logfile
  1000.  
  1001.   if logfile == "" | translate(logfile) == "NUL" then
  1002.      return 0
  1003.  
  1004.   do 5
  1005.      rc = stream( logfile, "c", sys.open_write )
  1006.      if rc == "READY:" then leave
  1007.      call SysSleep 1
  1008.   end
  1009.  
  1010. return (rc == "READY:")
  1011.  
  1012. /*------------------------------------------------------------------
  1013.  * Write Log Record
  1014.  *------------------------------------------------------------------*/
  1015. LogPut: procedure expose (globals)
  1016.  
  1017.   parse arg type, message, file_or_url, information
  1018.   type = translate(type)
  1019.  
  1020.   if type == "INF" then type = "INFO"
  1021.   if type == "ERR" then type = "ERROR"
  1022.   if type == "BLD" then type = "BOLD"
  1023.  
  1024.   select
  1025.     when type == "BOLD" | type == "INFO" then do
  1026.       logfile  = cfg.log_file
  1027.       end
  1028.  
  1029.     when type == "ERROR" then do
  1030.       logfile  = cfg.error_log
  1031.       end
  1032.  
  1033.     otherwise do
  1034.       type     = "USUAL"
  1035.       logfile  = cfg.log_file
  1036.       end
  1037.   end
  1038.  
  1039.   /* Output to file */
  1040.   if LogOpen(logfile) then do
  1041.  
  1042.      if arg( 3, "exists" ) then
  1043.         call lineout logfile, date('e')" "time()" "message": "file_or_url
  1044.      else
  1045.         call lineout logfile, date('e')" "time()" "message
  1046.  
  1047.      if arg( 4, "exists" ) & information \= "" then
  1048.         call lineout logfile, copies( ' ', 18 ) || information
  1049.  
  1050.      rc = stream( logfile, "c", "close" )
  1051.   end
  1052.  
  1053.   /* Sound's alert */
  1054.   if type == "ERROR" then
  1055.      call beep 1000, 100
  1056.  
  1057.   /* Display message */
  1058.   if arg( 3, "exists" ) then do
  1059.      if length(file_or_url) + length(message) < 73 then
  1060.         say color.type"■■■ "message": "file_or_url
  1061.      else do
  1062.         say color.type"■■■ "message": "
  1063.         say color.type"    "ShortenURL( file_or_url, 75 )
  1064.      end
  1065.      end
  1066.   else
  1067.      say color.type"■■■ "message
  1068.  
  1069.   if arg( 4, "exist" ) & information \= "" then
  1070.      say color.type"    "information
  1071.  
  1072.   call charout, color.usual
  1073. return
  1074.  
  1075. /* $Id: shorten.cms,v 1.3 2001/05/11 08:54:34 glass Exp $ */
  1076.  
  1077. /*------------------------------------------------------------------
  1078.  * Reduces URL length
  1079.  *------------------------------------------------------------------*/
  1080. ShortenURL: procedure expose (globals)
  1081.  
  1082.   parse arg url, max
  1083.  
  1084.   if length(url) > max then
  1085.      do
  1086.        if translate( left( url, 6 )) == "FTP://" then
  1087.           shorten = left( url, 6 )
  1088.        else if translate( left( url, 7 )) == "HTTP://" then
  1089.           shorten = left( url, 7 )
  1090.        else if substr( url, 3, 1 ) == "\" then
  1091.           shorten = left( url, 3 )
  1092.        else
  1093.           shorten = ""
  1094.  
  1095.        shorten = shorten || "..." ||,
  1096.                  right( url, max - length(shorten) - 3 )
  1097.      end
  1098.   else
  1099.      shorten = url
  1100.  
  1101. return shorten
  1102.  
  1103. /* $Id: replace.cms,v 1.5 2001/05/11 08:54:34 glass Exp $ */
  1104.  
  1105. /*------------------------------------------------------------------
  1106.  * Search and replace string
  1107.  *------------------------------------------------------------------*/
  1108. replace: procedure expose (globals)
  1109.  
  1110.   parse arg source, string, substitute
  1111.   string = translate(string)
  1112.  
  1113.   i = pos( string, translate(source))
  1114.  
  1115.   do while i \= 0
  1116.      source = substr( source, 1, i-1 ) || substitute ||,
  1117.               substr( source, i+length(string))
  1118.  
  1119.      i = pos( string, translate(source), i + length(substitute))
  1120.   end
  1121.  
  1122. return source
  1123.  
  1124. /* $Id: dirs.cms,v 1.24 2001/05/11 08:54:34 glass Exp $ */
  1125.  
  1126. /*------------------------------------------------------------------
  1127.  * Get Directorys
  1128.  *------------------------------------------------------------------*/
  1129. DirRead: procedure expose (globals)
  1130.  
  1131.   dir.todo    = AwGetObjectPath( "<AWG2_TODO>"    )
  1132.   dir.running = AwGetObjectPath( "<AWG2_RUNNING>" )
  1133.   dir.done    = AwGetObjectPath( "<AWG2_DONE>"    )
  1134.   dir.failed  = AwGetObjectPath( "<AWG2_FAILED>"  )
  1135.   dir.jobs    = AwGetObjectPath( "<AWG2_JOBS>"    )
  1136.   dir.desktop = AwGetObjectPath( "<WP_DESKTOP>"   )
  1137.  
  1138.   /* check it */
  1139.   dir_list = "ToDo Running Done Failed Jobs Desktop"
  1140.   do i = 1 to words(dir_list)
  1141.      name = translate( word( dir_list,i ))
  1142.      if dir.name == "" then do
  1143.         call LogPut err, msg.not_found, word( dir_list,i )
  1144.         exit 1
  1145.      end
  1146.   end
  1147. return
  1148.  
  1149. /*------------------------------------------------------------------
  1150.  * Show Directorys
  1151.  *------------------------------------------------------------------*/
  1152. DirShow: procedure expose (globals)
  1153.  
  1154.   say color.usual"*** "left( "Desktop"  ,10 )": "color.bold || ShortenURL( dir.desktop, 63 )
  1155.   say color.usual"*** "left( "Active"   ,10 )": "color.bold || ShortenURL( dir.running, 60 )
  1156.   say color.usual"*** "left( "Completed",10 )": "color.bold || ShortenURL( dir.done   , 63 )
  1157.   say color.usual"*** "left( "Failed"   ,10 )": "color.bold || ShortenURL( dir.failed , 60 )
  1158.   say color.usual"*** "left( "ToDo"     ,10 )": "color.bold || ShortenURL( dir.todo   , 63 )
  1159.   call charout , color.usual
  1160. return
  1161.  
  1162. /*------------------------------------------------------------------
  1163.  * Converts directory to canonical form
  1164.  *------------------------------------------------------------------*/
  1165. DirCanonical: procedure expose (globals)
  1166.  
  1167.   parse arg path
  1168.   path = translate( path, "\", "/" )
  1169.  
  1170.   if right( path, 1 ) == "\" & pos( ":", path ) \= length(path)-1 then
  1171.      path = left( path, length(path)-1 )
  1172.  
  1173. return path
  1174.  
  1175. /*------------------------------------------------------------------
  1176.  * Returns path to file
  1177.  *------------------------------------------------------------------*/
  1178. DirPath: procedure expose (globals)
  1179.  
  1180.   parse arg pathname
  1181.  
  1182. return DirCanonical( filespec( "drive", pathname ) ||,
  1183.                      filespec( "path" , pathname ))
  1184.  
  1185. /*------------------------------------------------------------------
  1186.  * Create directory
  1187.  *------------------------------------------------------------------*/
  1188. DirCreate: procedure expose (globals)
  1189.  
  1190.   parse arg path
  1191.  
  1192.   path = DirCanonical( path )
  1193.   rc   = SysMkDir( path )
  1194.  
  1195.   if rc == 3 & pos( "\", path ) \= 0 then do
  1196.  
  1197.      parent = left( path, length(path) - pos( "\", reverse(path)))
  1198.      rc = DirCreate( parent )
  1199.  
  1200.      if rc == 0 then
  1201.         rc = SysMkDir( path )
  1202.   end
  1203. return rc
  1204.  
  1205. /*------------------------------------------------------------------
  1206.  * Checks existence of the directory
  1207.  *------------------------------------------------------------------*/
  1208. DirExist: procedure expose (globals)
  1209.  
  1210.   parse arg path
  1211.   if path == "" then return 0
  1212.   path = DirCanonical( path )
  1213.  
  1214.   setlocal
  1215.   path = directory( path )
  1216.   endlocal
  1217.  
  1218. return path \= ""
  1219.  
  1220.  
  1221. /* $Id: wps.cms,v 1.19 2001/05/11 08:54:34 glass Exp $ */
  1222.  
  1223. /*------------------------------------------------------------------
  1224.  * Refresh Folder
  1225.  *------------------------------------------------------------------*/
  1226. WpsRefresh: procedure expose (globals)
  1227.  
  1228.   parse arg path
  1229.  
  1230. return SysSetObjectData( path, "MENUITEMSELECTED=503" )
  1231.  
  1232. /*------------------------------------------------------------------
  1233.  * Moves the WPS object
  1234.  *------------------------------------------------------------------*/
  1235. WpsMove: procedure expose (globals)
  1236.  
  1237.   parse arg file_from, file_to, touch
  1238.  
  1239.   file_long = WpsGetEA( file_from, ".LONGNAME" )
  1240.  
  1241.   if file_long == "" then
  1242.      rc = WpsPutEA( file_from, ".LONGNAME", filespec( "name", file_from ))
  1243.  
  1244.   if stream( file_to, "c", "query exists" ) \= "" then do
  1245.  
  1246.      path = filespec( "drive", file_to ) || filespec( "path", file_to )
  1247.      name = filespec( "name" , file_to )
  1248.      dot  = lastpos( ".", name )
  1249.      ext  = ""
  1250.  
  1251.      if dot > 0 then do
  1252.         ext  = substr( name, dot      )
  1253.         name = substr( name, 1, dot-1 )
  1254.      end
  1255.  
  1256.      if length( name ) > 8 then
  1257.         name = name"???"
  1258.      else do
  1259.         if length( name ) < 3 then
  1260.            name = substr( name, 1, 3, "!" )
  1261.  
  1262.         name = substr( name, 1, 5, "?" )
  1263.         name = substr( name, 1, 8, "?" )
  1264.      end
  1265.  
  1266.      file_to = SysTempFileName( path || name || ext )
  1267.   end
  1268.  
  1269.   if abbrev( "touch", touch, 1 ) then
  1270.      'copy "'file_from'" + ,, "'file_to'" 1> nul 2> nul'
  1271.   else
  1272.      'copy "'file_from'" "'file_to'" 1> nul 2> nul'
  1273.  
  1274.   if rc == 0 then
  1275.      call WpsDestroy file_from
  1276.   else do
  1277.      call LogPut err, msg.not_move", "file_from" -> "file_to
  1278.      file_to = ""
  1279.   end
  1280.  
  1281. return file_to
  1282.  
  1283. /*------------------------------------------------------------------
  1284.  * Destroys the WPS object
  1285.  *------------------------------------------------------------------*/
  1286. WpsDestroy: procedure expose (globals)
  1287.  
  1288.   parse arg file
  1289.  
  1290.   if stream( file, "C", "QUERY EXISTS" ) \= "" then
  1291.      return SysDestroyObject( file )
  1292.  
  1293. return 1
  1294.  
  1295. /*------------------------------------------------------------------
  1296.  * Write a named ascii extended attribute to a file
  1297.  *------------------------------------------------------------------*/
  1298. WpsPutEA: procedure expose (globals)
  1299.  
  1300.   parse arg file, name, ea_string
  1301.   ea = ""
  1302.  
  1303.   if pos( '00'x, ea_string ) > 0 then do
  1304.      do ea_count = 0 while length( ea_string ) > 0
  1305.        parse value ea_string with string '00'x ea_string
  1306.        ea = ea || 'FDFF'x ||,
  1307.             substr( reverse( d2c(length(string))), 1, 2, '00'x ) ||,
  1308.             string
  1309.      end
  1310.      ea = 'DFFF'x || '0000'x ||,
  1311.           substr( reverse( d2c(ea_count)), 1, 2, '00'x ) || ea
  1312.      end
  1313.   else
  1314.      ea = 'FDFF'x ||,
  1315.           substr( reverse( d2c(length(ea_string))), 1, 2, '00'x ) ||,
  1316.           ea_string
  1317.  
  1318. return SysPutEA( file, name, ea )
  1319.  
  1320. /*------------------------------------------------------------------
  1321.  * Read a named ascii extended attribute from a file
  1322.  *------------------------------------------------------------------*/
  1323. WpsGetEA: procedure expose (globals)
  1324.  
  1325.   parse arg file, name
  1326.   if file == "" then return ""
  1327.  
  1328.   if SysGetEA( file, name, "ea" ) \= 0 then
  1329.      return ""
  1330.  
  1331.   ea_type   = substr( ea, 1, 2 )
  1332.   ea_string = ""
  1333.  
  1334.   select
  1335.     when ea_type == 'FDFF'x then
  1336.       ea_string = substr( ea, 5 )
  1337.  
  1338.     when ea_type == 'DFFF'x then do
  1339.       ea_count = c2d( reverse( substr( ea, 5, 2 )))
  1340.       say "count: "ea_count
  1341.       ea_pos   = 7
  1342.       do ea_count while substr( ea, ea_pos, 2 ) == 'FDFF'x
  1343.          ea_length = c2d( reverse( substr( ea, ea_pos+2, 2 )))
  1344.          ea_string = ea_string || substr( ea, ea_pos+4, ea_length ) || '00'x
  1345.          ea_pos    = ea_pos + 4 + ea_length
  1346.       end
  1347.       end
  1348.  
  1349.     otherwise
  1350.   end
  1351.  
  1352. return ea_string
  1353.  
  1354. /* $Id: url.cms,v 1.15 2001/05/11 08:54:34 glass Exp $ */
  1355.  
  1356. /*------------------------------------------------------------------
  1357.  * Get URL from file
  1358.  *------------------------------------------------------------------*/
  1359. GetURLFromFile: procedure expose (globals)
  1360.  
  1361.   parse arg filename
  1362.  
  1363.   rc  = stream(filename, "c", sys.open_read )
  1364.   url = linein(filename)
  1365.  
  1366.   if translate( strip( url )) == "[INTERNETSHORTCUT]" then
  1367.      parse value linein(filename) with 'URL='url
  1368.  
  1369.   rc  = stream(filename, "c", "close" )
  1370. return strip(url)
  1371.  
  1372. /*------------------------------------------------------------------
  1373.  * Decode URL
  1374.  *------------------------------------------------------------------*/
  1375. DecodeURL: procedure expose (globals)
  1376.  
  1377.   parse arg url
  1378.  
  1379.   do while pos( "%", url ) > 0
  1380.  
  1381.      i = pos( "%", url )
  1382.  
  1383.      url = substr( url, 1, i-1      ) ||,
  1384.            x2c(substr( url, i+1, 2 )) ||,
  1385.            substr( url, i+3         )
  1386.   end
  1387.  
  1388. return url
  1389.  
  1390. /*------------------------------------------------------------------
  1391.  * Get filename from URL
  1392.  *------------------------------------------------------------------*/
  1393. GetFileFromURL: procedure expose (globals)
  1394.  
  1395.   /* generic-RL syntax consists of six components:           */
  1396.   /* <scheme>://<net_loc>/<path>;<params>?<query>#<fragment> */
  1397.  
  1398.   parse arg url
  1399.   url = strip(url)
  1400.  
  1401.   i = lastpos( "#", url )
  1402.   if i > 0 then url = substr( url, 1, i-1 )
  1403.  
  1404.   i = pos( ":", url )
  1405.   if i > 0 then url = substr( url, i+1 )
  1406.  
  1407.   if left(url,2) == "//" then do
  1408.      i = pos( "/", url, 3 )
  1409.      if i > 0 then
  1410.         url = substr( url, i )
  1411.      else
  1412.         url = ""
  1413.   end
  1414.  
  1415.   i = lastpos( "?", url )
  1416.   if i > 0 then url = substr( url, 1, i-1 )
  1417.  
  1418.   i = lastpos( ";", url )
  1419.   if i > 0 then url = substr( url, 1, i-1 )
  1420.  
  1421.   i = lastpos( "/", url )
  1422.   if i > 0 then url = substr( url, i+1 )
  1423.  
  1424.   if url == "" then url = "index.html"
  1425. return DecodeURL(url)
  1426.  
  1427. /*------------------------------------------------------------------
  1428.  * Check valid URL file
  1429.  *------------------------------------------------------------------*/
  1430. IsURLFile: procedure expose (globals)
  1431.  
  1432.   parse arg filename
  1433.  
  1434.   rc  = stream(filename, "c", "open read" )
  1435.   url = translate( strip( charin(filename,1,18)))
  1436.   rc  = stream(filename, "c", "close" )
  1437.  
  1438. return substr( url, 1,  7 ) == "HTTP://" |,
  1439.        substr( url, 1,  6 ) == "FTP://"  |,
  1440.        substr( url, 1, 18 ) == "[INTERNETSHORTCUT]"
  1441.  
  1442.  
  1443. /* $Id: jobs.cms,v 1.11 2001/05/11 08:54:34 glass Exp $ */
  1444.  
  1445. /*------------------------------------------------------------------
  1446.  * Read Job from file
  1447.  *------------------------------------------------------------------*/
  1448. JobRead: procedure expose (globals)
  1449.  
  1450.   parse arg pathname
  1451.  
  1452.   job.object               = ""
  1453.   job.url                  = ""
  1454.   job.download             = ""
  1455.   job.message_done         = ""
  1456.   job.message_error        = ""
  1457.   job.downloads_utility    = ""
  1458.   job.downloads_parameters = ""
  1459.   job.downloads_rc         = 0
  1460.   job.downloads_info       = ""
  1461.  
  1462.   rc = stream( pathname, "C", sys.open_read )
  1463.  
  1464.   if rc \= "READY:" then do
  1465.      call LogPut err, msg.read_error, pathname
  1466.      return 0
  1467.   end
  1468.  
  1469.   do while lines(pathname) > 0
  1470.      parse value linein(pathname) with command "=" argument
  1471.  
  1472.      command  = translate(strip(command))
  1473.      argument = strip(argument)
  1474.  
  1475.      select
  1476.         when command == "OBJECT",
  1477.            | command == "URL",
  1478.            | command == "DOWNLOAD",
  1479.            | command == "DOWNLOADS_UTILITY",
  1480.            | command == "DOWNLOADS_PARAMETERS",
  1481.            | command == "DOWNLOADS_SIMULTANEOUSLY",
  1482.            | command == "DOWNLOADS_RC",
  1483.            | command == "DOWNLOADS_INFO",
  1484.            | command == "MESSAGE_DONE",
  1485.            | command == "MESSAGE_ERROR" then
  1486.  
  1487.              job.command = argument
  1488.         otherwise
  1489.      end
  1490.   end
  1491.  
  1492.   rc = stream( pathname, "C", "CLOSE" )
  1493. return 1
  1494.  
  1495. /*------------------------------------------------------------------
  1496.  * Save Job to file
  1497.  *------------------------------------------------------------------*/
  1498. JobSave: procedure expose (globals)
  1499.  
  1500.   parse arg pathname
  1501.  
  1502.   if arg( 1, "omitted" ) | pathname == "" then do
  1503.      pathname = SysTempFileName( dir.jobs"\?????.job" )
  1504.      body.0   = 0
  1505.      end
  1506.   else do
  1507.      rc = stream( pathname, "C", sys.open_read )
  1508.  
  1509.      do i = 1 while lines(pathname) > 0
  1510.         body.i = linein(pathname)
  1511.      end
  1512.      body.0 = i - 1
  1513.      rc = stream( pathname, "C", "CLOSE" )
  1514.   end
  1515.  
  1516.   key_list = "OBJECT "               ||,
  1517.              "URL "                  ||,
  1518.              "DOWNLOAD "             ||,
  1519.              "MESSAGE_DONE "         ||,
  1520.              "MESSAGE_ERROR "        ||,
  1521.              "DOWNLOADS_UTILITY "    ||,
  1522.              "DOWNLOADS_PARAMETERS " ||,
  1523.              "DOWNLOADS_RC "         ||,
  1524.              "DOWNLOADS_INFO "
  1525.  
  1526.   do i = 1 to words(key_list)
  1527.      key = word(key_list,i)
  1528.  
  1529.      do j = 1 to body.0
  1530.         if left( strip( body.j ), 1 ) == "#" then
  1531.            iterate
  1532.  
  1533.         parse value body.j with command "="
  1534.         command = translate(strip(command))
  1535.  
  1536.         if key == command then
  1537.            leave
  1538.      end j
  1539.  
  1540.      body.j = key "=" job.key
  1541.  
  1542.      if j > body.0 then
  1543.         body.0 = j
  1544.   end i
  1545.  
  1546.   if stream( pathname, "C", "QUERY EXISTS" ) \= "" then
  1547.      '@del "'pathname'" /F'
  1548.  
  1549.   rc = stream( pathname, "C", sys.open_write )
  1550.  
  1551.   if rc \= "READY:" then do
  1552.      call LogPut err, msg.write_error, pathname
  1553.      return ""
  1554.   end
  1555.  
  1556.   do j = 1 to body.0
  1557.      call lineout pathname, body.j
  1558.   end
  1559.  
  1560.   rc = stream( pathname, "C", "CLOSE" )
  1561. return pathname
  1562.  
  1563. /* $Id: plugins.cms,v 1.14 2001/05/11 08:54:34 glass Exp $ */
  1564.  
  1565. /*------------------------------------------------------------------
  1566.  * Get Plugins List
  1567.  *------------------------------------------------------------------*/
  1568. PlgRead: procedure expose (globals)
  1569.  
  1570.   parse arg type
  1571.  
  1572.   type  = translate(type"_plugin")
  1573.   rc    = stream( sys.config_file, "C", sys.open_read )
  1574.   count = 0
  1575.  
  1576.   do while lines(sys.config_file) > 0
  1577.      parse value linein(sys.config_file) with command "=" argument
  1578.  
  1579.      if translate(strip(command)) == type then do
  1580.         count = count + 1
  1581.         plugins.count.module = strip(argument)
  1582.         plugins.count.handle = ""
  1583.         plugins.count.buffer = ""
  1584.      end
  1585.   end
  1586.  
  1587.   rc = stream( sys.config_file, "C", "CLOSE" )
  1588.   plugins.0 = count
  1589. return
  1590.  
  1591. /*------------------------------------------------------------------
  1592.  * Activate Plugins
  1593.  *------------------------------------------------------------------*/
  1594. PlgStart: procedure expose (globals)
  1595.  
  1596.   do i = 1 to plugins.0
  1597.      rc = AwPOpen( "cmd.exe", "/c "plugins.i.module,,
  1598.                               "plugins."i".handle", "detach" )
  1599.      if rc \= 0 then
  1600.         call LogPut err, msg.error_in "AwPOpen, rc="rc,, SysGetMessage(rc)
  1601.   end
  1602. return
  1603.  
  1604. /*------------------------------------------------------------------
  1605.  * Deactivate Plugins
  1606.  *------------------------------------------------------------------*/
  1607. PlgStop: procedure expose (globals)
  1608.  
  1609.   do i = 1 to plugins.0
  1610.      if plugins.i.handle \= "" then
  1611.         AwPWrite( plugins.id.handle, "STOP" || "0D0A"x )
  1612.   end
  1613. return
  1614.  
  1615. /*------------------------------------------------------------------
  1616.  * Send Event
  1617.  *------------------------------------------------------------------*/
  1618. PlgSend: procedure expose (globals)
  1619.  
  1620.   parse arg id, event
  1621.   event = event || "0D0A"x
  1622.  
  1623.   if AwPWrite( plugins.id.handle, event ) != length(event) then do
  1624.      call LogPut err, msg.error_in "AwPWrite",, plugins.id.module
  1625.      return 0
  1626.   end
  1627.  
  1628.   do forever
  1629.      readed = AwPRead( plugins.id.handle )
  1630.      if readed == "" then do
  1631.         call LogPut err, msg.plugin_dead, plugins.id.module
  1632.         plugins.id.handle = ""
  1633.         return 1
  1634.      end
  1635.  
  1636.      plugins.id.buffer = plugins.id.buffer || readed
  1637.  
  1638.      i = pos( '0D0A'x,  plugins.id.buffer )
  1639.      do while i > 0
  1640.         event = substr( plugins.id.buffer, 1, i - 1 )
  1641.         plugins.id.buffer = substr( plugins.id.buffer, i + 2 )
  1642.  
  1643.         message = substr( event, 6    )
  1644.         event   = substr( event, 1, 4 )
  1645.  
  1646.         select
  1647.           when event == "INFO" then
  1648.                say color.info || "*** "message || color.usual
  1649.           when event == "EVNT" then
  1650.                call LogPut bld, message
  1651.           when event == "ALRM" then
  1652.                call LogPut err, message
  1653.  
  1654.           when event == "DONE" then do
  1655.                if message \= "" then
  1656.                   say color.info || "*** "message || color.usual
  1657.  
  1658.                plugins.id.buffer = ""
  1659.                return 1
  1660.                end
  1661.  
  1662.           when event == "FAIL" then do
  1663.                if message \= "" then
  1664.                   call LogPut err, message
  1665.  
  1666.                plugins.id.buffer = ""
  1667.                return 0
  1668.                end
  1669.  
  1670.           otherwise
  1671.         end
  1672.         i = pos( '0D0A'x,  plugins.id.buffer )
  1673.      end
  1674.   end
  1675. return 0
  1676.  
  1677. /*------------------------------------------------------------------
  1678.  * Broadcast Event
  1679.  *------------------------------------------------------------------*/
  1680. PlgBroadcast: procedure expose (globals)
  1681.  
  1682.   parse arg event
  1683.   done = 1
  1684.  
  1685.   do i = 1 to plugins.0
  1686.      if plugins.i.handle \= "" then
  1687.         done = PlgSend( i, event ) & done
  1688.   end
  1689. return done
  1690.  
  1691. /*------------------------------------------------------------------
  1692.  * Write Byte Stream
  1693.  *------------------------------------------------------------------*/
  1694. PlgWrite: procedure expose (globals)
  1695.  
  1696.   parse arg stream
  1697.  
  1698.   do i = 1 to plugins.0
  1699.      if plugins.i.handle \= "" then
  1700.         call AwPWrite plugins.i.handle, stream
  1701.   end
  1702. return
  1703.  
  1704. /* $Id: ppp.cms,v 1.11 2001/05/11 08:54:34 glass Exp $ */
  1705.  
  1706. /*------------------------------------------------------------------
  1707.  * Check PPP connection
  1708.  *------------------------------------------------------------------*/
  1709. pppCheck: procedure expose (globals)
  1710.  
  1711.   if \cfg.check_connection then
  1712.  
  1713.     sys.connected = 1
  1714.  
  1715.   else do
  1716.  
  1717.     new_queue = RxQueue( 'create' )
  1718.     old_queue = RxQueue( 'set', new_queue )
  1719.     active    = 0
  1720.  
  1721.     '@netstat -a | RXQUEUE' new_queue
  1722.  
  1723.     do while queued() > 0
  1724.        parse pull . IP1 . interface . . . IP2
  1725.        if interface >= '10' then do
  1726.           active = 1
  1727.        end
  1728.     end
  1729.  
  1730.     call RxQueue 'delete', new_queue
  1731.     call RxQueue 'set'   , old_queue
  1732.  
  1733.     if active \= sys.connected then do
  1734.        sys.connected = active
  1735.  
  1736.        if active then
  1737.           call LogPut bld, msg.connection_established
  1738.        else
  1739.           call LogPut bld, msg.connection_broken
  1740.     end
  1741.   end
  1742.  
  1743. return sys.connected
  1744.  
  1745. /* $Id: date.cms,v 1.5 2001/05/11 08:54:34 glass Exp $ */
  1746.  
  1747. /*------------------------------------------------------------------
  1748.  * Convert a date in the format dd/mm/yy into the base date
  1749.  *------------------------------------------------------------------*/
  1750. DateBase: procedure expose (globals)
  1751.  
  1752.   /* initialize routine */
  1753.   NonLeap.   = 31
  1754.   NonLeap.0  = 12
  1755.   NonLeap.2  = 28
  1756.   NonLeap.4  = 30
  1757.   NonLeap.6  = 30
  1758.   NonLeap.9  = 30
  1759.   NonLeap.11 = 30
  1760.  
  1761.   /* grab parameter and store it in cyear cmonth cdate  */
  1762.   parse arg cdate +2 +1 cmonth +2 +1 cyear .
  1763.  
  1764.   if datatype(cdate ) \= "NUM" |,
  1765.      datatype(cmonth) \= "NUM" |,
  1766.      datatype(cyear ) \= "NUM" then
  1767.      return 0
  1768.  
  1769.   /* grab year and convert it to YYYY                   */
  1770.   /* simulate the behaviour of the REXX function date() */
  1771.   if length( cyear ) <= 2 then
  1772.      if cyear < 80 then
  1773.         fullyear = "20" || cyear
  1774.      else
  1775.         fullyear = "19" || cyear
  1776.   else
  1777.      fullyear = cyear
  1778.  
  1779.   numyears    = fullyear - 1
  1780.   basedays    = numyears * 365
  1781.   QuadCentury = numyears % 400
  1782.   Century     = numyears % 100
  1783.   LeapYears   = numyears % 4
  1784.   basedays    = basedays + (((LeapYears - Century) + QuadCentury) - 1)
  1785.  
  1786.   do i = 1 to (cmonth -1)
  1787.      if i <> "2" then
  1788.         basedays = basedays + NonLeap.i
  1789.      else /* find if it's a leap year or not */
  1790.         if (fullyear // 4) > 0 then
  1791.            basedays = basedays + 28
  1792.         else
  1793.            if ((fullyear // 100) = 0) & ((fullyear // 400) > 0) then
  1794.               do
  1795.                 /* century not divisble by 400       */
  1796.                 basedays = basedays + 28
  1797.               end /* if */
  1798.            else
  1799.               do
  1800.                 /* quad century or regular leap year */
  1801.                 basedays = basedays + 29
  1802.               end /* else */
  1803.   end /* do */
  1804.  
  1805.   basedays = basedays + cdate
  1806. return basedays
  1807.