/*
** $Log$
*/

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

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

#include <rexx/rxslib.h>
#include <rexx/rexxio.h>
#include <rexx/errors.h>

#include <dos/dos.h>
#include <exec/memory.h>
#include <utility/tagitem.h>

#include "get_folder_path.h"

int __stack = 12000;

struct NewsNode
{
    struct NewsNode *next;
    struct NewsNode *prev;
    struct List *domains;
    char *ngname;
    char *path;
    long last;
    long maxlen;
    long maxmsg;
    char folder[40];
    char update;
};

#ifndef __GNUC__
struct Library        *RexxSysBase = NULL;
#else
struct RxsLib         *RexxSysBase = NULL;
#endif

struct List *newsgroupslist=0;
struct List   *folders;

void        *listpool=0;

char buf[1000];

char *stristr(char *buf, char *str)
{
    register int len = strlen(buf);
    register int len2 = strlen(str);
    register int a;

    for(a = 0; a <= len - len2; a++)
        if(strnicmp(&buf[a], str, len2) == 0)
            return(&buf[a]);
    return(0);
}

int LoadConfig(void)
{
    BPTR fh;
    char *tmp;

    fh=Open("YAM:Yam2NN.config", MODE_OLDFILE);

    while(FGets(fh, buf, 200))
    {
        if(strlen(buf) < 2)
            break;

        if(buf[0] == ';')
            continue;

        if(!(strnicmp(buf, "Newsgroups:", 11)))
        {
            struct NewsNode *newsnode;

            if(!newsgroupslist)
            {
                newsgroupslist = LibAllocPooled(listpool, sizeof(struct List));
                NewList(newsgroupslist);
            }

            newsnode = LibAllocPooled(listpool, sizeof(struct NewsNode));

            newsnode->domains = LibAllocPooled(listpool, sizeof(struct List));
            NewList(newsnode->domains);
            newsnode->update = FALSE;

            tmp=strtok(buf + 12, " ");
            newsnode->ngname = LibAllocPooled(listpool, strlen(tmp) + 1);
            strcpy(newsnode->ngname, tmp);

            tmp=strtok(NULL, " \n");
            if(!tmp)
                return(FALSE);

            newsnode->path = LibAllocPooled(listpool, strlen(tmp)+  1);
            strcpy(newsnode->path, tmp);

            {
                int a, b;

                a = strlen(tmp);
                if(tmp[a - 1] == '/')
                    tmp[a - 1] = 0;
                while(tmp[a] != '/' && tmp[a] != ':' && a > 0)
                    a--;

                strcpy(newsnode->folder, &tmp[a + 1]);
            }

            FGets(fh, buf, 200);
            newsnode->maxlen = atol(&buf[13]);

            FGets(fh, buf, 200);
            newsnode->maxmsg = atol(&buf[15]);

            while(1)
            {
                struct Node *node;

                if(!(FGets(fh, buf, 200)))
                    break;

                if(strnicmp(buf, "\n", 1)==0)
                    break;
            }

            AddTail(newsgroupslist, newsnode);
        }
    }
    Close(fh);
    return(TRUE);
}

// this function was written by Christian Hattemer <Chris@heaven.riednet.wh.tu-darmstadt.de>

long SendRexxCommand(char *Port, char *Cmd, struct MsgPort *ReplyPort, char *Result)
{
   ULONG Error;
   struct MsgPort *RexxPort;

   Forbid();

   if (RexxPort = FindPort(Port))
   {
      struct RexxMsg *rexxMsg, *Answer;

      if (rexxMsg = CreateRexxMsg(ReplyPort, NULL, NULL))
      {
         if (rexxMsg->rm_Args[0] = CreateArgstring(Cmd, strlen(Cmd)))
         {
            rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;

            PutMsg(RexxPort, &rexxMsg->rm_Node);

            do
            {
               WaitPort(ReplyPort);
               Answer = (struct RexxMsg *)GetMsg(ReplyPort);
            } while (Answer == NULL);

            Permit();

            if ((Error = Answer->rm_Result1) == RC_OK)
            {
               if (Answer->rm_Result2)
               {
                  strcpy(Result, (STRPTR)Answer->rm_Result2);
                  DeleteArgstring((UBYTE *)Answer->rm_Result2);
               }
            }

            DeleteArgstring((UBYTE *)ARG0(Answer));
            DeleteRexxMsg(Answer);

            return Error;
         }
         else
            DeleteRexxMsg(rexxMsg);
      }
   }

   Permit();

   return RC_FATAL;
}

int FindOldHeader(char *in, char *out, char *header)
{
    int n = 0, i = 0;
    char *h;
    BOOL end=FALSE;

    h = strstr(in, header);

    if(h)
    {
        while(h[n] != ':')
            n++;

        n += 2;

        while(!end)
        {
            while(h[n] != 10)
                out[i++] = h[n++];

            if(h[n-1] != ',')
                end = TRUE;
            else
            {
                while(isspace(h[n++])) ;
                n--;
            }
        }

        out[i]=0;
        return(TRUE);
    }
    return(FALSE);
}

void GetFolderName(char *folder, char *path)
{
    char fconfig[108];
    BPTR fh;

    strcpy(fconfig, path);
    AddPart(fconfig, ".fconfig", 108);
    fh=Open(fconfig, MODE_OLDFILE);

    while(FGets(fh, fconfig, 108))
    {
        if(strnicmp("name", fconfig, 4)==0)
        {
            int a=0, b=0;

            while(fconfig[a++]!='=') ;

            a++;
            while(isspace(fconfig[a++])) ;

            a--;
            while(fconfig[a]!=10)
                folder[b++]=fconfig[a++];

            folder[b]=0;
            break;
        }
    }
    Close(fh);
}

void update_folder(void)
{
    struct MsgPort *ARexxPort;
    char tmp[100];

    ARexxPort = CreateMsgPort();
    if(!ARexxPort)
        return;

    sprintf(buf, "SETFOLDER %d", get_folder_pos(folders, DELETED));
    SendRexxCommand("YAM", buf, ARexxPort, tmp);

    SendRexxCommand("YAM", "MAILUPDATE", ARexxPort, tmp);

    sprintf(buf, "SETFOLDER %d", ((struct Folder *)folders->lh_Head)->f_num);
    SendRexxCommand("YAM", buf, ARexxPort, tmp);


    DeleteMsgPort(ARexxPort);
}

int main(int argc, char *argv[])
{
    struct FileInfoBlock *fib;
    BPTR lock, fh, oldlock;
    char *msg = 0, tmp[108], path[108];

    RexxSysBase = OpenLibrary("rexxsyslib.library", 0);
    if(!RexxSysBase)
        return(20);

    query_for_user();

    folders = init_folder_list();

    strcpy(path, current_user_path);
    strcpy(tmp, get_folder_path(folders, DELETED));

    AddPart(path, tmp, sizeof(path));

    strcpy(buf, path);
    AddPart(buf, ".fconfig", sizeof(buf));

    lock = Lock(buf, ACCESS_READ);
    if(!lock)
        exit(20);

    UnLock(lock);

    if(!(listpool = LibCreatePool(MEMF_ANY | MEMF_CLEAR, 4096, 4096)))
        exit(20);

    fib = AllocDosObject(DOS_FIB, TAG_DONE);

    if(!(LoadConfig()))
        exit(20);

    lock = Lock(path, ACCESS_READ);
    if(!lock)
        exit(20);
    oldlock = CurrentDir(lock);

    Examine(lock, fib);

    while(ExNext(lock, fib))
    {
        if(fib->fib_EntryType < -2)
        {
            if(stricmp(fib->fib_FileName, ".fconfig") && stricmp(fib->fib_FileName, ".index"))
            {
                char header[60];

                fh = Open(fib->fib_FileName, MODE_OLDFILE);
                msg = AllocVec(fib->fib_Size, MEMF_ANY | MEMF_CLEAR);
                Read(fh, msg, fib->fib_Size);

                if(FindOldHeader(msg, header, "Message-ID:"))
                {
                    if(FindOldHeader(msg, tmp, "Newsgroups:"))
                    {
                        BPTR fh2;
                        char name[108], *p, *nextname;
                        struct NewsNode *nn = (struct NewsNode *)newsgroupslist->lh_Head;

                        nextname = strtok(tmp, ",");
                        while(nextname)
                        {
                            char folder[108];

                            strcpy(name, "YAM:NNTP-Headers/");

                            while(nn->next)
                            {
                                if(stricmp(nn->ngname, nextname) == 0)
                                    break;
                                nn = nn->next;
                            }

                            GetFolderName(folder, nn->path);
                            strcat(name, folder);

                            header[0] = 'p';
                            if(strlen(header) <= 30)
                            {
                                p = strchr(header, '>');
                                if(p)
                                    *p = 0;
                            }
                            else
                                header[30] = 0;

                            AddPart(name, header, sizeof(name));
                            fh2 = Open(name, MODE_OLDFILE);
                            if(fh2)
                            {
                                Close(fh2);
                                DeleteFile(name);
                            }
                            nextname = strtok(NULL, ",");
                            if(!nextname)
                                break;
                        }
                    }
                }
                FreeVec(msg);
                Close(fh);
                DeleteFile(fib->fib_FileName);
            }
        }
    }

    FreeDosObject(DOS_FIB, fib);
    CurrentDir(oldlock);
    UnLock(lock);
    LibDeletePool(listpool);
    update_folder();
    free_folders_list(folders);
    CloseLibrary(RexxSysBase);
    exit(0);
}
