/*
** $Log$
*/

/*
**   YAM2NN - Usenet access for YAM p7 and newer
**   Copyright (C) 1999 Karol Bryd <kbryd@femina.com.pl>
**
**   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.
*/

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

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

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

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

#include "get_folder_path.h"

__stkargs void NewList(struct List * list);

struct NewsNode {
	struct NewsNode * next;
	struct NewsNode * prev;
	char * ngname;
	char * path;
	char folder[40];
};

struct List * newsgroupslist = 0;
struct List * folders = 0;
APTR 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;

	if(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)
				{
					if(newsgroupslist = AllocPooled(listpool, sizeof(struct List)))
						NewList(newsgroupslist);
					else
						return(FALSE);
				}
				if(newsnode = AllocPooled(listpool, sizeof(struct NewsNode)))
				{
					tmp = strtok(buf + 12, " ");
					if(newsnode->ngname = AllocPooled(listpool, strlen(tmp) + 1))
					{
						strcpy(newsnode->ngname, tmp);
						tmp = strtok(NULL, " \n");
						if(!tmp)
							return(FALSE);
						if(newsnode->path = AllocPooled(listpool, strlen(tmp) + 1))
						{
							strcpy(newsnode->path, tmp);
							{
								int a;

								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]);
							}
							while(1)
							{
								if(!(FGets(fh, buf, 200)))
									break;
								if(Strnicmp(buf, "\n", 1) == 0)
									break;
							}
							AddTail(newsgroupslist, (struct Node *)newsnode);
						}
						else
							return(FALSE);
					}
					else
						return(FALSE);
				}
				else
					return(FALSE);
			}
		}
		Close(fh);
		return(TRUE);
	}
	else
		return(FALSE);
}

// 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;

	if(h = strstr(in, header))
	{
		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 update_folder(void)
{
	struct MsgPort * ARexxPort;
	char tmp[100];

	if(!(ARexxPort = CreateMsgPort()))
		return;
	SPrintf(buf, "SETFOLDER %ld", get_folder_pos(folders, DELETED));
	SendRexxCommand("YAM", buf, ARexxPort, tmp);
	SendRexxCommand("YAM", "MAILUPDATE", ARexxPort, tmp);
	SPrintf(buf, "SETFOLDER %ld", get_folder_pos(folders, INCOMING));
	SendRexxCommand("YAM", buf, ARexxPort, tmp);
	DeleteMsgPort(ARexxPort);
}

void _main(void)
{
	struct FileInfoBlock * fib = NULL;
	BPTR lock = 0, fh, oldlock = 0;
	static char * newsmsg = NULL, tmp[108], path[108];

	if(SysBase->LibNode.lib_Version < 39)
		_exit(20);
	if(query_for_user() == -1)
		_exit(20);
	if(!(folders = open_folder_list()))
	{
		if(folders = init_folder_list())
		{
			if(build_folders_list(folders) != -2)
			{
				if(listpool = CreatePool(MEMF_ANY | MEMF_CLEAR, 8192, 4096))
				{
					if(LoadConfig())
					{
						save_folder_list(folders, newsgroupslist);
						free_folders_list(folders);
						if(listpool)
							DeletePool(listpool);
						folders = open_folder_list();
					}
					else
					{
						free_folders_list(folders);
						if(listpool)
							DeletePool(listpool);
						_exit(20);
					}
				}
				else
				{
					free_folders_list(folders);
					_exit(20);
				}
			}
			else
			{
				free_folders_list(folders);
				_exit(20);
			}
		}
		else
			_exit(20);
	}
	strcpy(path, get_folder_path(folders, DELETED));
	if(!strstr(path, ":"))
	{
		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));
	if(!(lock = Lock(buf, ACCESS_READ)))
	{
		free_folders_list(folders);
		_exit(20);
	}
	UnLock(lock);
	if(!(listpool = CreatePool(MEMF_ANY | MEMF_CLEAR, 8192, 4096)))
	{
		free_folders_list(folders);
		_exit(20);
	}
	if(!(LoadConfig()))
	{
		free_folders_list(folders);
		if(listpool)
			DeletePool(listpool);
		_exit(20);
	}
	if(!(lock = Lock(path, ACCESS_READ)))
	{
		free_folders_list(folders);
		if(listpool)
			DeletePool(listpool);
		_exit(20);
	}
	if(!(fib = AllocDosObject(DOS_FIB, TAG_DONE)))
	{
		free_folders_list(folders);
		if(lock)
			UnLock(lock);
		if(listpool)
			DeletePool(listpool);
		_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"))
			{
				static char header[60];

				strcpy(tmp, fib->fib_FileName);
				if(fh = Open(tmp, MODE_OLDFILE))
				{
					if(newsmsg = (char *)AllocVec(fib->fib_Size + 2, MEMF_ANY | MEMF_CLEAR))
					{
						Read(fh, newsmsg, fib->fib_Size);
						if(FindOldHeader(newsmsg, tmp, "Newsgroups:"))
						{
							if(FindOldHeader(newsmsg, header, "Message-ID:"))
							{
								BPTR fh2;
								char name[108], * p, * nextname;

								for(nextname = strtok(tmp, ","); nextname; nextname = strtok(NULL, ","))
								{
									struct NewsNode * nn;
									long cut = 0;

									strcpy(name, "YAM:NNTP-Headers/");
									for(nn = (struct NewsNode *)newsgroupslist->lh_Head; nn->next; nn = (struct NewsNode *)nn->next)
									{
										if(Stricmp(nn->ngname, nextname) == 0)
										{
											cut = 1;
											break;
										}
									}
									if(cut)
									{
										strcat(name, nn->folder);
										header[0] = 'p';
										if(strlen(header) <= 30)
										{
											if(p = strchr(header, '>'))
												*p = 0;
										}
										else
											header[30] = 0;
										AddPart(name, header, sizeof(name));
										if(fh2 = Lock(name, ACCESS_READ))
										{
											UnLock(fh2);
											DeleteFile(name);
										}
										else
										{
											char name2[108];

											for(nn = (struct NewsNode *)newsgroupslist->lh_Head; nn->next; nn = (struct NewsNode *)nn->next)
											{
												strcpy(name2, "YAM:NNTP-Headers/");
												strcat(name2, nn->folder);
												AddPart(name2, header, sizeof(name));
												if(fh2 = Lock(name2, ACCESS_READ))
												{
													UnLock(fh2);
													DeleteFile(name2);
													break;
												}
											}
										}
										break;
									}
								}
							}
						}
						FreeVec(newsmsg);
					}
					Close(fh);
					DeleteFile(fib->fib_FileName);
				}
			}
		}
	}
	if(fib)
		FreeDosObject(DOS_FIB, fib);
	if(oldlock)
		CurrentDir(oldlock);
	if(lock)
		UnLock(lock);
	if(listpool)
		DeletePool(listpool);
	update_folder();
	free_folders_list(folders);
	_exit(0);
}
