nightmare3_fluffos_v2/
nightmare3_fluffos_v2/bin/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/ChangeLog.old/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/Win32/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/simuls/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/clone/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/command/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/data/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/etc/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/master/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/log/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/compiler/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/efuns/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/operators/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/u/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/tmp/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/windows/
nightmare3_fluffos_v2/lib/cmds/ambassador/
nightmare3_fluffos_v2/lib/cmds/database/
nightmare3_fluffos_v2/lib/cmds/hm/
nightmare3_fluffos_v2/lib/cmds/soul/
nightmare3_fluffos_v2/lib/daemon/cfg/
nightmare3_fluffos_v2/lib/daemon/cfg/mon_races/
nightmare3_fluffos_v2/lib/daemon/cfg/races/
nightmare3_fluffos_v2/lib/daemon/include/
nightmare3_fluffos_v2/lib/daemon/save/
nightmare3_fluffos_v2/lib/daemon/services/
nightmare3_fluffos_v2/lib/daemon/soul/
nightmare3_fluffos_v2/lib/doc/
nightmare3_fluffos_v2/lib/doc/TestPlans/
nightmare3_fluffos_v2/lib/doc/approval/
nightmare3_fluffos_v2/lib/doc/approval/QC/
nightmare3_fluffos_v2/lib/doc/approval/balance/
nightmare3_fluffos_v2/lib/doc/build/
nightmare3_fluffos_v2/lib/doc/build/armours/
nightmare3_fluffos_v2/lib/doc/build/economy/
nightmare3_fluffos_v2/lib/doc/build/etc/
nightmare3_fluffos_v2/lib/doc/build/monster/
nightmare3_fluffos_v2/lib/doc/build/room/
nightmare3_fluffos_v2/lib/doc/build/virtual/
nightmare3_fluffos_v2/lib/doc/build/weapon/
nightmare3_fluffos_v2/lib/doc/classes/
nightmare3_fluffos_v2/lib/doc/efun/
nightmare3_fluffos_v2/lib/doc/etc/
nightmare3_fluffos_v2/lib/doc/help/creator/
nightmare3_fluffos_v2/lib/doc/help/hm/
nightmare3_fluffos_v2/lib/doc/law/
nightmare3_fluffos_v2/lib/doc/lpc/basic/
nightmare3_fluffos_v2/lib/doc/lpc/data_types/
nightmare3_fluffos_v2/lib/doc/lpc/etc/
nightmare3_fluffos_v2/lib/doc/lpc/intermediate/
nightmare3_fluffos_v2/lib/doc/lpc/types/
nightmare3_fluffos_v2/lib/doc/mudlib/
nightmare3_fluffos_v2/lib/doc/mudlib/features/
nightmare3_fluffos_v2/lib/domains/Examples/etc/
nightmare3_fluffos_v2/lib/domains/Examples/room/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaA/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaB/
nightmare3_fluffos_v2/lib/domains/Examples/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/
nightmare3_fluffos_v2/lib/domains/Praxis/adm/
nightmare3_fluffos_v2/lib/domains/Praxis/attic/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/mon/
nightmare3_fluffos_v2/lib/domains/Praxis/data/
nightmare3_fluffos_v2/lib/domains/Praxis/death/
nightmare3_fluffos_v2/lib/domains/Praxis/mountains/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/armour/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/magic/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/orc_valley/
nightmare3_fluffos_v2/lib/domains/Praxis/quests/
nightmare3_fluffos_v2/lib/domains/Praxis/standardOld/
nightmare3_fluffos_v2/lib/include/
nightmare3_fluffos_v2/lib/log/
nightmare3_fluffos_v2/lib/log/errors/
nightmare3_fluffos_v2/lib/log/reports/
nightmare3_fluffos_v2/lib/log/watch/
nightmare3_fluffos_v2/lib/news/
nightmare3_fluffos_v2/lib/secure/cfg/
nightmare3_fluffos_v2/lib/secure/cmds/ambassador/
nightmare3_fluffos_v2/lib/secure/cmds/mortal/
nightmare3_fluffos_v2/lib/secure/save/users/d/
nightmare3_fluffos_v2/lib/secure/std/
nightmare3_fluffos_v2/lib/std/hm/
nightmare3_fluffos_v2/lib/std/living/
nightmare3_fluffos_v2/lib/std/room/
nightmare3_fluffos_v2/lib/std/user/
nightmare3_fluffos_v2/lib/std/virtual/
nightmare3_fluffos_v2/lib/www/
nightmare3_fluffos_v2/lib/www/errors/
nightmare3_fluffos_v2/lib/www/gateways/
nightmare3_fluffos_v2/win32/
/*    /daemon/mcp_d.c
 *    from Intermare libs
 */

#include <std.h>
#include <daemons.h>
#include <security.h>
#include <network.h>
#include <socket.h>
#include "mcp_d.h"

inherit DAEMON;

#define PORT_MCP                 (query_host_port() - 4)
#define MAX_ONE_WRITE 3072
#define VALID_INTERMARES ([ "199.199.122.10": ({ "tna", "3996" }), \
			"134.130.76.1": ({ "teu", "4996" }) ])

static private int __SocketMCP;
static private mapping __Sockets;
static private mapping __ValidHosts;

void create() { 
    daemon::create();
    set_no_clean(1);
    __Sockets = ([]);
    __ValidHosts = VALID_INTERMARES;
    call_out("setup", 2);
    call_out("clean_sockets", 180);
}

static void setup() {
    if((__SocketMCP=socket_create(STREAM,"read_callback","close_callback"))<0){
        log_file("inter_copy", "Failed to create socket.\n");
        return;
    }
    if(socket_bind(__SocketMCP, PORT_MCP) < 0) {
        socket_close(__SocketMCP);
        log_file("inter_copy", "Failed to bind port to socket.\n");
        return;
    }
    if(socket_listen(__SocketMCP, "listen_callback") < 0) {
        socket_close(__SocketMCP);
        log_file("inter_copy", "Failed to listen to socket.\n");
    }
}

void listen_callback(int fd) {
    int New;
    string tmp;

    if((New = socket_accept(fd, "read_callback", "write_callback")) < 0)
      return;
    if(!__Sockets[New]) {
        sscanf(socket_address(New), "%s %*s", tmp);
	if (member_array(tmp,keys(__ValidHosts)) == -1) {
	    socket_close(New);
	    log_file("inter_copy", "Illegal connection attempt from "+tmp+".\n");
	} else
	    __Sockets[New] = ([ "address": tmp, "time": time() ]);
    } 
}

void write_callback(int fd) {
    int i, pos;
    string str, file;

    if (str = __Sockets[fd]["pos"]) {
	pos = to_int(str);
	file = __Sockets[fd]["file"];
	if (pos == 0) {
	    i = file_size(file);
	    if (i > 0) {
		if (i >= MAX_ONE_WRITE) {
		    str = read_file(file,1,49);
		    socket_write(fd, "store "+file+"\n"+str);
		    __Sockets[fd]["pos"]="50";
		    __Sockets[fd]["file"]=file;
		    map_delete(__Sockets[fd],"write_callback");
		    if (find_call_out("write_tick") == -1)
			call_out("write_tick",1);
		} else {
		    str = read_file(file);
		    socket_write(fd, "store "+file+"\n"+str+"****EOT****\n");
		    close_connection(fd);
		}
	    } else {
		close_connection(fd);
	    }
	}
    }
}

void read_callback(int fd, string str) {
    string *lines;
    string cmd, args;
    int eof, i, j;

    if(str && str != "") {
	str = replace_string(str, "\r", "");
	if (str == "\n" ||  str == "")
	    lines = ({ "" });
	else
	    lines = explode(str,"\n");
	if (__Sockets[fd]["store"]) {
	    eof = 0;
	    if ((i = sizeof(lines)) > 0) {
		if (lines[i-1] == "****EOT****")
		{
		    eof = 1;
		    i--;
		    if (i) 
			for (j=0;j<i;j++)
			    write_file(__Sockets[fd]["store"],lines[j]+"\n");
		} else
		    write_file(__Sockets[fd]["store"],str);
	    }
	    if (eof)
	    	close_connection(fd);
	    return;
	}
	sscanf(lines[0], "%s %s", cmd, args);
	switch(lower_case(cmd)) {
	    case "retrieve": retrieve_file(fd, args); return;
	    case "store": store_file(fd, args, lines); return;
	    // add here
	    default: close_connection(fd); return;
	}
    }
}

void close_callback(int fd) {
    socket_close(fd);
    if(fd == __SocketMCP) this_object()->remove();
}

void close_connection(int fd) {
    map_delete(__Sockets, fd);
    socket_close(fd);
}
    
static void clean_sockets() {
    int *cles;
    int i;

    i = sizeof(cles = keys(__Sockets));
    while(i--)
      if(time() - __Sockets[cles[i]]["time"] > 180) close_connection(cles[i]);
    call_out("clean_sockets", 180);
}

void remove() {
    if(previous_object() != this_object()) return 0;
    socket_close(__SocketMCP);
    destruct(this_object());
    // return daemon::remove();
}

void write_tick() {
    int i, fd, f, pos;
    string str;
    
    f = 0;
    i = sizeof(__Sockets);
    while (i--) {
	fd = keys(__Sockets)[i];
	if (__Sockets[fd]["write_callback"])
	    continue;
	if (str = __Sockets[fd]["pos"]) {
	    pos = to_int(str);
	    str = read_file(__Sockets[fd]["file"],pos,50);
	    if (str) {
		socket_write(fd, str);
		__Sockets[fd]["pos"]=sprintf("%d",pos+50);
	        __Sockets[fd]["time"]=time();
		f++;
	    } else {
	        socket_write(fd,"****EOT****\n");
		close_connection(fd);
	    }
	}
    }
    if (f)
	call_out("write_tick",1);
}

static private void retrieve_file(int fd, string file) {
    string str;
    int i;

    if (strlen(file) < 5 || file[0..4] != "/ftp/") {
	log_file("inter_copy", __Sockets[fd]["address"]+" attempted to retrieve: "+file+".\n");
        close_connection(fd);
	return;
    }
    log_file("inter_copy", __Sockets[fd]["address"]+" retrieved: "+file+".\n");
    i = file_size(file);
    if (i > 0) {
	if (i >= MAX_ONE_WRITE) {
	    str = read_file(file,1,49);
	    socket_write(fd, "store "+file+"\n");
	    socket_write(fd, str);
	    __Sockets[fd]["pos"]="50";
	    __Sockets[fd]["file"]=file;
	    if (find_call_out("write_tick") == -1)
		call_out("write_tick",1);
	} else {
	    str = read_file(file);
	    socket_write(fd, "store "+file+"\n");
	    socket_write(fd, str);
	    socket_write(fd,"****EOT****\n");
	    close_connection(fd);
	}
    }
}

static private void store_file(int fd, string file, string *lines) {
    int i, j, eof;

    if (strlen(file) < 5 || file[0..4] != "/ftp/") {
	log_file("inter_copy", __Sockets[fd]["address"]+" attempted to store: "+file+".\n");
        close_connection(fd);
	return;
    }
    log_file("inter_copy", __Sockets[fd]["address"]+" stored: "+file+".\n");
    rm(file);
    eof = 0;
    if ((i = sizeof(lines)) > 1) {
	if (lines[i-1] == "****EOT****")
	{
	    eof = 1;
	    i--;
	}
	for (j=1;j<i;j++)
	    write_file(file,lines[j]+"\n");
    }
    if (!eof)
        __Sockets[fd]["store"]=file;
}

static private void do_send(string file,string dest) {
    int fd;
    if (strlen(file) < 5 || file[0..4] != "/ftp/") {
	log_file("inter_copy", "Someone attempted to send: "+file+".\n");
	return;
    }
    log_file("inter_copy", "Someone send: "+file+" to "+dest+".\n");
    if((fd=socket_create(STREAM,"read_callback","close_callback"))<0){
        log_file("inter_copy", "Failed to create send socket.\n");
        return;
    }
    __Sockets[fd] = ([ "address": explode(dest," ")[0], "time": time(),
			"pos": "0", "file": file, "write_callback": 1, ]);
    if(socket_connect(fd, dest, "read_callback", "write_callback") < 0) {
        socket_close(fd);
	map_delete(__Sockets, fd);
        log_file("inter_copy", "Failed to connect send socket.\n");
    }
}

void send_file(string file, string mud) {
    int i;
    if (!mud || !file) return;
    for (i=0; i<sizeof(__ValidHosts); i++) {
	if (__ValidHosts[keys(__ValidHosts)[i]][0] == mud) {
	    do_send(file,keys(__ValidHosts)[i]+" "+
		__ValidHosts[keys(__ValidHosts)[i]][1]);
	    break;	
	}
    }
}