/* $Id: nntp.cpp,v 1.13 2004/01/02 03:54:01 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of a library used by the Archimedes email client     * 
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU Library 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 Library General Public License for more details.                      *
 *                                                                             *
 *   You should have received a copy of the GNU Library 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 <fmail.h>
#include <umail.h>
#include <cfgfile.h>
#include <connectionManager.h>

extern cfgfile Config;
extern class connectionManager ConMan;
extern void nntp_account();

static char response[255];
static int nntpsock = -1;
FILE *nntp_in = NULL;
FILE *nntp_out = NULL;


#if STDC_HEADERS || defined(HAVE_STDARG_H)
int nntp_command(char *fmt, ...)
#else
int nntp_command(char *fmt, va_dcl
				 va_list)
#endif
{
	int res;
	char buf[255];
	va_list ap;

#if STDC_HEADERS || defined(HAVE_STDARG_H)
	va_start(ap, fmt);
#else
	va_start(ap);
#endif

	if(fmt) {
		vsnprintf(response, sizeof(response), fmt, ap);

		if(logging & LOG_NNTP) {
			if(!strncasecmp(response, "AUTHINFO PASS ", 14))
				display_msg(MSG_LOG, "nntp", "-> AUTHINFO PASS ******");
			else
				display_msg(MSG_LOG, "nntp", "-> %-.127s", response);
		}

		if(putline(response, nntp_out) == -1)
			return -1;
	}

	if(getline(response, sizeof(response), nntp_in) == NULL)
		return -1;

	if(logging & LOG_NNTP)
		display_msg(MSG_LOG, "nntp", "<- %-.127s", response);

	res = -1;
	sscanf(response, "%d%s", &res, buf);

	if(res == -1) {
		display_msg(MSG_WARN, "nntp", "%-.127s", response);
		return -1;
	}

	return res;
}

void nntp_close() {

	ConMan.del_cinfo(nntpsock);

	if(nntp_in != NULL)
		fclose(nntp_in);

	nntp_in = NULL;
	nntp_out = NULL;
}

void nntp_end() {
	if(nntp_command("QUIT") != 205)
		display_msg(MSG_WARN, "nntp", "%-.127s", response);

	nntp_close();
}

int nntp_init() {
	char buf[255];
	int res, authusr = 0, authpass = 0;

	if(nntpsock != -1) {
		display_msg(MSG_WARN, "nntp", "NNTP busy");
		return -1;
	}

	strcpy(buf, Config.get("nntphost", "news").c_str());
	nntpsock =
	ConMan.host_connect(buf, const_cast<char *>(Config.get("nntport", "119").c_str()), NULL); 
    
    if(nntpsock == -1)
		return -1;

	if((nntp_in = fdopen(nntpsock, "r+")) == NULL) {
		display_msg(MSG_WARN, "nntp", "fdopen failed");
		nntp_close();
		return -1;
	}

	nntp_out = nntp_in;

	if(Config.getInt("nntpauth", 0)) {
		if(Config.exist("nntpasswd") && (Config.getInt("nntpstorpwd", 0) == 0))
			nntp_account();
		if(Config.exist("nntpuser"))
			authusr = 1;
		authpass = 1;
	}
	switch(nntp_command(NULL)) {
		case 200:
			break;

		case 380:
		case 480:
			authusr = 1;
			break;

		case 381:
			authpass = 1;
			break;

		default:
			display_msg(MSG_WARN, "nntp", "%-.127s", response);
			nntp_close();
			return -1;
			break;
	}

	nntp_user:
	if(authusr) {
		if(!Config.exist("nntpuser"))
			nntp_account();
		switch(nntp_command
			   ("AUTHINFO USER %s",
				Config.get("nntpuser", user_n).c_str())) {
			case 381:
				authpass = 1;
				break;

			case 281:
				authpass = 0;
				break;

			default:
				display_msg(MSG_WARN, "nntp", "%-.127s", response);
				nntp_close();
				return -1;
				break;
		}
	}

	if(authpass) {
		if(Config.exist("nntpasswd"))
			nntp_account();
		switch(nntp_command("AUTHINFO PASS %s", Config.get("nntpasswd", "").c_str())) {
			case 281:
				break;

			case 482:
				authpass = 0;
				authusr = 1;
				goto nntp_user;
				break;

			default:
				nntp_account();
				if(nntp_command ("AUTHINFO PASS %s", Config.get("nntpasswd", "").c_str()) != 281) {
					display_msg(MSG_WARN, "nntp", "%-.127s", response);
					nntp_close();
					return -1;
				}
				break;
		}
	}

	if(((res = nntp_command("MODE READER")) != 200) && (res != 500)) {
		display_msg(MSG_WARN, "nntp", "%-.127s", response);
		nntp_close();
		return -1;
	}

	return 0;
}

int nntp_send_message(struct _mail_msg *msg) {
	struct _head_field *hf;

	if(msg->header->News == NULL)
		return 0;

	if(nntp_init() == -1)
		return -1;

	if(nntp_command("POST") != 340) {
		display_msg(MSG_WARN, "nntp", "%-.127s", response);
		nntp_end();
		return -1;
	}

	if((hf = find_field(msg, "X-Mailer")) != NULL)
		snprintf(hf->f_name, sizeof(hf->f_name), "X-Newsreader");

	if(smtp_message(msg, nntp_out) == -1) {
		nntp_end();
		if(hf != NULL)
			snprintf(hf->f_name, sizeof(hf->f_name), "X-Mailer");
		return -1;
	}

	if(hf != NULL)
		snprintf(hf->f_name, sizeof(hf->f_name), "X-Mailer");

	if(nntp_command(".") != 240) {
		display_msg(MSG_WARN, "nntp", "%-.127s", response);
		nntp_end();
		return -1;
	}

	nntp_end();
	return 0;
}

int is_newsgroup_addr(struct _mail_addr *addr, int strict) {
	char *p;

	if(addr->name || addr->comment || addr->pgpid)
		return 0;

	if(!strncmp(addr->addr, "#news.", 6))
		return 1;

	if(strict || !islower(*addr->addr))
		return 0;

	p = addr->addr + 1;
	while(*p) {
		if(!islower(*p) && !isdigit(*p) &&
		   (*p != '-') && (*p != '_') && (*p != '.'))
			return 0;

		if(*p == '.') {
			if((p[1] == '.') || (p[1] == '\0') || (p[-1] == '.'))
				return 0;
		}

		p++;
	}

	return 1;
}

struct _news_addr *expand_news_addr_list(struct _mail_addr *addr,
										 int strict) {
	struct _news_addr *ng, *naddr = NULL;

	while(addr) {
		if(is_newsgroup_addr(addr, strict)) {
			if((ng = get_news_addr(addr->addr)) != NULL) {
				ng->next = naddr;
				naddr = ng;
			}
		}
		addr = addr->next_addr;
	}

	return naddr;
}
