/********************************************************
 * File: scan.c
 * Created at Sun Jan 28 22:10:32 MSK 2001 by raorn // raorn@binec.ru
 * SCAN
 * $Id: scan.c,v 1.9 2002/02/04 22:13:30 raorn Exp $
 *******************************************************/
#include "crashecho.h"

void LogScanResults(void)
{
  printf("\n");

  if (scan_total == 0)
    LogWrite(2, TOSSINGINFO, "No messages exported");
  else if (scan_total == 1)
    LogWrite(2, TOSSINGINFO, "1 message exported");
  else {
    LogWrite(2, TOSSINGINFO, "%lu messages exported", scan_total);
  }
}

bool ScanHandle(struct MemMessage *mm)
{
  uchar buf[50];
  ulong oldattr;

  if (mm->Area[0] == 0) {
    Print4D(&mm->DestNode, buf, 50);

    LogWrite(4, TOSSINGINFO, "Exporting message #%lu from \"%s\" to \"%s\" at %s", mm->msgnum, mm->From, mm->To, buf);
  } else {
    LogWrite(4, TOSSINGINFO, "Exporting message #%lu from \"%s\" to \"%s\" in %s", mm->msgnum, mm->From, mm->To, mm->Area);
  }

  if (config.cfg_Flags & CFG_ADDTID)
    AddTID(mm);

  oldattr = mm->Attr;

  if (HandleMessage(mm, FALSE)) {
    scan_total++;

    mm->Attr = oldattr;
    mm->Changed = TRUE;

    if (mm->Area[0] == 0) {
      if ((config.cfg_Flags & CFG_ALLOWKILLSENT) && (mm->Attr & FLAG_KILLSENT)) {
        LogWrite(2, TOSSINGINFO, "Deleting message with KILLSENT flag");
        mm->Deleted = TRUE;
      } else {
        mm->Attr |= FLAG_SENT;
      }
    } else {
      mm->Attr |= FLAG_SENT;
    }

    return TRUE;
  }

  return FALSE;
}

bool ScanArea(uchar * tagname)
{
  struct Area *area;

  for (area = (struct Area *) config.AreaList.First; area; area = area->Next)
    if (stricmp(area->Tagname, tagname) == 0)
      break;

  if (area) {
    if (area->AreaType != AREATYPE_ECHOMAIL && area->AreaType != AREATYPE_NETMAIL) {
      LogWrite(1, USERERR, "You cannot scan area %s, not an echomail or netmail area", tagname);
    } else if (!area->Messagebase) {
      LogWrite(1, USERERR, "You cannot scan area %s, area is pass-through", tagname);
    } else if (!area->Messagebase->scanfunc) {
      LogWrite(1, USERERR, "You cannot scan area %s, scanning is not supported for this type of messagebase", tagname);
    } else {
      printf("Scanning area %s\n", area->Tagname);
      return (*area->Messagebase->scanfunc) (area, TRUE, FALSE, 0, NULL, AcceptNotSent, ScanHandle);
    }
  } else {
    LogWrite(1, USERERR, "Unknown area %s", tagname);
  }

  return TRUE;
}

#ifdef MSGBASE_JAM
static bool AddJamToList(struct jbList *scanlist, uchar *file)
{
  ulong jbcpos;
  struct Area *area;
  struct ScanEntry *tmpscan;
  struct MsgEntry *tmpmsg;
  uchar base[200], buf[200], buf2[200];
  ulong msgnum;
  FILE *fh;

  if ((fh=fopen(file, "rt")) != NULL) {
    while (fgets(buf2, 200, fh)) {
      jbcpos = 0;

      if(!(jbstrcpy(base, buf2, 200, &jbcpos)))
        /* Skip invalid line */
        continue;

      if(!(jbstrcpy(buf, buf2, 200, &jbcpos)))
        /* Skip invalid line */
        continue;

      msgnum = atoi(buf);

      for (area = (struct Area *) config.AreaList.First; area; area = area->Next)
        if (!stricmp(base, area->Path))
          break;

      if (area) {
        for (tmpscan = (struct ScanEntry *) scanlist->First; tmpscan; tmpscan = tmpscan->Next)
          if (tmpscan->area == area)
            break;

        if (!tmpscan) {
          if ((tmpscan = calloc(1, sizeof(struct ScanEntry))) == NULL) {
            nomem = TRUE;
            return FALSE;
          }

          tmpscan->area = area;
          jbNewList(&tmpscan->msglist);

          jbAddNode(scanlist, (struct jbNode *) tmpscan);
        }

        if ((tmpmsg = calloc(1, sizeof(struct MsgEntry))) == NULL) {
          nomem = TRUE;
          return FALSE;
        }

        tmpmsg->num = msgnum;

        jbAddNode(&tmpscan->msglist, (struct jbNode *) tmpmsg);
      }
    }

    fclose(fh);
  }

  return TRUE;
}

static bool ScanJAMFile(uchar *file)
{
  struct jbList scanlist;
  struct ScanEntry *tmpscan;

  jbNewList(&scanlist);

  if(!AddJamToList(&scanlist, file)) {
    for (tmpscan = (struct ScanEntry *) scanlist.First; tmpscan; tmpscan = tmpscan->Next)
      jbFreeList(&tmpscan->msglist);

    jbFreeList(&scanlist);
    return FALSE;
  }

  for (tmpscan = (struct ScanEntry *) scanlist.First; tmpscan; tmpscan = tmpscan->Next) {
    if (tmpscan->area->Messagebase && (tmpscan->area->AreaType == AREATYPE_ECHOMAIL || tmpscan->area->AreaType == AREATYPE_NETMAIL)) {
      if (tmpscan->area->Messagebase->scanfunc) {
        printf("Scanning area %s\n", tmpscan->area->Tagname);

        if (!(*tmpscan->area->Messagebase->scanfunc) (tmpscan->area, TRUE, FALSE, 0, (struct jbList *) &tmpscan->msglist, AcceptNotSent, ScanHandle)) {
          /* FIXME Previous elements already freed */
          for (; tmpscan; tmpscan = tmpscan->Next)
            jbFreeList(&tmpscan->msglist);

          jbFreeList(&scanlist);
          return FALSE;
        }
      }
    }

    jbFreeList(&tmpscan->msglist);
  }

  jbFreeList(&scanlist);
  return TRUE;
}
#endif

bool Scan(bool ignoreflags)
{
  struct Area *area;

  LogWrite(2, ACTIONINFO, "Scanning areas for messages to export");

#ifdef MSGBASE_JAM
  if (ignoreflags) {
#endif
    for (area = (struct Area *) config.AreaList.First; area; area = area->Next)
      if (area->Messagebase && (area->AreaType == AREATYPE_ECHOMAIL || area->AreaType == AREATYPE_NETMAIL)) {
        if (area->Messagebase->scanfunc) {
          printf("Scanning area %s\n", area->Tagname);

          if (!(*area->Messagebase->scanfunc) (area, TRUE, FALSE, 0, NULL, AcceptNotSent, ScanHandle)) {
            return (FALSE);
          }
        }
      }
#ifdef MSGBASE_JAM
  } else {
    uchar buf[200];
    bool existsany = FALSE;
    bool existsthis;

    /* FIXME ``netmail.jam'' looks ugly... Should we define it's name in config? */
    MakeFullPath(config.cfg_jam_FlagsDir, "netmail.jam", buf, 200);
    if ((existsthis = Exists(buf))) {
      if (!ScanJAMFile(buf)) {
        return FALSE;
      }
      /* FIXME Hmm... */
      unlink(buf);
    }
    existsany = existsany || existsthis;

    /* FIXME ``echomail.jam'' looks ugly... Should we define it's name in config? */
    MakeFullPath(config.cfg_jam_FlagsDir, "echomail.jam", buf, 200);
    if ((existsthis = Exists(buf))) {
      if (!ScanJAMFile(buf)) {
        return FALSE;
      }
      /* FIXME Hmm... */
      unlink(buf);
    }
    existsany = existsany || existsthis;

    if (!existsany) {
      /* Process all areas... */
      for (area = (struct Area *) config.AreaList.First; area; area = area->Next)
        if (area->Messagebase && (area->AreaType == AREATYPE_ECHOMAIL || area->AreaType == AREATYPE_NETMAIL)) {
          if (area->Messagebase->scanfunc) {
            printf("Scanning area %s\n", area->Tagname);

            if (!(*area->Messagebase->scanfunc) (area, TRUE, FALSE, 0, NULL, AcceptNotSent, ScanHandle)) {
              return (FALSE);
            }
          }
        }
    } else {
      /* Process all other (MSG) areas... */
      for (area = (struct Area *) config.AreaList.First; area; area = area->Next)
        if (area->Messagebase && stricmp(area->Messagebase->name, "JAM") && (area->AreaType == AREATYPE_ECHOMAIL || area->AreaType == AREATYPE_NETMAIL)) {
          if (area->Messagebase->scanfunc) {
            printf("Scanning area %s\n", area->Tagname);

            if (!(*area->Messagebase->scanfunc) (area, TRUE, FALSE, 0, NULL, AcceptNotSent, ScanHandle)) {
              return (FALSE);
            }
          }
        }
    }
  }
#endif

  return (TRUE);
}

bool ScanList(uchar * file)
{
  FILE *fh;
  uchar buf[100];

  if (!(fh = fopen(file, "rt"))) {
    LogWrite(1, USERERR, "Unable to open %s", file);
    return (FALSE);
  }

  while (fgets(buf, 100, fh)) {
    if (strlen(buf) > 2) {
      if (buf[strlen(buf) - 1] < 32)
        buf[strlen(buf) - 1] = 0;

      if (!ScanArea(buf)) {
        fclose(fh);
        return (FALSE);
      }
    }
  }

  fclose(fh);

  return (TRUE);
}


syntax highlighted by Code2HTML, v. 0.9.1