/* Remote Editor * Shaydz 1/3/02 * Small bits of code, and idea from Descartes of Borg RCP */ #include <access.h> #include <network.h> #define PORT_RCP 7320; inherit SERVER; #include <remote.h> private string Password; private mapping Connections; private string Directory, Home; private int connected; string eventWriteFile(int fd, string file, string str) { file = replace(file,"^M"); file = replace(file,"\r"); if (!master()->valid_write(file,Connections[fd]["username"] , "write_file")) return "50 Permission denied to write: " + file; if( file_size(file) > -1 && !rm(file) ) return "50 Failed to write file: " + file; if( !write_file(file, str) ) return "50 Failed to write file: " + file; else { log_file("/secure/log/redit.log", "%s: %s uploaded %s\n", ctime(time()), Connections[fd]["username"],file); return "110 File " + file + " written."; } } /* eventWriteFile() */ string eventReadFile(int fd, string file) { string tmp; if (!master()->valid_read(file,Connections[fd]["username"] , "read_file")) return "50 Permission denied to read: " + file; tmp = read_file(file); if( !(tmp = read_file(file)) ) return ""; log_file("/secure/log/redit.log", "%s: %s downloaded %s\n", ctime(time()), Connections[fd]["username"],file); return tmp; } /* eventReadFile() */ string eventCommand(int fd, string cmd, string arg) { string *files; object ob; string tmp; switch(cmd) { case "ls": if( !arg || arg == "" ) arg = Directory; if (!master()->valid_read(arg,Connections[fd]["username"] , "get_dir")) return 0; switch(file_size(arg)) { case -2: if( arg[<1] != '/' ) arg += "/"; files = ({ arg }); files += map(get_dir(arg), (: (file_size($(arg) + $1) == -2) ? $1 + "/" : $1 :)); return implode(files, " "); case -1: return 0; default: return arg; } case "mkdir": arg = Directory+arg; if (!master()->valid_write(arg,Connections[fd]["username"] , "mkdir")) return "50 Permission denied to mkdir: " + arg; if( file_size(arg) != -1 ) return 0; if( !mkdir(arg) ) return 0; else return "Directory created."; case "cd": arg = Directory+arg; if( !arg || arg == "" ) Directory = Home; else if( !((int)master()->valid_read(arg, Connections[fd]["username"], "cd")) ) return 0; else Directory = arg; return Directory; case "rm": arg = Directory+arg; if (!master()->valid_write(arg,Connections[fd]["username"] , "rm")) return "50 Permission denied to rm " + arg; if( !rm(arg) ) return 0; else return arg + " deleted."; case "rmdir": arg = Directory+arg; if (!master()->valid_write(arg,Connections[fd]["username"] , "rmdir")) return "50 Permission denied to rmdir " + arg; if( !rmdir(arg) ) return 0; else return arg + " deleted."; case "mv": files = explode(arg, " "); if( sizeof(files) != 2 ) return 0; files[0] = Directory+files[0]; files[1] = Directory+ files[1]; if (!master()->valid_read(files[0],Connections[fd]["username"] , "read_file")) return 0; if (!master()->valid_write(files[1],Connections[fd]["username"] , "write_file")) return 0; if( !rename(files[0], files[1]) ) return 0; else return files[0] + " renamed to " + files[1] + "."; case "update": arg = Directory+ arg; if( arg[<2..] == ".c" ) arg = arg[0..<3]; if( ob = find_object(arg) ) { if( !((int)ob->eventDestruct()) ) return "Failed to destruct original object."; } tmp = catch(call_other(arg, "???")); if( tmp ) return "Error in loading object: " + replace_string(tmp, "\n", "\t"); else return arg + ": successfully loaded."; } return 0; } /* eventCommand() */ void create() { server::create(); Connections = ([]); connected = 0; call_out( (: Setup :), 1); } /* create() */ void Setup() { seteuid(geteuid(TO)); if( eventCreateSocket(7320) < 0 ) { if( this_object() ) dest_me(); return; } } /* Setup() */ void eventSocketClosed(int fd) { map_delete(Connections, fd); connected=0; } /* eventSocketClosed() */ void eventRead(int fd, string str) { if( !str ) { eventWrite(fd, "50 Invalid command.\n", 1); if( Connections[fd] ){ map_delete(Connections, fd); connected = 0; } return; } eventProcess(fd, str); } /* eventRead() */ private void eventProcess(int fd, string str) { string tmp, cmd, arg, file, val; int x; if( Connections[fd] && Connections[fd]["in edit"] > 0 ) { int len; Connections[fd]["buffer"] += str; if( !(len = strlen(Connections[fd]["buffer"])) ) return; if( len == Connections[fd]["in edit"] ) { tmp = eventWriteFile(fd, Connections[fd]["file"], Connections[fd]["buffer"]); eventWrite(fd, tmp + "\n"); Connections[fd]["in edit"] = 0; Connections[fd]["file"] = ""; Connections[fd]["buffer"] = ""; return; } else if( len > Connections[fd]["in edit"] ) { string tmp1, tmp2; tmp1 =Connections[fd]["buffer"][0..(Connections[fd]["in edit"]-1)]; tmp2 =Connections[fd]["buffer"][Connections[fd]["in edit"]..]; Connections[fd]["buffer"] = ""; eventProcess(fd, tmp1); eventProcess(fd, tmp2); return; } return; } if( !Connections[fd] ) Connections[fd] = ([ "buffer" : "" ]); if( (Connections[fd]["buffer"] += str) == "" ) return; if( (x = strsrch(Connections[fd]["buffer"], "\n")) == -1 ) return; str = Connections[fd]["buffer"][0..(x-1)]; if( x != strlen(Connections[fd]["buffer"]) - 1 ) Connections[fd]["buffer"] = Connections[fd]["buffer"][(x+1)..]; else Connections[fd]["buffer"] = ""; if( sscanf(str, "%s %s", cmd, arg) != 2) { cmd = replace_string(str, "\r", ""); arg = ""; } else arg = replace_string(arg, "\r", ""); if( !Connections[fd]["username"] ) { string username, *user, password; if( cmd != "login" ) { eventWrite(fd, "50 Must login with user name and password.\n", 1); map_delete(Connections, fd); connected =0; return; } if( sscanf(arg, "%s %s", username, password) != 2 ) { eventWrite(fd, "50 Login failed.\n", 1); map_delete(Connections, fd); connected=0; return; } user = explode(username," ")-({"login"}); username = implode(user,""); if( !creatorp(username) ) { eventWrite(fd, "50 Login failed.\n", 1); map_delete(Connections, fd); connected=0; return; } if (!LOGIN_OBJ->test_password(username, password)) { log_file("remote", "Failed attempt to login as " + username + "\n"); eventWrite(fd, "50 Login failed.\n", 1); connected=0; map_delete(Connections, fd); return; } Directory = "/w/"+username+"/"; Connections[fd]["username"] = username; connected =1; event(users(),"inform",CAP(username)+" connected to redit","ftp"); eventWrite(fd, "60 Connection to " + mud_name() + ".\n"); } else if( cmd == "100" ) { int sz; if( sscanf(arg, "%d %s", sz, Connections[fd]["file"]) != 2 ) eventWrite(fd, "50 Bad file send command.\n"); else { if( !sz ) eventWrite(fd, "110 No changes sent or written.\n"); else Connections[fd]["in edit"] = sz; } } else switch( cmd ) { case "edit": file = eventReadFile(fd, arg); if(sizeof(file)){ if( file[<1] != '\n' ) file += "\n"; if(file[0..1] == "50"){ eventWrite(fd, file); break; } } if(!strlen(file)){ eventWrite(fd, "50 File doesn't seem to exist."); break; } tmp = sprintf( "%-14s", "100 " + strlen(file)); eventWrite(fd, tmp[0..15]); eventWrite(fd, file); break; case "ls": val = eventCommand(fd, cmd, arg); if( val ) eventWrite(fd, "500 " + val + "\n"); else eventWrite(fd, "50 " +cmd+ " " +arg+ ": Permission denied.\n"); break; case "update": val = eventCommand(fd, cmd, arg); if( val ) eventWrite(fd, "510 " + val + "\n"); else eventWrite(fd, "50 Update attempt went off into nowhere.\n"); break; default: val = eventCommand(fd, cmd, arg); if( val ) eventWrite(fd, "400 " + val + "\n"); else eventWrite(fd, "50 "+cmd+" "+arg+": Command not supported.\n"); break; } eventProcess(fd, ""); } /* eventProcess() */ string stats(){ return sprintf("%O",Connections); } /* stats() */ void clean_up(){ return ; } /* clean_up() */