/********************************************************
 * File: misc.c
 * Created at Sun Jan 28 22:10:31 MSK 2001 by raorn // raorn@binec.ru
 *
 * $Id: misc.c,v 1.14 2002/10/27 22:53:11 raorn Exp $
 *******************************************************/
#include "crashecho.h"

void ExpandPacker(uchar * cmd, uchar * dest, ulong destsize, uchar * arc, uchar * file)
{
  ulong c, d;

  d = 0;
  for (c = 0; c < strlen(cmd); c++) {
    if (cmd[c] == '%' && (cmd[c + 1] | 32) == 'a') {
      strncpy(&dest[d], arc, (size_t) (destsize - 1 - d));
      dest[destsize - 1] = 0;
      d = strlen(dest);
      c++;
    } else if (cmd[c] == '%' && (cmd[c + 1] | 32) == 'f') {
      strncpy(&dest[d], file, (size_t) (destsize - 1 - d));
      dest[destsize - 1] = 0;
      d = strlen(dest);
      c++;
    } else if (cmd[c] == '%' && cmd[c + 1] != 0) {
      dest[d++] = cmd[c + 1];
      c++;
    } else
      dest[d++] = cmd[c];
  }
  dest[d] = 0;
}

int DateCompareFE(const void *f1, const void *f2)
{
  if ((*(struct FileEntry **) f1)->Date > (*(struct FileEntry **) f2)->Date)
    return (1);

  if ((*(struct FileEntry **) f1)->Date < (*(struct FileEntry **) f2)->Date)
    return (-1);

  /* Compares by filenames to get packet files
     with the same date in the right order */
  return stricmp((*(struct FileEntry **) f1)->Name, (*(struct FileEntry **) f2)->Name);
}

bool SortFEList(struct jbList *list)
{
  struct FileEntry *ftt, **buf, **work;
  ulong nodecount = 0;

  for (ftt = (struct FileEntry *) list->First; ftt; ftt = ftt->Next)
    nodecount++;

  if (!nodecount)
    return (TRUE);

  if (!(buf = (struct FileEntry **) malloc(nodecount * sizeof(struct FileEntry *)))) {
    nomem = TRUE;
    return (FALSE);
  }

  work = buf;

  for (ftt = (struct FileEntry *) list->First; ftt; ftt = ftt->Next)
    *work++ = ftt;

  qsort(buf, (size_t) nodecount, (size_t) sizeof(struct FileEntry *), DateCompareFE);

  jbNewList(list);

  for (work = buf; nodecount--;)
    jbAddNode(list, (struct jbNode *) *work++);

  free(buf);

  return (TRUE);
}

bool IsArc(uchar * file)
{
  int c;
  uchar ext[4];

  if (strlen(file) != 12)
    return (FALSE);
  if (file[8] != '.')
    return (FALSE);

  for (c = 0; c < 8; c++)
    if ((file[c] < '0' || file[c] > '9') && ((tolower(file[c]) < 'a') || (tolower(file[c]) > 'z')))
      return (FALSE);

  strncpy(ext, &file[9], 2);
  ext[2] = 0;

  if (stricmp(ext, "MO") == 0)
    return (TRUE);
  if (stricmp(ext, "TU") == 0)
    return (TRUE);
  if (stricmp(ext, "WE") == 0)
    return (TRUE);
  if (stricmp(ext, "TH") == 0)
    return (TRUE);
  if (stricmp(ext, "FR") == 0)
    return (TRUE);
  if (stricmp(ext, "SA") == 0)
    return (TRUE);
  if (stricmp(ext, "SU") == 0)
    return (TRUE);

  return (FALSE);
}

bool IsPkt(uchar * file)
{
  if (strlen(file) != 12)
    return (FALSE);
  if (file[8] != '.')
    return (FALSE);
  if (stricmp(&file[9], "pkt") != 0)
    return (FALSE);

  return (TRUE);
}

bool IsNewPkt(uchar * file)
{
  if (strlen(file) < 7)
    return (FALSE);

  if (stricmp(&file[strlen(file) - 7], ".newpkt") != 0)
    return (FALSE);

  return (TRUE);
}

bool IsPktTmp(uchar * file)
{
  if (strlen(file) < 7)
    return (FALSE);

  if (stricmp(&file[strlen(file) - 7], ".pkttmp") != 0)
    return (FALSE);

  return (TRUE);
}

bool IsOrphan(uchar * file)
{
  if (strlen(file) < 7)
    return (FALSE);

  if (stricmp(&file[strlen(file) - 7], ".orphan") != 0)
    return (FALSE);

  return (TRUE);
}

bool IsBad(uchar * file)
{
  if (strlen(file) > 4 && stricmp(&file[strlen(file) - 4], ".bad") == 0)
    return (TRUE);

  return (FALSE);
}

void striptrail(uchar * str)
{
  int c;

  for (c = strlen(str) - 1; str[c] < 33 && c >= 0; c--)
    str[c] = 0;
}


void striplead(uchar * str)
{
  int c;

  c = 0;

  while (str[c] == ' ')
    c++;

  strcpy(str, &str[c]);
}

void stripleadtrail(uchar * str)
{
  striplead(str);
  striptrail(str);
}

void BadFile(uchar * filename)
{
  uchar destname[200], numbuf[10];
  ulong num;

  LogWrite(3, TOSSINGERR, "Renaming %s to .bad", filename);

  num = 0;

  do {
    mystrncpy(destname, filename, 180);
    strcat(destname, ".bad");

    if (num != 0) {
      snprintf(numbuf, 10, ",%ld", num);
      strcat(destname, numbuf);
    }

    num++;
  } while (Exists(destname));

  if (!movefile(filename, destname)) {
    LogWrite(1, SYSTEMERR, "Failed to move %s to %s", filename, destname);
    LogWrite(1, SYSTEMERR, "Error: %s", strerror(errno));
    return;
  }
}

bool MatchFlags(uchar group, uchar * node)
{
  uchar c;

  for (c = 0; c < strlen(node); c++) {
    if (group == node[c])
      return (TRUE);
  }

  return (FALSE);
}

bool AddTID(struct MemMessage * mm)
{
  uchar buf[100];

  strcpy(buf, "\001TID: CrashEcho " VERSION "\015");

  return mmAddLine(mm, buf, MM_KLUDGE);
}

void MakeFidoDate(time_t tim, uchar * dest)
{
  struct tm *tp;
  time_t t;
  uchar *monthnames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };

  t = tim;
  tp = localtime(&t);

  snprintf(dest, 20, "%02d %s %02d  %02d:%02d:%02d", tp->tm_mday, monthnames[tp->tm_mon], tp->tm_year % 100, tp->tm_hour, tp->tm_min, tp->tm_sec);
}

#define COPYBUFSIZE 5000

bool copyfile(uchar * file, uchar * newfile)
{
  FILE *ifh, *ofh;
  ulong len;
  uchar *copybuf;

  if (!(copybuf = (uchar *) malloc(COPYBUFSIZE))) {
    nomem = TRUE;
    return (FALSE);
  }

  if (!(ifh = fopen(file, "rb"))) {
    free(copybuf);
    return (FALSE);
  }

  if (!(ofh = fopen(newfile, "wb"))) {
    free(copybuf);
    fclose(ifh);
    return (FALSE);
  }

  while ((len = fread(copybuf, 1, COPYBUFSIZE, ifh))) {
    if (fwrite(copybuf, 1, len, ofh) != len) {
      ioerror = TRUE;
      ioerrornum = errno;
    }
  }

  free(copybuf);

  fclose(ofh);
  fclose(ifh);

  if (ioerror) {
    unlink(newfile);
    return (FALSE);
  }

  return (TRUE);
}

bool movefile(uchar * file, uchar * newfile)
{
  if (!rename(file, newfile))
    return (TRUE);              /* rename was enough */

  if (!copyfile(file, newfile))
    return (FALSE);

  unlink(file);
  return (TRUE);
}

bool MakeNetmailKludges(struct MemMessage * mm)
{
  uchar buf[100];

  if (mm->OrigNode.Zone != mm->DestNode.Zone || (config.cfg_Flags & CFG_FORCEINTL)) {
    snprintf(buf, 100, "\001INTL %u:%u/%u %u:%u/%u\015", mm->DestNode.Zone,
            mm->DestNode.Net, mm->DestNode.Node, mm->OrigNode.Zone,
            mm->OrigNode.Net, mm->OrigNode.Node);

    mmAddBuf(&mm->TextChunks, buf, strlen(buf), MM_HEAD);
  }
  if (mm->DestNode.Point) {
    snprintf(buf, 100, "\001TOPT %u\015", mm->DestNode.Point);
    mmAddBuf(&mm->TextChunks, buf, strlen(buf), MM_HEAD);
  }
  if (mm->OrigNode.Point) {
    snprintf(buf, 100, "\001FMPT %u\015", mm->OrigNode.Point);
    mmAddBuf(&mm->TextChunks, buf, strlen(buf), MM_HEAD);
  }

  return (TRUE);
}

/*************************************
 *
 * Fido DateTime conversion routines 
 *
 *************************************/

time_t FidoToTime(uchar * date)
{
  ulong month;
  struct tm tm;
  time_t t;

  static char *mo[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

  if (date[2] == ' ' && date[6] == ' ') {
    /* Standard Fido                "01 Jan 91  11:22:33" */

    /* Get month */

    for (month = 0; month < 12; month++)
      if (strnicmp(mo[month], &date[3], 3) == 0)
        break;

    if (month == 12)
      return time(NULL);        /* return current time */

    tm.tm_sec = atoi(&date[17]);
    tm.tm_min = atoi(&date[14]);
    tm.tm_hour = atoi(&date[11]);
    tm.tm_mday = atoi(date);
    tm.tm_mon = month;
    tm.tm_year = atoi(&date[7]);
    tm.tm_wday = 0;
    tm.tm_yday = 0;
    tm.tm_isdst = -1;

    if (tm.tm_year < 80)        /* Y2K fix */
      tm.tm_year += 100;
  } else {
    /* SEAdog "Wed 13 Jan 86 02:34" */
    /* SEAdog "Wed  3 Jan 86 02:34" */

    /* Get month */

    for (month = 0; month < 12; month++)
      if (strnicmp(mo[month], &date[7], 3) == 0)
        break;

    if (month == 12)
      return time(NULL);        /* return current time */

    tm.tm_sec = 0;
    tm.tm_min = atoi(&date[17]);
    tm.tm_hour = atoi(&date[14]);
    tm.tm_mday = atoi(&date[4]);
    tm.tm_mon = month;
    tm.tm_year = atoi(&date[11]);
    tm.tm_wday = 0;
    tm.tm_yday = 0;
    tm.tm_isdst = -1;

    if (tm.tm_year < 80)        /* Y2K fix */
      tm.tm_year += 100;
  }

  t = mktime(&tm);

  if (t == -1)
    t = time(NULL);

  return (t);
}

bool Parse5D(uchar * buf, struct Node4D * n4d, uchar * domain)
{
  ulong c = 0;
  uchar buf2[100];

  domain[0] = 0;

  mystrncpy(buf2, buf, 100);

  for (c = 0; c < strlen(buf2); c++)
    if (buf2[c] == '@')
      break;

  if (buf2[c] == '@') {
    buf2[c] = 0;
    mystrncpy(domain, &buf2[c + 1], 20);
  }

  return Parse4D(buf2, n4d);
}

bool ExtractAddress(uchar * origin, struct Node4D * n4d, uchar * domain)
{
  ulong pos, e;
  uchar addr[50];

  pos = strlen(origin);

  while (pos > 0 && origin[pos] != '(')
    /* Find address */
    pos--;

  if (origin[pos] != '(')
    return (FALSE);

  pos++;

  while (origin[pos] != 13 && (origin[pos] < '0' || origin[pos] > '9'))
    /* Skip (FidoNet ... ) */
    pos++;

  e = 0;

  while (origin[pos] != ')' && e < 49)
    addr[e++] = origin[pos++];

  addr[e] = 0;

  return Parse5D(addr, n4d, domain);
}


unsigned long hextodec(char *hex)
{
  char *hextab = "0123456789abcdef";
  int c = 0, c2 = 0;
  unsigned long result = 0;

  for (;;) {
    for (c2 = 0; c2 < 16; c2++)
      if (tolower(hex[c]) == hextab[c2])
        break;

    if (c2 == 16)
      /* End of correct hex number */
      return (result);

    result *= 16;
    result += c2;

    c++;
  }
}

/*struct Area *FindAreaByName(uchar* areaname)
{
  struct Area *area;

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

  return area;
}*/

/*struct Area *FindAreaByPath(uchar* path)
{
  struct Area *area;

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

  return area;
}*/


syntax highlighted by Code2HTML, v. 0.9.1