/*****************************************************************************
 *
 * $Id$
 * Purpose ...............: File forward to a node
 *
 *****************************************************************************
 * Copyright (C) 1997-2002
 *   
 * Michiel Broek		FIDO:		2:280/2802
 * Beekmansbos 10
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS 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, or (at your option) any
 * later version.
 *
 * MBSE BBS 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 MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

#include "../config.h"
#include "../lib/libs.h"
#include "../lib/memwatch.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "../lib/dbnode.h"
#include "../lib/dbtic.h"
#include "../lib/diesel.h"
#include "tic.h"
#include "sendmail.h"
#include "rollover.h"
#include "mgrutil.h"
#include "forward.h"



void ForwardFile(fidoaddr Node, fa_list *sbl)
{
    char	*subject = NULL, *temp, *fwdfile = NULL, *queuedir, *listfile, *ticfile = NULL, fname[PATH_MAX], *ticname, flavor;
    FILE	*fp, *fi, *fl, *net;
    faddr	*dest, *routeto, *Fa, *Temp, *ba;
    int		i, z, n;
    time_t	now, ftime;
    fa_list	*tmp;

    if (!SearchNode(Node)) {
	WriteError("TIC forward in %s, node %s not in setup but defined in area setup", TIC.TicIn.Area, aka2str(Node));
	return;
    }
    Syslog('+', "Forward file to %s, %s netmail", aka2str(Node), nodes.Message?"with":"without");

    /*
     * Hier moet een nieuwe SEEN-BY check komen, maar dan wel zo dat
     * de net toegevoegde seenby niet getest wordt.
     */

    /*
     * If Costsharing active for this node
     */
    if (nodes.Billing) {
	/*
	 * Check if this node has enough credits for this file.
	 */
	T_File.Cost = TIC.FileCost + (TIC.FileCost * nodes.AddPerc / 1000);
	if ((nodes.Credit < (nodes.StopLevel + T_File.Cost))  && (!TIC.Charge)) {
	    Syslog('!', "No forward to %s, not enough credit left", aka2str(Node));
	    exit;
	}

	/*
	 * Check if we are passing the warning level
	 */
	if ((nodes.Credit > nodes.WarnLevel) && ((nodes.Credit - T_File.Cost) <= nodes.WarnLevel)) {
	    Syslog('+', "Low credit warning to %s", aka2str(Node));
	    /* CREATE NETMAIL */
	}
    }

    fwdfile  = calloc(PATH_MAX, sizeof(char));
    queuedir = calloc(PATH_MAX, sizeof(char));
    listfile = calloc(PATH_MAX, sizeof(char));
    sprintf(queuedir, "%s/%d.%d.%d.%d", CFG.out_queue, Node.zone, Node.net, Node.node, Node.point);
    sprintf(listfile, "%s/.filelist", queuedir);
    mkdirs(listfile, 0750);
    if ((fl = fopen(listfile, "a+")) == NULL) {
	WriteError("$Can't open %s", listfile);
	free(fwdfile);
	free(listfile);
	free(queuedir);
	return;
    }
    Syslog('f', "%s is open", listfile);
    
    /*
     * Create the full filename
     */
    if (TIC.SendOrg) {
	sprintf(fwdfile, "%s/%s", TIC.Inbound, TIC.RealName);
	subject = xstrcpy(TIC.RealName);
    } else {
	sprintf(fwdfile, "%s/%s", TIC.BBSpath, TIC.NewName);
	subject = xstrcpy(TIC.NewName);
    }

    flavor = 'f';
    if (nodes.Crash) 
	flavor = 'c';
    if (nodes.Hold)
	flavor = 'h';

    fprintf(fl, "%c LEAVE %s\n", flavor, fwdfile);

    if (nodes.RouteVia.zone)
	routeto = fido2faddr(nodes.RouteVia);
    else
	routeto = fido2faddr(Node);
    dest = fido2faddr(Node);

    ticfile = calloc(PATH_MAX, sizeof(char));
    ticname = calloc(15, sizeof(char));
    if (nodes.Tic) {
	sprintf(ticname, "%08lx.tic", sequencer());
	subject = xstrcat(subject, (char *)" ");
	subject = xstrcat(subject, ticname);
	sprintf(ticfile, "%s/%s", CFG.ticout, ticname);
    }
    free(ticname);

    /*
     *  Send netmail message if the node has it turned on.
     */
    if (nodes.Message) {
	Temp = fido2faddr(Node);
	if ((net = SendMgrMail(Temp, CFG.ct_KeepMgr, TRUE, (char *)"Filemgr", subject, NULL)) != NULL) {
	    if ((fi = OpenMacro("forward.tic", nodes.Language, FALSE)) != NULL) {
		ftime = TIC.FileDate;
		MacroVars("a", "s", TIC.TicIn.Area);
		MacroVars("b", "s", tic.Comment);
		MacroVars("c", "d", TIC.FileCost);
		MacroVars("d", "s", fgroup.Comment);
		MacroVars("f", "s", TIC.TicIn.FullName);
		MacroVars("g", "d", TIC.FileSize);
		MacroVars("h", "d", (TIC.FileSize / 1024));
		MacroVars("i", "s", TIC.TicIn.Crc);
		MacroVars("j", "s", TIC.TicIn.Origin);
		MacroVars("m", "s", rfcdate(ftime));
		MacroVars("n", "s", TIC.TicIn.Desc);
		MacroVars("s", "s", nodes.Sysop);
		if (TIC.SendOrg)
		    MacroVars("e", "s", TIC.RealName);
		else
		    MacroVars("e", "s", TIC.NewName);
		if (strlen(TIC.TicIn.Magic))
		    MacroVars("k", "s", TIC.TicIn.Magic);
		if (strlen(TIC.TicIn.Replace))
		    MacroVars("l", "s", TIC.TicIn.Replace);
		MacroRead(fi, net);
		fprintf(net, "%s\r", TearLine());
		CloseMail(net, Temp);
	    }
	} else {
	    WriteError("$Can't create netmail");
	}
	tidy_faddr(Temp);
    }
    free(subject);

    /*
     * If we need a .TIC file, start creating it.
     */
    if (nodes.Tic) {
	mkdirs(ticfile, 0770);
	if ((fp = fopen(ticfile, "a+")) != NULL) {
	    fprintf(fp, "Area %s\r\n", TIC.TicIn.Area);
	    fprintf(fp, "Origin %s\r\n", TIC.TicIn.Origin);
	    Fa = fido2faddr(tic.Aka);
	    fprintf(fp, "From %s\r\n", ascfnode(Fa, 0x0f));
	    free(Fa);
	    if (strlen(TIC.TicIn.Replace))
		fprintf(fp, "Replaces %s\r\n", TIC.TicIn.Replace);
	    if (strlen(TIC.TicIn.Magic))
		fprintf(fp, "Magic %s\r\n", TIC.TicIn.Magic);

	    if ((TIC.PassThru) || (TIC.SendOrg))
		subject = xstrcpy(TIC.RealName);
	    else
		subject = xstrcpy(TIC.NewName);
	    /*
	     * Create 8.3 filename if this is a long filename. In normal
	     * cases mbcico will transmit the long filename to the other
	     * node. If they can't process the TIC files which has a short
	     * 8.3 filename and they have a long filename in the inbound
	     * then in mbsetup these nodes need to be set to 8.3 filenames.
	     * The mailer will then transmit the file with a 8.3 name.
	     * Thank the inventors of the 8.3 filenames for this.
	     */
	    temp = xstrcpy(subject);
	    name_mangle(temp);
	    fprintf(fp, "File %s\r\n", temp);
	    fprintf(fp, "Fullname %s\r\n", subject);
	    free(temp);
	    free(subject);

	    fprintf(fp, "Size %ld\r\n", (long)(TIC.FileSize));
	    fprintf(fp, "Desc %s\r\n", TIC.TicIn.Desc);
	    fprintf(fp, "Crc %s\r\n", TIC.TicIn.Crc);
	    if (nodes.AdvTic) {
		fprintf(fp, "To %s, %s\r\n", nodes.Sysop, ascfnode(dest, 0x1f));
		fprintf(fp, "Areadesc %s\r\n", tic.Comment);
		fprintf(fp, "Fdn %s\r\n", fgroup.Comment);
		/*
		 * According to Harald Harms this field must
		 * be multiplied with 100.
		 */
		if (TIC.FileCost && nodes.Billing) 
		    fprintf(fp, "Cost %ld.00\r\n", T_File.Cost);
		if (TIC.TicIn.TotLDesc)
		    for (i = 0; i < TIC.TicIn.TotLDesc; i++)
			fprintf(fp, "LDesc %s\r\n", TIC.TicIn.LDesc[i]);
	    }
	    fprintf(fp, "Created by MBSE BBS %s %s\r\n", VERSION, SHORTRIGHT);
	    if (TIC.TicIn.TotPath)
		for (i = 0; i < TIC.TicIn.TotPath; i++)
		    fprintf(fp, "Path %s\r\n", TIC.TicIn.Path[i]);
	    /*
	     * Add our system to the path
	     */
	    now = time(NULL);
	    subject = ctime(&now);
	    Striplf(subject);
	    ba = bestaka_s(dest);
	    fprintf(fp, "Path %s %lu %s %s\r\n", ascfnode(ba, 0x1f), mktime(localtime(&now)), subject, tzname[0]);
	    tidy_faddr(ba);

	    if (nodes.AdvTic) {
		/*
		 * In advanced TIC mode we send multiple seenby
		 * addresses on one line in stead of one line
		 * per system.
		 */
		z = 0;
		n = 0;
		subject = xstrcpy((char *)"Seenby");
		for (tmp = sbl; tmp; tmp = tmp->next) {
		    if (strlen(subject) > 70) {
			fprintf(fp, "%s\r\n", subject);
			z = 0;
			n = 0;
			free(subject);
			subject = xstrcpy((char *)"Seenby ");
		    } else {
			subject = xstrcat(subject, (char *)" ");
		    }

		    if (z != tmp->addr->zone) {
			subject = xstrcat(subject, ascfnode(tmp->addr, 0x0e));
			z = tmp->addr->zone;
		    } else { 
			if (n != tmp->addr->net) {
			    subject = xstrcat(subject, ascfnode(tmp->addr, 0x06));
			    n = tmp->addr->net;
			} else {
			    subject = xstrcat(subject, ascfnode(tmp->addr, 0x02));
			}
		    }
		}
		if (strlen(subject) > 7) {
		    fprintf(fp, "%s\r\n", subject);
		    free(subject);
		}
	    } else {
		/*
		 * Old style seenby lines
		 */
		for (tmp = sbl; tmp; tmp = tmp->next) {
		    fprintf(fp, "Seenby %s\r\n", ascfnode(tmp->addr, 0x0f));
		}
	    }

	    /*
	     * Now append all passthru ticlines
	     */
	    if (TIC.TicIn.Unknowns)
		for (i = 0; i < TIC.TicIn.Unknowns; i++)
		    fprintf(fp, "%s\r\n", TIC.TicIn.Unknown[i]);

	    fprintf(fp, "Pw %s\r\n", nodes.Fpasswd);
	    fclose(fp);
	    fprintf(fl, "%c KFS %s\n", flavor, ticfile);
	} else {
	    WriteError("$Can't create %s", ticfile);
	}
    }

    if (TIC.Charge && nodes.Billing) {
	nodes.Credit -= TIC.FileCost;
	Syslog('-', "Cost: %d  Left: %d", TIC.FileCost, nodes.Credit);

	/*
	 * Add an entry to the billing file, each node has his own
	 * billing file.
	 */
	sprintf(fname, "%s/tmp/%d.%d.%d.%d.bill", getenv("MBSE_ROOT"), 
		nodes.Aka[0].zone, nodes.Aka[0].net, nodes.Aka[0].node, nodes.Aka[0].point);
	if ((fp = fopen(fname, "a+")) != NULL) {
	    memset(&bill, 0, sizeof(bill));
	    bill.Node = nodes.Aka[0];
	    strcpy(bill.FileName, TIC.NewName);
	    strcpy(bill.FileEcho, TIC.TicIn.Area);
	    bill.Size = TIC.FileSize;
	    bill.Cost = TIC.FileCost;
	    fwrite(&bill, sizeof(bill), 1, fp);
	    fclose(fp);
	} else {
	    WriteError("$Can't create %s", fname);
	}
    }
    fsync(fileno(fl));
    fclose(fl);
    
    /*
     * Update the nodes statistic counters
     */
    StatAdd(&nodes.FilesSent, 1L);
    StatAdd(&nodes.F_KbSent, T_File.SizeKb);
    UpdateNode();
    SearchNode(Node);
    free(ticfile);
    free(fwdfile);
    free(queuedir);
    free(listfile);
    tidy_faddr(routeto);
}