lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

/*
** file.c -- handler for I3's "file" service
**
** 950126, Deathblade: created
*/

#include <log.h>

void oob_register_requests(mapping requests);
void oob_register_replies(mapping replies);
void oob_initiate_connection(string target_mudname);
void oob_svc_send(object socket, mixed * message);
void oob_svc_error(object socket, string errcode, string errmsg,
		   mixed * errpacket);

/*
** Store the lists of requests for each target mud
*/
nosave private mapping file_requests = ([ ]);

nosave private string * file_status = ({
    "request failed (write permission)",
    "request failed (read  permission)",
    "request failed (fpath error)",
    "request failed (unknown error)",
    "request successful"
});


private nomask string prepare_path(string path)
{
    if ( path == "/" )
	path = DIR_I3_FILES;
    else
    {
	string * parts;

	parts = explode(path, "/") - ({ "", "." });
	for ( int idx = 0; idx < sizeof(parts); )
	{
	    if ( parts[idx] == ".." )
	    {
		if ( idx )
		{
		    parts[idx-1..idx] = ({ });
		    --idx;
		}
		else
		    parts[idx..idx] = ({ });
	    }
	    ++idx;
	}
	path = DIR_I3_FILES;
	if ( sizeof(parts) )
	    path += "/" + implode(parts, "/");
    }
DBBUG(path);

    return path;
}

private nomask void file_add_request(string mudname, mixed * request)
{
    if ( !file_requests[mudname] )
	file_requests[mudname] = request;
    else
	file_requests[mudname] += request;
}

nomask void do_file_list_request(string mudname, string dir)
{
    file_add_request(mudname, ({ ({ "file-list-req",
					mud_name(),
					this_user()->query_userid(),
					dir,
					}) }));

    oob_initiate_connection(mudname);
}

nomask void do_file_put_request(string mudname,
				string local_fname,
				string remote_fname)
{
    file_add_request(mudname, ({ ({ "file-put",
					random(50000),
					mud_name(),
					this_user()->query_userid(),
					remote_fname,
					local_fname,
					}) }));

    oob_initiate_connection(mudname);
}

nomask void do_file_get_request(string mudname,
				string local_fname,
				string remote_fname)
{
    file_add_request(mudname, ({ ({ "file-get-req",
					random(50000),
					mud_name(),
					this_user()->query_userid(),
					remote_fname,
					local_fname,
					}) }));

    oob_initiate_connection(mudname);
}

private nomask mixed * handle_file_reply(string mudname,
					 object socket,
					 mixed * message,
					 string request_type,
					 string reply_type,
					 int request_id,
					 int reply_id,
					 int req_user_idx
					 )
{
    object p;
    mixed * requests = file_requests[mudname];
    mixed * request;

    if ( !sizeof(requests) || requests[0][0] != request_type )
    {
	oob_svc_error(socket,
		      "bad-proto",
		      "unexpected " + reply_type,
		      message);
	return 0;
    }
    request = requests[0];
    file_requests[mudname] = requests[1..];

    if ( request[request_id] != message[reply_id] )
    {
	oob_svc_error(socket,
		      "bad-proto",
		      reply_type + " did not match the " + request_type,
		      message);
	return 0;
    }

    p = find_user(request[req_user_idx]);

    return ({ p, request });
}

private nomask void handle_file_list_req(string mudname,
					 object socket,
					 mixed * message)
{
    string dir;
    mixed * data;
    string err;

    dir = message[3];
    if ( !sizeof(dir) || !stringp(dir) )
    {
	oob_svc_error(socket,
		      "bad-proto",
		      "bad directory specified",
		      message);
	return;
    }

    dir = prepare_path(dir);
    err = catch(data = get_dir(dir + "/*", -1));
    if ( err )
    {
	oob_svc_error(socket,
		      "bad-directory",
		      err,
		      ({ }));
	return;
    }

    oob_svc_send(socket, ({ "file-list-reply", message[2], data }));
}

private nomask void handle_file_list_reply(string mudname,
					   object socket,
					   mixed * message)
{
    mixed * info = handle_file_reply(mudname,
				     socket,
				     message,
				     "file-list-req",
				     "file-list-reply",
				     2, 1, 2);
    string list;

    if ( !info || !info[0] )
	return;

    if ( message[2] )
    {
	list = implode(message[2],
		       (: sprintf("%s%-20s %8s   %s\n",
				  $1,
				  $2[0],
				  $2[1] == -2 ? "- DIR -" : ""+$2[1],
				  ctime($2[2])) :),
		       "");
    }
    else
    {
	list = "<< an error occurred on the target mud >>\n";
    }
    info[0]->receive_private_msg(sprintf("\nDirectory %s on %s:\n%s\n",
					 info[1][3],
					 mudname, list));
}

private nomask void handle_file_put(string mudname,
				    object socket,
				    mixed * message)
{
    string fname;
    string err;

    fname = message[4];
    if ( !sizeof(fname) || !stringp(fname) )
    {
	oob_svc_send(socket, ({ "file-put-ack", message[1], -1 }));
	return;
    }

    fname = prepare_path(fname);
    err = catch(write_file(fname, message[5], 1));
    if ( err )
    {
	oob_svc_send(socket, ({ "file-put-ack", message[1], 0 }));
	return;
    }

    oob_svc_send(socket, ({ "file-put-ack", message[1], 1 }));
}

private nomask void handle_file_put_ack(string mudname,
					object socket,
					mixed * message)
{
    mixed * info = handle_file_reply(mudname,
				     socket,
				     message,
				     "file-put",
				     "file-put-ack",
				     1, 1, 3);
    string msg;
    int status;

    if ( !info || !info[0] )
	return;

    status = message[2];
    if ( status < -3 || status > 1 )
	status = 3;
    else
	status += 3;

    msg = sprintf("\n[IFTP] %s put of %s: %s\n",
		  mudname,
		  info[1][5],
		  file_status[status]);
    info[0]->receive_private_msg(msg);
}

private nomask void handle_file_get_req(string mudname,
					object socket,
					mixed * message)
{
    string fname;
    string err;
    string contents;

    fname = message[4];
    if ( !sizeof(fname) || !stringp(fname) )
    {
	oob_svc_send(socket, ({ "file-get-reply", message[1], -1, 0 }));
	return;
    }

    fname = prepare_path(fname);
    err = catch(contents = read_file(fname));
    if ( err )
    {
	oob_svc_send(socket, ({ "file-get-reply", message[1], 0, 0 }));
	return;
    }

    oob_svc_send(socket, ({ "file-get-reply", message[1], 1, contents }));
}

private nomask void handle_file_get_reply(string mudname,
					  object socket,
					  mixed * message)
{
    mixed * info = handle_file_reply(mudname,
				     socket,
				     message,
				     "file-get-req",
				     "file-get-reply",
				     1, 1, 3);
    string msg;
    int status;

    if ( !info )
	return;

    status = message[2];
    if ( status < -3 || status > 1 )
	status = 3;
    else
	status += 3;
    msg = sprintf("\n[IFTP] %s get of %s (to %s): %s\n",
		  mudname,
		  info[1][4],
		  info[1][5],
		  file_status[status]);

    if ( status == 4 )
    {
	string err;

	err = catch(write_file(info[1][5], message[3], 1));
	if ( err )
	    msg = sprintf("\n[IFTP] %s get of %s: ERROR: %s\n",
			  mudname,
			  info[1][5],
			  err);
    }

    if ( info[0] )
	info[0]->receive_private_msg(msg);
}

protected nomask int file_has_outgoing(string mudname)
{
    return sizeof(file_requests[mudname]) != 0;
}

protected nomask int file_send_outgoing(string mudname, object socket)
{
    mixed * requests = file_requests[mudname];
    mixed * request;

    if ( !sizeof(requests) )
	return 0;
    request = requests[0];

    switch ( request[0] )
    {
    case "file-list-req":
	oob_svc_send(socket, request);
	break;
    case "file-put":
	oob_svc_send(socket,
		     request[0..4] + ({ read_file(request[5]) }));
	break;
    case "file-get-req":
	oob_svc_send(socket, request[0..4]);
	break;
    }
}

protected nomask void file_startup()
{
    oob_register_requests(([ "file-list-req" : (: handle_file_list_req :),
				 "file-put" : (: handle_file_put :),
				 "file-get-req" : (: handle_file_get_req :),
				 ]));
    oob_register_replies(([ "file-list-reply" : (: handle_file_list_reply :),
				"file-put-ack" : (: handle_file_put_ack :),
				"file-get-reply" : (: handle_file_get_reply :),
				]));
}