#include <player_handler.h> #include <origin.h> #define ERASE_RATE 30 #define ONE_DAY (60*60*24) #define MIN_DELAY (30*ONE_DAY) #define MAX_DELAY (600*ONE_DAY) #define TIMES_AGE 30 #define FOLDER_H HANDLER_DIR "/folder_handler" #define PLAYERINFO_H HANDLER_DIR "/playerinfo" #define ALPHABET ({ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", \ "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", \ "w", "x", "y","z" }) #define SAVEFILE SECURE_DIR SAVE_DIR HANDLER_DIR "/bulk_delete.os" int last_log_on, time_on, creator; mapping map_prop; nosave string *dirs, current; private void delete_name(string name); private void check_name(string name); protected void do_delete_check(); /** @ignore yes */ protected void create() { string var; seteuid("Root"); dirs = ({ }); if( file_exists(SAVEFILE) ) { var = unguarded( (: read_file, SAVEFILE :) ); dirs = restore_variable(var); } call_out("continuous_erase", 1 ); unguarded( (: do_delete_check() :) ); } /* create() */ /** @ignore yes */ protected void reset() { string var; var = save_variable(dirs); unguarded( (: write_file, SAVEFILE, var, 1 :) ); if( find_call_out("continuous_erase") == -1 ) call_out("continuous_erase", 1 ); } /* reset() */ /** @ignore yes */ void delete_related_files( string name, int mail ) { string *files; if( origin() != ORIGIN_LOCAL && TP && TP->query_name() != name && PO != find_object("/cmds/admin/rmp_layer") && PO != find_object("/secure/cmds/lord/securitytool") ) { user_event("inform", sprintf("Not doing erasing in " "delete_related_files. PO : %O", PO ), "admin"); unguarded( (: write_file, "/log/CHEAT", ctime( time() )+ ": illegal attempt to delete related files using "+ file_name(TO)+"\nTP : "+( TP ? file_name(TP)+" ("+ TP->query_name()+")" : 0 )+"\nTrace: "+ back_trace() :) ); return; } REFRESH_H->player_deleted( name ); PLAYER_H->delete_from_cache( name ); unguarded( (: rm, "/save/artifacts/"+name :) ); unguarded( (: rm, "/save/cmr_library/"+name+".o" :) ); unguarded( (: rm, "/save/bank_accounts/"+name[0..0]+"/"+name+".o" :) ); if( sizeof( files = get_dir( "/w/.dead_ed_files/"+name+"-*" ) ) ) map( files, (: unguarded( (: rm, "/w/.dead_ed_files/"+ $1 :) ) :) ); if( mail ) { // We only delete their player info if we also delete their mail. FOLDER_H->delete_account( name ); PLAYERINFO_H->player_remove( name ); BOARD_H->delete_player( name ); } } /* delete_related_files() */ protected void do_delete_check() { string *bits, name; mixed rubbish; call_out("do_delete_check", ONE_DAY ); bits = get_dir( PLAYER_SAVE_DIR+DELETE_DIR+"/*.o" ); foreach( string bit in bits ) { rubbish = stat( PLAYER_SAVE_DIR+DELETE_DIR+"/"+bit ); if( rubbish[1] + ( ONE_DAY * 10 ) < time() ) { sscanf( bit, "%s.o", name ); log_file("EXPIRED", "%s Requested player deletion: %s.\n", ctime(time()), name ); user_event("inform", "Auto deleting user "+CAP(name), "delete"); delete_related_files( name, 1 ); unguarded( (: rm( PLAYER_SAVE_DIR+DELETE_DIR+"/"+$(bit) ) :) ); } } } /* do_delete_check() */ /** @ignore yes */ protected void continuous_erase( string *all_files ) { if( !sizeof(all_files) ) { if( !sizeof(dirs) ) dirs = ALPHABET; current = dirs[random(sizeof(dirs))]; dirs -= ({ current }); all_files = get_dir( PLAYER_SAVE_DIR + current + "/*.o" ); } if( sizeof(all_files) ) check_name( all_files[0][0..<3] ); call_out("continuous_erase", ERASE_RATE, all_files[1..] ); } /* continuous_erase() */ /** @ignore yes */ private void check_name( string name ) { int age; if( find_player(name) ) return; if( !PLAYER_H->test_user(name) ) { delete_name(name); return; } unguarded( (: restore_object, LOGIN_OBJ->query_player_file_name(name) :) ); if( creatorp(name) || creator || map_prop["no delete"] ) return; // Logged on within MIN_DELAY. if( last_log_on > time() - MIN_DELAY ) return; // TIME_AGE times age or MAX_DELAY. age = time_on * TIMES_AGE; if( age < -MAX_DELAY ) age = -MAX_DELAY; // They have not reached their idle limit yet. if( age < last_log_on - time() ) return; delete_name(name); } /* check_name() */ /** @ignore yes */ private void delete_name( string name ) { string pfile; if( !pfile = (string)LOGIN_OBJ->query_player_file_name(name) ) { log_file("FAILED_DELETE", "%s Failed to delete %s - No player file in " "login ob!\n", ctime(time()), name ); return; } user_event("inform", "Deleting timed out user "+CAP(name), "delete"); log_file("EXPIRED", "%s Timed out player deletion: %s\n", ctime(time()), name ); delete_related_files( name, 1 ); rm( pfile+".o" ); } /* delete_name() */ /** @ignore yes */ int delete_files( string letter ) { string *all_files; if( !sizeof( filter( previous_object(-1), (: interactive($1) :) ) ) ) { unguarded( (: write_file, "/log/CHEAT", ctime( time() )+ ": illegal attempt to delete timed out player files using " "BULK_DELETE_H.\nTrace: " + back_trace() :) ); return 0; } if( !adminp( previous_object(-1) ) ) { unguarded( (: write_file, "/log/CHEAT", ctime( time() )+ ": illegal attempt to delete timed out player files using " "BULK_DELETE_H.\nTrace: " + back_trace() :) ); return 0; } log_file("EXPIRED", "%s Manually Requested Processing of %s.\n", ctime(time()), letter ); all_files = get_dir( PLAYER_SAVE_DIR+ letter +"/*.o" ); if( !sizeof(all_files) ) return notify_fail("Directory empty.\n"); // Put the current current back into the array so it's not skipped. dirs += ({ current }); // Make the requested letter current. current = letter; // Remove the new current letter from the array. dirs -= ({ current }); // Remove the old call out. remove_call_out("continuous_erase"); call_out("continuous_erase", 5, all_files ); return 1; } /* delete_files() */ /** @ignore yes */ int clean_up_files( string dir ) { int i; string *all_files = ({ }); if( !sizeof( filter( previous_object(-1), (: interactive($1) :) ) ) ) { unguarded( (: write_file, "/log/CHEAT", ctime( time() )+ ": illegal attempt to delete unused files using " "BULK_DELETE_H.\nTrace: " + back_trace() :) ); return 0; } if( !adminp( previous_object(-1) ) ) { unguarded( (: write_file, "/log/CHEAT", ctime( time() )+ ": illegal attempt to delete unused files using " "BULK_DELETE_H.\nTrace: " + back_trace() :) ); return 0; } switch( dir ) { case "artifacts" : all_files = get_dir("/save/"+ dir +"/*"); break; case "mail" : all_files = get_dir("/save/"+ dir +"/*inbox.o"); break; case "bank_accounts" : case "library" : all_files = get_dir("/save/"+ dir +"/*.o"); break; case ".dead_ed_files" : all_files = get_dir("/w/.dead_ed_files/"); break; default : return notify_fail("Invalid directory.\n"); } all_files -= ({ ".", ".." }); if( !sizeof(all_files) ) return notify_fail("Directory empty.\n"); for( i = sizeof(all_files) - 1; i > -1; i-- ) { switch( dir ) { case "artifacts" : call_out((: check_name :), 5 * (i + 1), all_files[i]); break; case "mail" : call_out((: check_name :), 5 * (i + 1), explode( all_files[i], "inbox")[0] ); break; case ".dead_ed_files" : call_out((: check_name :), 5 * (i + 1), explode( all_files[i], "-")[0] ); break; default : call_out((: check_name :), 5 * (i + 1), all_files[i][0..<3]); break; } } return 1; } /* clean_up_files() */ /** @ignore yes */ mixed stats() { return ({ ({"current letter", current }), ({"remaining dirs", sizeof(dirs) ? implode( dirs, ", ") : 0 }), }); } /* stats() */