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