/*
** GrabHTTP.c - Opens an ARexx port and wait for commands
** Copyright (C) 1996-97 Serge Emond
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/


/// Revision History
//
//  0.001   Up to 16.8.96   No information.
//  0.002   16.08.96
//          - Checks if port already exists
//          - ARexx Command VERSION
//          - Read/write to socket not buffered anymore
//          - A lot of unlogged stuff
//  0.003   19.8.96
//          - Replaced console output with window
//          - Cannot be made resident anymore (font loading/window drawing)
//
///

#include "GrabHTTP.h"

/// Prototypes
#include "GrabHTTP_protos.h"
#include "GHUtilities_protos.h"
#include "GHWindows_protos.h"

#ifdef ONE_OBJECT_ONLY
#include "GHUtilities.c"
#include "BufIO.c"
#include "GHRexxFcts.c"
#include "GHWindows.c"
#include "GHBase64.c"
#endif
///

/// Globals

const TEXT *version=VERSION;

extern struct ExecBase *SysBase;
struct Common c;
struct Specific s;                  // Won't be global somewhere in the future
struct Library *TimerBase;

extern const struct Functions fcts[];

struct Wtexts wtexts = {
    "URL:",
    "File:",
    "Received:",
    "Chars/sec:",
    "Actual:",
    "Remaining:",
    "_Skip this file",
    "_Abort transfer" };

///

/// Main()

LONG main(void)
{
    // Checks for system version

    if (SysBase->LibNode.lib_Version < 39)
    {
        Write(Output(), "You need OS version 39 or more\n", 31);
        exit(20);
    }

    InitAll();
    Loop();
    EndAll(NULL);
}
///

/// InitAll()

void InitAll(void)
{
    const ULONG opt_wbuf = DEF_WBUF;

    // Fill Global struct with NULLs
    memset((STRPTR)&c, 0L, sizeof(struct Common));
    memset((STRPTR)&s, 0L, sizeof(struct Specific));

    // Set default options

    c.opts[OPT_ACCEPT] = (LONG) DEF_MIME;
    c.opts[OPT_PORT] = (LONG) DEF_PORTNAME;
    c.opts[OPT_WBUF] = (LONG) &opt_wbuf;

    // Read CLI Args
    if (!(c.rdargs = ReadArgs(OPT_TEMP, c.opts, NULL)))
    {
        PrintFault(IoErr(), NULL);
        EndAll(RETURN_FAIL);
    }

    // Init Specific
    memset((char *)&s, 0L, sizeof(struct Specific));
    if (!InitSpecific(&s))
        EndAll(RETURN_FAIL);

    s.wtexts = &wtexts;

    // Create Msg Port
    Forbid();
    c.mp = FindPort((TEXT *)c.opts[OPT_PORT]);
    Permit();

    if (c.mp) {
        Printf("Port already in use\n");
        c.mp = 0;
        EndAll(RETURN_FAIL);
    }

    if (!(c.mp = CreatePort((STRPTR)c.opts[OPT_PORT], NULL)))
    {
        Printf("Can't create message port\n");
        EndAll(RETURN_FAIL);
    }

    // Get Initial Directory Lock
    c.idir = CurrentDir(NULL);
    UnLock(CurrentDir(DupLock(c.idir)));

    // Open Timer Device
    c.tr = (struct timerequest *)CreateExtIO(c.mp, sizeof (struct timerequest));
    if (!c.tr) EndAll(RETURN_FAIL);

    if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)c.tr, NULL))
        EndAll(RETURN_FAIL);
    else
        TimerBase = (struct Library *)c.tr->tr_node.io_Device;

    c.timezone = DEF_TZ;

    c.wbufsize = ( *(ULONG *)c.opts[OPT_WBUF] > MIN_WBUF ?
                   *(ULONG *)c.opts[OPT_WBUF] : MIN_WBUF);

}
///

/// EndAll()

void EndAll(ULONG ret)
{
    if (TimerBase) CloseDevice((struct IORequest *)c.tr);

    if (c.tr) DeleteExtIO((struct IORequest *)c.tr);

    if (c.mp)
    {
        /* Return residual messages */
        while(c.msg = GetMsg(c.mp)) {
            if (IsRexxMsg((struct RexxMsg *)c.msg)) {
                ((struct RexxMsg *)c.msg)->rm_Result1 = 20;
            }

            ReplyMsg(c.msg);
        }

        DeletePort(c.mp);
    }

    FreeSpecific(&s);

    if (c.email.p)
        FreeMem(c.email.p, c.email.s);

    if (c.auth.p)
        FreeMem(c.auth.p, c.auth.s);

    if (s.gtxt.url.p)
        FreeMem(s.gtxt.url.p, s.gtxt.url.s);
    if (s.gtxt.file.p)
        FreeMem(s.gtxt.file.p, s.gtxt.file.s);
    if (s.gtxt.recd.p)
        FreeMem(s.gtxt.recd.p, s.gtxt.recd.s);
    if (s.gtxt.cps.p)
        FreeMem(s.gtxt.cps.p, s.gtxt.cps.s);
    if (s.gtxt.actual.p)
        FreeMem(s.gtxt.actual.p, s.gtxt.actual.s);
    if (s.gtxt.rem.p)
        FreeMem(s.gtxt.rem.p, s.gtxt.rem.s);
    if (s.gtxt.stat.p)
        FreeMem(s.gtxt.stat.p, s.gtxt.stat.s);
    if (s.gtxt.user.p)
        FreeMem(s.gtxt.user.p, s.gtxt.user.s);
    if (s.gtxt.prog.p)
        FreeMem(s.gtxt.prog.p, s.gtxt.prog.s);

    if (c.rdargs)
        FreeArgs(c.rdargs);

    if (s.ffh)
        Close(s.ffh);

    if (c.idir)
        UnLock(CurrentDir(c.idir));

    if (s.w) {
        CloseWindow(s.w);
        FreeGadgets(s.glist);
        FreeVisualInfo(s.vi);
        UnlockPubScreen(NULL, s.scr);
    }

    exit(ret);
}
///

/// Loop()

void Loop(void)
{
    ULONG signal;

    while(1)
    {
        signal = Wait(1 << c.mp->mp_SigBit | SIGBREAKF_CTRL_C);

        if (signal & (1<<c.mp->mp_SigBit))
        {
            while(c.msg = GetMsg(c.mp))
            {
                /* We want only ARexx messages */
                if (IsRexxMsg((struct RexxMsg *)c.msg)) ProcMsg();
                else ReplyMsg(c.msg);
            }
        }
        if (signal & SIGBREAKF_CTRL_C)
        {
            Printf("***BREAK\n");
            EndAll(0L);
        }
    }
}
///

/// ProgMsg()

void ProcMsg(void)
{
    TEXT tok[128], *p;

    p = stptok(((struct RexxMsg *)c.msg)->rm_Args[0], tok, sizeof(tok), " ");
    p = stpblk(++p);

    for (c.CurFct=0; fcts[c.CurFct].cmd != NULL; c.CurFct++)
    {
        if (!Stricmp(fcts[c.CurFct].cmd, tok))
        {
            fcts[c.CurFct].function(p);
            break;
        }
    }

    if (fcts[c.CurFct].cmd == NULL) Reply(10, NULL);
}
///

