#include "common/extern.h"
#include "common/asyncio.h"
#include "common/parseurl.h"
#include "common/subtasksupp.h"
#include "common/urltype.h"
#include "common/Grab_mcc.h"
#include "scanhtml.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <proto/exec.h>
#include <proto/dos.h>

#include <workbench/startup.h>


/// "Global variables"

struct SignalSemaphore *mem_sema;
APTR pool;
extern char *vstring;

///

inline ULONG
is_space (char a)
{
  return ((a == ' ') || (a == '\t') || (a == CR) || (a == LF))
}

/// "ULONG DoPortMethod (struct MsgPort *port, struct MsgPort *rport, APTR obj, ...)"
ULONG
DoPortMethod (struct MsgPort * port, struct MsgPort * rport, APTR obj,...)
{
  struct MUIMessage muimsg =
  {obj, 0, (ULONG *) (&obj) + 1};

  struct SubTaskMsg stm_Message =
  {
    {
      {NULL, NULL, 0, 0, NULL},
      rport, sizeof (struct SubTaskMsg)
    },

    STC_MUIMSG,
    &muimsg,
    0
  };

  PutMsg (port, (struct Message *) &stm_Message);
  WaitPort (rport);
  GetMsg (rport);

  return (stm_Message.stm_Result);
}

ULONG
DoPortAMethod (struct MsgPort * port, struct MsgPort * rport, APTR obj, LONG parnum,...)
{
  struct MUIMessage muimsg =
  {obj, parnum, (ULONG *) (&parnum) + 1};

  struct SubTaskMsg stm_Message =
  {
    {
      {NULL, NULL, 0, 0, NULL},
      rport, sizeof (struct SubTaskMsg)
    },

    STC_MUIAMSG,
    &muimsg,
    0
  };

  PutMsg (port, (struct Message *) &stm_Message);
  WaitPort (rport);
  GetMsg (rport);

  return (stm_Message.stm_Result);
}

///

/// "addurl"

void
add_url (struct scanhtml_data *sd, char *url, struct parseurl *abs_url)
{
  struct parseurl *rel_url;
  struct URLNode *und;

  if ((und = (struct URLNode *) AllocSPooled (pool, sizeof (struct URLNode))))
    {
      memset (und, 0, sizeof (struct URLNode));

      if ((und->url = encode_url (url, __UF_UNRESERVED | __UF_URIC | __UF_SPECIAL)))
        {
          if ((rel_url = parse_url (und->url)))
            {
              FreeVecPooled (pool, und->url);

              if ((und->url = parse_relurl2absurl (abs_url, rel_url)))
                {
                  BOOL add = FALSE;

                  // HTTP url ?
                  if ((rel_url->pu_scheme) ? (stricmp (rel_url->pu_scheme, "http") == 0) : FALSE)
                    {
                      // To do: Here I compare the two server
                      if ((rel_url->pu_netloc && abs_url->pu_netloc) ? (stricmp (rel_url->pu_netloc, abs_url->pu_netloc)) : FALSE)
                        {
                          if ((sd->sn->nd) ? (sd->sn->nd->flags & URLN_EXTERNSERVER) : TRUE)
                            {
                              if (rel_url->pu_name)
                                {
                                  und->name = newstrcpy (pool, rel_url->pu_name);
                                  und->password = newstrcpy (pool, rel_url->pu_passwd);
                                }
                              else
                                {
                                  und->name = NULL;
                                  und->password = NULL;
                                }

                              add = TRUE;
                            }
                        }
                      else if ((sd->sn->nd) ? (sd->sn->nd->flags & URLN_SAMESERVER) : TRUE)
                        {
                          if (sd->sn->nd)
                            {
                              if (!rel_url->pu_name)
                                {
                                  und->name = newstrcpy (pool, sd->sn->nd->name);
                                  und->password = newstrcpy (pool, sd->sn->nd->password);
                                }
                              else
                                {
                                  und->name = newstrcpy (pool, rel_url->pu_name);
                                  und->password = newstrcpy (pool, rel_url->pu_passwd);
                                }
                            }

                          // check for direction
                          /*if (sd->sn->nd->flags & URLN_FORWARD)
                            {
                              if (stricmp (rel_url->pu_path, rel_url->pu_path) >= 0)
                                add = TRUE;
                            }
                          else if (sd->sn->nd->flags & URLN_BACKWARD)
                            {
                              if (stricmp (rel_url->pu_path, rel_url->pu_path) < 0)
                                add = TRUE;
                            }
                          else */
                            add = TRUE;
                        }
                    }

                  if (add)
                    {
                      struct URLNode *tnd;

                      if ((tnd = sd->sn->nd))
                        {
                          und->flags = tnd->flags;

                          if (tnd->depth > 0)
                            und->depth = tnd->depth - 1;
                          else
                            und->depth = 0;

                          und->maxsize = tnd->maxsize;

                          und->extensions = newstrcpy (pool, tnd->extensions);
                          und->types = newstrcpy (pool, tnd->types);

                          und->htmlflags = tnd->htmlflags;

                        }
                      else
                        {
                          und->extensions = und->types = NULL;
                          und->flags = 0;
                          und->depth = 0;
                          und->maxsize = 0;
                          und->htmlflags = HTML_HTML_AMIGA;
                        }

                      und->status = ST_CLEAR;
                      und->title = und->type = und->etag = NULL;
                      und->size = 0;

                      ObtainSemaphore (&sd->sema);
                      AddTail (&sd->linklist, (struct Node *) und);
                      ReleaseSemaphore (&sd->sema);

                      return;   //und = NULL;

                    }
                }

              free_parseurl (rel_url);
            }

          FreeVecPooled (pool, und->url);
        }

      FreeSPooled (pool, und, sizeof (struct URLNode));
    }
}

///

/// "tokencmp"

int
tokencmp (unsigned char *d, unsigned char *s)
{
  unsigned char c;

  while ((c = *s) == tolower (*d))
    {
      if (c == 0)
        return (0);

      ++s;
      ++d;
    }

  if ((c == 0) && is_space (*d))
    return (0);

  if (c < tolower (*d))
    return (-1);
  return (1);

}

int
asynctokencmp (struct AsyncFile *fin, unsigned char *s)
{
  LONG chr;
  unsigned char c;
  char d;
  // Search first '<'

  while ((chr = ReadCharAsync (fin)) != -1)
    {
      d = chr;

      if ((c = *s) == tolower ((unsigned char) d))
        {
          if (c == 0)
            return (1);

          ++s;
        }
      else if ((c == 0))
        {
          if (d == '>')
            {
              return (0);
            }
          else if (d == ' ' || d == '\t' || d == CR || d == LF)
            {
              while ((chr = ReadCharAsync (fin)) != -1)
                {
                  if (chr == '>')
                    return (0);
                  else if (chr == ' ' || chr == '\t' || chr == CR || chr == LF)
                    ;
                  else
                    return (1);
                }

              if (chr == -1)
                return (-1);
              else
                return (1);
            }
          else
            return (1);
        }
      else
        return (1);
    }


  return (-1);
}

///

/// "findcode"

char *
findcode (unsigned char *d, unsigned char *s, int len)
{
  while (*d)
    {
      if (tolower (*d) == *s)
        if (strnicmp (d, s, len) == 0)
          {
            d += len;

            while (is_space (*d))
              ++d;              //skip white spaces

            if (*d == '=')
              {
                d++;

                while (is_space (*d))
                  ++d;          //skip white spaces

                return (d);
              }
          }

      ++d;
    }

  return (NULL);
}

///

/// "addcodeurl"

BOOL
addcodeurl (struct scanhtml_data * sd, unsigned char *buf, unsigned char *item, int len)
{
  char *tmp, *url, t;

  if ((url = findcode (buf, item, len)))
    {
      if (*url == '\"')
        tmp = strchr (++url, t = '\"');
      else if (*url == '\'')
        tmp = strchr (++url, t = '\'');
      else
        {
          tmp = strpbrk (url, " \t");
          t = ' ';
        }

      if (tmp)
        *tmp = '\0';

      decode_html_string (url);

      add_url (sd, url, sd->abs_url);

      if (tmp)
        *tmp = t;

      return (TRUE);
    }

  return (FALSE);
}

BOOL
addcodeurl (struct scanhtml_data * sd, unsigned char *buf, unsigned char *item, int len, struct parseurl * abs_url)
{
  char *tmp, *url, t;

  if ((url = findcode (buf, item, len)))
    {
      if (*url == '\"')
        tmp = strchr (++url, t = '\"');
      else if (*url == '\'')
        tmp = strchr (++url, t = '\'');
      else
        {
          tmp = strpbrk (url, " \t");
          t = ' ';
        }

      if (tmp)
        *tmp = '\0';

      decode_html_string (url);

      if (!abs_url)
        abs_url = sd->abs_url;

      add_url (sd, url, abs_url);

      if (tmp)
        *tmp = t;

      return (TRUE);
    }

  return (FALSE);
}


///

/// "findurl"
BOOL
htmlfindurl (struct scanhtml_data * sd, char *buf, int bufsize)
{
  LONG chr;
  int count;

  // Search first '<'
  while ((chr = ReadCharAsync (sd->fin)) != -1)
    {
      if (chr == '<')
        {
          count = -1;

          while ((chr = ReadCharAsync (sd->fin)) != -1)
            {
              if (++count < bufsize)
                {
                  buf[count] = chr;

                  if (chr == '\"')
                    {
                      // ctrl if is = *SP "
                      char *tmp = buf + count - 1;

                      while (is_space (*tmp))
                        tmp--;

                      if (*tmp == '=')
                        {
                          while ((chr = ReadCharAsync (sd->fin)) != -1)
                            {
                              if (++count < bufsize)
                                {
                                  buf[count] = chr;

                                  if (chr == '\"')
                                    break;
                                }
                              else
                                {
                                  buf[count] = '\0';
                                  return (TRUE);
                                }
                            }

                          if (chr == -1)
                            return (FALSE);
                        }
                    }
                  else if (chr == '\'')
                    {
                      // ctrl if is = *SP "
                      char *tmp = buf + count - 1;

                      while (is_space (*tmp))
                        tmp--;

                      if (*tmp == '=')
                        {
                          while ((chr = ReadCharAsync (sd->fin)) != -1)
                            {
                              if (++count < bufsize)
                                {
                                  buf[count] = chr;

                                  if (chr == '\'')
                                    break;
                                }
                              else
                                {
                                  buf[count] = '\0';
                                  return (TRUE);
                                }
                            }

                          if (chr == -1)
                            return (FALSE);
                        }
                    }
                  else if (chr == '>')
                    {
                      buf[count] = '\0';

                      // I'd add comments... <!-- --  -- > -->

                      if (tokencmp (buf, "xmp") == 0)
                        {
                          //search </XMP>
                          while ((chr = ReadCharAsync (sd->fin)) != -1)
                            {
                              if (chr == '<')
                                {
                                  if ((chr = asynctokencmp (sd->fin, "/xmp")) == 0)
                                    break;
                                }
                            }

                          if (chr == -1)
                            return (FALSE);

                          break;
                        }
                      else if (tokencmp (buf, "listing") == 0)
                        {
                          while ((chr = ReadCharAsync (sd->fin)) != -1)
                            {
                              if (chr == '<')
                                {
                                  if ((chr = asynctokencmp (sd->fin, "/listing")) == 0)
                                    break;
                                }
                            }

                          if (chr == -1)
                            return (FALSE);

                          break;
                        }
                      else
                        return (TRUE);
                    }
                }
              else
                {
                  buf[count] = '\0';
                  return (FALSE);
                }
            }
        }
    }

  return (FALSE);
}

///

/// "struct SubTask *InitSubTask (void)"

struct SubTask *
InitSubTask (void)
{
  struct Task *me;
  struct SubTask *st;
  struct SubTaskMsg *stm;

  me = FindTask (NULL);

  /*
     ** Wait for our startup message from the SpawnSubTask() function.
   */

  WaitPort (&((struct Process *) me)->pr_MsgPort);
  stm = (struct SubTaskMsg *) GetMsg (&((struct Process *) me)->pr_MsgPort);
  st = (struct SubTask *) stm->stm_Parameter;

  if ((st->st_Port = CreateMsgPort ()))
    {
      /*
         ** Reply startup message, everything ok.
         ** Note that if the initialization fails, the code falls
         ** through and replies the startup message with a stm_Result
         ** of 0 after a Forbid(). This tells SpawnSubTask() that the
         ** sub task failed to run.
       */

      stm->stm_Result = TRUE;
      ReplyMsg ((struct Message *) stm);

      return (st);
    }
  else
    {
      if (st->st_Port)
        DeleteMsgPort (st->st_Port);

      Forbid ();
      stm->stm_Result = FALSE;
      ReplyMsg ((struct Message *) stm);

      return (NULL);
    }
}
///

/// "void GrabFunc(void) -- (START)"
int
main (int argc, char **argv)
{
  struct SubTask *st;
  struct ScanData *data;
  struct SubTaskMsg *stm;
  struct scanhtml_data sd;

  struct List *downlist;
  struct SignalSemaphore *lsema;
  struct ScanMessage *sn;

  char buf[1024 * 4];
  int bufsize = 1024 * 4;

  BYTE sig = 0;

  BOOL running = TRUE;

  char *tmp = NULL;
  BPTR old = NULL, dir;

  D (kprintf ("-- Init Decoding Subtask: %ld --\n", argc));

  memset (&sd, 0, sizeof (struct scanhtml_data));

  if ((st = InitSubTask ()))
    {
      data = (struct ScanData *) st->st_Data;

      SetProgramName ("GNG-HTML Decoder");

      lsema = &data->lsema;

      ObtainSemaphore (lsema);
      downlist = &data->scanlist;
      ReleaseSemaphore (lsema);

      NewList (&sd.linklist);
      InitSemaphore (&sd.sema);
      sd.abs_url = NULL;

      mem_sema = data->mem_sema;
      pool = data->pool;

      /*
         *** This set the right dir
       */

      if ((dir = Lock ("PROGDIR:", ACCESS_READ)))
        {
          UnLock (CurrentDir (dir));
        }

      for (;;)
        {
          ObtainSemaphore (lsema);
          sd.sn = sn = (struct ScanMessage *) RemHead (downlist);
          ReleaseSemaphore (lsema);

          while (sn)
            {
              /* Scan a file ? */
              if (sn->filename && (!sn->nd))
                {
                  if ((dir = Lock ("PROGDIR:", ACCESS_READ)))
                    {
                      UnLock (CurrentDir (dir));
                    }

                  sd.abs_url = NULL;
                  sd.abs_applet = NULL;
                  sd.abs_obj = NULL;

                  sd.htmlflags = ~0;    //ALL

                  sd.htmlflags = ~0;    //ALL

                }

              /* Scan an url node ? */
              else if (sn->nd)
                {
                  if (sn->nd->url)
                    sd.abs_url = parse_url (sn->nd->url);

                  sd.abs_applet = NULL;
                  sd.abs_obj = NULL;
                  sd.htmlflags = 0;
                  sd.htmlflags2 = 0;

                  if (sn->nd->htmlflags & HTML_HTML_20)
                    {
                      sd.htmlflags |= HTML_20_TAGS;
                      sd.htmlflags2 |= HTML_20_TAGS2;
                    }
                  else if (sn->nd->htmlflags & HTML_HTML_32)
                    {
                      sd.htmlflags |= HTML_32_TAGS | HTML_20_TAGS;
                      sd.htmlflags2 |= HTML_32_TAGS2 | HTML_20_TAGS2;
                    }
                  else if (sn->nd->htmlflags & HTML_HTML_40)
                    {
                      sd.htmlflags |= HTML_40_TAGS | HTML_32_TAGS | HTML_20_TAGS;
                      sd.htmlflags2 |= HTML_40_TAGS2 | HTML_32_TAGS2 | HTML_20_TAGS2;
                    }

                  if (sn->nd->htmlflags & HTML_HTML_IE)
                    {
                      sd.htmlflags |= HTML_IE_TAGS;
                      sd.htmlflags2 |= HTML_IE_TAGS2;
                    }

                  if (sn->nd->htmlflags & HTML_HTML_NS)
                    {
                      sd.htmlflags |= HTML_NS_TAGS;
                      sd.htmlflags2 |= HTML_NS_TAGS2;
                    }

                  if (sn->nd->htmlflags & HTML_HTML_OTHER)
                    {
                      sd.htmlflags |= HTML_OTHER_TAGS;
                      sd.htmlflags2 |= HTML_OTHER_TAGS2;
                    }

                  if (sn->nd->htmlflags & HTML_HTML_INIMG)
                    {
                      sd.htmlflags &= ~HTML_IMG_TAGS;
                      sd.htmlflags2 &= ~HTML_IMG_TAGS2;
                    }
                  if (sn->nd->htmlflags & HTML_HTML_INBACK)
                    {
                      sd.htmlflags &= ~HTML_BACK_TAGS;
                      sd.htmlflags2 &= ~HTML_BACK_TAGS2;
                    }
                  if (sn->nd->htmlflags & HTML_HTML_INAPPL)
                    {
                      sd.htmlflags &= ~HTML_APPLET_TAGS;
                      sd.htmlflags2 &= ~HTML_APPLET_TAGS2;
                    }
                  if (sn->nd->htmlflags & HTML_HTML_INOBJ)
                    {
                      sd.htmlflags &= ~HTML_OBJECT_TAGS;
                      sd.htmlflags2 &= ~HTML_OBJECT_TAGS2;
                    }

                  if (sd.abs_url)
                    {
                      {
                        data->pprefs = sn->pprefs;

                            /*ObtainSemaphore (&data->pprefs->sema);
                            dir = DupLock (data->pprefs->downdir);
                            ReleaseSemaphore (&data->pprefs->sema);

                            if (dir)
                              UnLock (CurrentDir (dir)); */
                      }

                      sn->filename = parseurl2file (sd.abs_url, sn->pprefs);
                    }
                }

              D (kprintf ("Decoding: parsing \"%s\"\n", sn->filename));

              //Now start scanning process
              // check if url or filename
              if (sn->filename)
                {
                  if ((sd.fin = OpenAsync (sn->filename, MODE_READ, 4096)))
                    {
                      char *url, *tmp, t;

                      while (htmlfindurl (&sd, buf, bufsize))
                        {
                          //D (kprintf ("find:\n--\n%s\n--\n\n", buf));

                          if (tokencmp (buf, "base") == 0)
                            {
                              if ((url = findcode (buf, "href", 4)))
                                {
                                  if (*url == '\"')
                                    tmp = strchr (++url, t = '\"');
                                  else if (*url == '\'')
                                    tmp = strchr (++url, t = '\'');
                                  else
                                    {
                                      tmp = strpbrk (url, " \t");
                                      t = ' ';
                                    }

                                  if (tmp)
                                    *tmp = '\0';

                                  decode_html_string (url);

                                  if (sd.abs_url)
                                    free_parseurl (sd.abs_url);

                                  sd.abs_url = parse_url (url);

                                  if (tmp)
                                    *tmp = t;
                                }
                            }
                          /* LINKS */
                          else if (tokencmp (buf, "a") == 0)
                            {
                              if (sd.htmlflags & HTML_A_HREF)
                                addcodeurl (&sd, buf, "href", 4);
                            }
                          else if (tokencmp (buf, "link") == 0)
                            {
                              if (sd.htmlflags & HTML_LINK_HREF)
                                addcodeurl (&sd, buf, "href", 4);
                            }

                          /* INLINED IMAGES OR OBJECTS */
                          else if (tokencmp (buf, "img") == 0)
                            {
                              if (sd.htmlflags & HTML_IMG_HREF)
                                addcodeurl (&sd, buf, "href", 4);

                              if (sd.htmlflags & HTML_IMG_SRC)
                                addcodeurl (&sd, buf, "src", 3);

                              if (sd.htmlflags & HTML_IMG_LONGDESC)
                                addcodeurl (&sd, buf, "longdesc", 8);

                              if (sd.htmlflags & HTML_IMG_LOWSRC)
                                addcodeurl (&sd, buf, "lowsrc", 6);

                              if (sd.htmlflags & HTML_IMG_DYNSRC)
                                addcodeurl (&sd, buf, "dynsrc", 6);

                            }
                          else if (tokencmp (buf, "body") == 0)
                            {
                              if (sd.htmlflags & HTML_BODY_BACKGROUND)
                                addcodeurl (&sd, buf, "background", 10);
                            }
                          else if (tokencmp (buf, "applet") == 0)
                            {
                              if ((url = findcode (buf, "codebase", 8)))
                                {
                                  if (*url == '\"')
                                    tmp = strchr (++url, t = '\"');
                                  else if (*url == '\'')
                                    tmp = strchr (++url, t = '\'');
                                  else
                                    {
                                      tmp = strpbrk (url, " \t");
                                      t = ' ';
                                    }

                                  if (tmp)
                                    *tmp = '\0';

                                  decode_html_string (url);

                                  if (sd.abs_applet)
                                    free_parseurl (sd.abs_applet);

                                  sd.abs_applet = parse_url (url);

                                  if (tmp)
                                    *tmp = t;
                                }


                              if (sd.htmlflags & HTML_APPLET_CODE)
                                addcodeurl (&sd, buf, "code", 4, sd.abs_applet);

                              if (sd.htmlflags & HTML_APPLET_OBJECT)
                                addcodeurl (&sd, buf, "object", 6, sd.abs_applet);

                              if (sd.htmlflags & HTML_APPLET_ARCHIVE)
                                addcodeurl (&sd, buf, "archive", 7, sd.abs_applet);

                              if (sd.htmlflags & HTML_APPLET_SRC)
                                addcodeurl (&sd, buf, "src", 3, sd.abs_applet);
                            }
                          else if (tokencmp (buf, "object") == 0)
                            {
                              if ((url = findcode (buf, "codebase", 8)))
                                {
                                  if (*url == '\"')
                                    tmp = strchr (++url, t = '\"');
                                  else if (*url == '\'')
                                    tmp = strchr (++url, t = '\'');
                                  else
                                    {
                                      tmp = strpbrk (url, " \t");
                                      t = ' ';
                                    }

                                  if (tmp)
                                    *tmp = '\0';

                                  decode_html_string (url);

                                  if (sd.abs_obj)
                                    free_parseurl (sd.abs_obj);

                                  sd.abs_obj = parse_url (url);

                                  if (tmp)
                                    *tmp = t;
                                }

                              if (sd.htmlflags & HTML_OBJECT_DATA)
                                addcodeurl (&sd, buf, "data", 4, sd.abs_obj);

                              if (sd.htmlflags & HTML_OBJECT_CLASSID)
                                addcodeurl (&sd, buf, "classid", 7, sd.abs_obj);

                              if (sd.htmlflags & HTML_OBJECT_ARCHIVE)
                                addcodeurl (&sd, buf, "archive", 7, sd.abs_obj);

                              if (sd.htmlflags & HTML_OBJECT_CODE)
                                addcodeurl (&sd, buf, "code", 4, sd.abs_obj);

                              // with type (HTML 4.0, IE) filter MIME type
                              // with codetype (HTML 4.0, IE) filter MIME type
                            }
                          else if (tokencmp (buf, "embed") == 0)
                            {
                              if (sd.htmlflags & HTML_EMBED_SRC)
                                addcodeurl (&sd, buf, "src", 3);

                              if (sd.htmlflags & HTML_EMBED_PLUGINPAGE)
                                addcodeurl (&sd, buf, "pluginpage", 10);

                              if (sd.htmlflags & HTML_EMBED_PLUGINURL)
                                addcodeurl (&sd, buf, "pluginurl", 10);

                              // with type (netscape) filter MIME type
                            }
                          /* FRAMES */
                          else if (tokencmp (buf, "frame") == 0)
                            {
                              if (sd.htmlflags & HTML_FRAME_SRC)
                                addcodeurl (&sd, buf, "src", 3);

                              if (sd.htmlflags & HTML_FRAME_LONGDESC)
                                addcodeurl (&sd, buf, "longdesc", 8);
                            }
                          else if (tokencmp (buf, "iframe") == 0)
                            {
                              if (sd.htmlflags & HTML_IFRAME_SRC)
                                addcodeurl (&sd, buf, "src", 3);

                              if (sd.htmlflags & HTML_IFRAME_LONGDESC)
                                addcodeurl (&sd, buf, "longdesc", 8);
                            }

                          /* LAYERS - Netscape extension */
                          else if (tokencmp (buf, "layer") == 0)
                            {
                              if (sd.htmlflags & HTML_LAYER_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                              if (sd.htmlflags & HTML_LAYER_BACKGROUND)
                                addcodeurl (&sd, buf, "background", 10);
                            }
                          else if (tokencmp (buf, "ilayer") == 0)
                            {
                              if (sd.htmlflags & HTML_ILAYER_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                              if (sd.htmlflags & HTML_ILAYER_BACKGROUND)
                                addcodeurl (&sd, buf, "background", 10);
                            }

                          /* FORM */
                          else if (tokencmp (buf, "input") == 0)
                            {
                              if (sd.htmlflags & HTML_INPUT_SRC)
                                addcodeurl (&sd, buf, "src", 3);

                              if (sd.htmlflags & HTML_INPUT_DYNSRC)
                                addcodeurl (&sd, buf, "dynsrc", 6);

                              if (sd.htmlflags & HTML_INPUT_LOWSRC)
                                addcodeurl (&sd, buf, "lowsrc", 6);

                            }
                          /* SCRIPTS */
                          else if (tokencmp (buf, "script") == 0)
                            {
                              if (sd.htmlflags & HTML_SCRIPT_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                              // i'd check type
                            }
                          /* TABLE - IE */
                          else if (tokencmp (buf, "table") == 0)
                            {
                              if (sd.htmlflags2 & HTML_TABLE_BACKGROUND)
                                addcodeurl (&sd, buf, "background", 10);
                            }

                          /* MAP */
                          else if (tokencmp (buf, "area") == 0)
                            {
                              if (sd.htmlflags2 & HTML_AREA_HREF)
                                addcodeurl (&sd, buf, "href", 4);
                            }

                          /* OTHER... ?? */
                          else if (tokencmp (buf, "fig") == 0)
                            {
                              if (sd.htmlflags2 & HTML_FIG_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                            }
                          else if (tokencmp (buf, "overlay") == 0)
                            {
                              if (sd.htmlflags2 & HTML_OVERLAY_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                            }
                          else if (tokencmp (buf, "bgsound") == 0)
                            {
                              if (sd.htmlflags2 & HTML_BGSOUND_SRC)
                                addcodeurl (&sd, buf, "src", 3);
                            }

                          /* CITAZIONI - HTML 4.0 */
                          else if (tokencmp (buf, "blockquote") == 0)
                            {
                              if (sd.htmlflags2 & HTML_BLOCKQUOTE_CITE)
                                addcodeurl (&sd, buf, "cite", 4);
                            }
                          else if (tokencmp (buf, "q") == 0)
                            {
                              if (sd.htmlflags2 & HTML_Q_CITE)
                                addcodeurl (&sd, buf, "cite", 4);
                            }
                          else if (tokencmp (buf, "del") == 0)
                            {
                              if (sd.htmlflags2 & HTML_DEL_CITE)
                                addcodeurl (&sd, buf, "cite", 4);
                            }
                          else if (tokencmp (buf, "ins") == 0)
                            {
                              if (sd.htmlflags2 & HTML_INS_CITE)
                                addcodeurl (&sd, buf, "cite", 4);
                            }
                        }

                      if (sd.abs_url)
                        {
                          free_parseurl (sd.abs_url);
                          sd.abs_url = NULL;
                        }

                      if (sd.abs_applet)
                        {
                          free_parseurl (sd.abs_applet);
                          sd.abs_applet = NULL;
                        }

                      if (sd.abs_obj)
                        {
                          free_parseurl (sd.abs_obj);
                          sd.abs_obj = NULL;
                        }

                      // End of scanning process
                      // Send list to add to project...

                      ObtainSemaphore (data->sema);
                      if (data->app)
                        {
                          ReleaseSemaphore (data->sema);
                          DoPortAMethod (st->st_Reply, st->st_Port, sn->proj, 3,
                          MUIM_ProjWin_AddListNode, &sd.linklist, &sd.sema);
                        }
                      else
                        {       // End... Shut Down!

                          ReleaseSemaphore (data->sema);

                          struct ScanMessage *tsn;

                          ObtainSemaphore (lsema);
                          tsn = (struct ScanMessage *) RemHead (downlist);
                          ReleaseSemaphore (lsema);

                          while (tsn)
                            {
                              if (tsn->filename)
                                FreeVecPooled (pool, tsn->filename);
                              FreeSPooled (pool, tsn, sizeof (struct ScanMessage));

                              ObtainSemaphore (lsema);
                              tsn = (struct ScanMessage *) RemHead (downlist);
                              ReleaseSemaphore (lsema);
                            }
                        }

                      CloseAsync (sd.fin);
                    }
                  else
                    D (kprintf ("Decoding: Error opening file %s\n", sn->filename));

                  FreeVecPooled (pool, sn->filename);
                }
              else
                D (kprintf ("Decoding: Error making filepath\n"));

              FreeSPooled (pool, sn, sizeof (struct ScanMessage));

              ObtainSemaphore (lsema);
              sd.sn = sn = (struct ScanMessage *) RemHead (downlist);
              ReleaseSemaphore (lsema);

            }                   // end while (sn)

          if (sn == NULL)
            {
              ULONG sigs;

              sigs = Wait (SIGBREAKF_CTRL_C | (1 << st->st_Port->mp_SigBit));

              if (sigs & (1 << st->st_Port->mp_SigBit))
                {

                  while ((stm = (struct SubTaskMsg *) GetMsg (st->st_Port)))
                    {
                      switch (stm->stm_Command)
                        {
                        case STC_SHUTDOWN:
                          running = FALSE;
                          break;

                        case STC_STARTUP:
                          break;

                        case STC_SCANHTML:
                          break;
                        }

                      /*
                         ** If we received a shutdown message, we do not reply it
                         ** immediately. First, we need to free our resources.
                       */
                      if (!running)
                        break;

                      ReplyMsg ((struct Message *) stm);
                    }

                  if (!running)
                    break;
                }
            }
        }                       // end for(;;)

      if (st->st_Port)
        DeleteMsgPort (st->st_Port);

      Forbid ();

      if (stm)
        {
          stm->stm_Result = FALSE;
          ReplyMsg ((struct Message *) stm);
        }
    }


  return (NULL);
}
///

