| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919 |
- #!/usr/bin/perl
- #
- # OGP - Open Game Panel
- # Copyright (C) 2008 - 2014 The OGP Development Team
- #
- # http://www.opengamepanel.org/
- #
- # This program 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
- # of the License, or any later version.
- #
- # This program 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 this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #
- use warnings;
- use strict;
- use Cwd; # Fast way to get the current directory
- use lib getcwd();
- use Frontier::Daemon::Forking; # Forking XML-RPC server
- use File::Copy; # Simple file copy functions
- use File::Copy::Recursive
- qw(fcopy rcopy dircopy fmove rmove dirmove pathempty pathrmdir)
- ; # Used to copy whole directories
- use File::Basename; # Used to get the file name or the directory name from a given path
- use Crypt::XXTEA; # Encryption between webpages and agent.
- use Cfg::Config; # Config file
- use Cfg::Preferences; # Preferences file
- use Fcntl ':flock'; # Import LOCK_* constants for file locking
- use LWP::UserAgent; # Used for fetching URLs
- use MIME::Base64; # Used to ensure data travelling right through the network.
- use Getopt::Long; # Used for command line params.
- use Path::Class::File; # Used to handle files and directories.
- use File::Path qw(mkpath);
- use Archive::Extract; # Used to handle archived files.
- use File::Find;
- use Schedule::Cron; # Used for scheduling tasks
- # Compression tools
- use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error); # Used to compress files to bz2.
- use Compress::Zlib; # Used to compress file download buffers to zlib.
- use Archive::Tar; # Used to create tar, tgz or tbz archives.
- use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); # Used to create zip archives.
- # Current location of the agent.
- use constant AGENT_RUN_DIR => getcwd();
- # Load our config file values
- use constant AGENT_KEY => $Cfg::Config{key};
- use constant AGENT_IP => $Cfg::Config{listen_ip};
- use constant AGENT_LOG_FILE => $Cfg::Config{logfile};
- use constant AGENT_PORT => $Cfg::Config{listen_port};
- use constant AGENT_VERSION => $Cfg::Config{version};
- use constant SCREEN_LOG_LOCAL => $Cfg::Preferences{screen_log_local};
- use constant DELETE_LOGS_AFTER => $Cfg::Preferences{delete_logs_after};
- use constant AGENT_PID_FILE =>
- Path::Class::File->new(AGENT_RUN_DIR, 'ogp_agent.pid');
- use constant STEAM_LICENSE_OK => "Accept";
- use constant STEAM_LICENSE => $Cfg::Config{steam_license};
- use constant MANUAL_TMP_DIR => Path::Class::Dir->new(AGENT_RUN_DIR, 'tmp');
- use constant STEAMCMD_CLIENT_DIR => Path::Class::Dir->new(AGENT_RUN_DIR, 'steamcmd');
- use constant STEAMCMD_CLIENT_BIN =>
- Path::Class::File->new(STEAMCMD_CLIENT_DIR, 'steamcmd.sh');
- use constant SCREEN_LOGS_DIR =>
- Path::Class::Dir->new(AGENT_RUN_DIR, 'screenlogs');
- use constant GAME_STARTUP_DIR =>
- Path::Class::Dir->new(AGENT_RUN_DIR, 'startups');
- use constant SCREENRC_FILE =>
- Path::Class::File->new(AGENT_RUN_DIR, 'ogp_screenrc');
- use constant SCREENRC_TMP_FILE =>
- Path::Class::File->new(AGENT_RUN_DIR, 'ogp_screenrc.tmp');
- use constant SCREEN_TYPE_HOME => "HOME";
- use constant SCREEN_TYPE_UPDATE => "UPDATE";
- use constant FD_DIR => Path::Class::Dir->new(AGENT_RUN_DIR, 'FastDownload');
- use constant FD_ALIASES_DIR => Path::Class::Dir->new(FD_DIR, 'aliases');
- use constant FD_PID_FILE => Path::Class::File->new(FD_DIR, 'fd.pid');
- use constant SCHED_PID => Path::Class::File->new(AGENT_RUN_DIR, 'scheduler.pid');
- use constant SCHED_TASKS => Path::Class::File->new(AGENT_RUN_DIR, 'scheduler.tasks');
- use constant SCHED_LOG_FILE => Path::Class::File->new(AGENT_RUN_DIR, 'scheduler.log');
- $Cfg::Config{sudo_password} =~ s/('+)/'\"$1\"'/g;
- our $SUDOPASSWD = $Cfg::Config{sudo_password};
- my $no_startups = 0;
- my $clear_startups = 0;
- our $log_std_out = 0;
- GetOptions(
- 'no-startups' => \$no_startups,
- 'clear-startups' => \$clear_startups,
- 'log-stdout' => \$log_std_out
- );
- # Starting the agent as root user is not supported anymore.
- if ($< == 0)
- {
- print "ERROR: You are trying to start the agent as root user.";
- print "This is not currently supported. If you wish to start the";
- print "you need to create a normal user account for it.";
- exit 1;
- }
- ### Logger function.
- ### @param line the line that is put to the log file.
- sub logger
- {
- my $logcmd = $_[0];
- my $also_print = 0;
- if (@_ == 2)
- {
- ($also_print) = $_[1];
- }
- $logcmd = localtime() . " $logcmd\n";
- if ($log_std_out == 1)
- {
- print "$logcmd";
- return;
- }
- if ($also_print == 1)
- {
- print "$logcmd";
- }
- open(LOGFILE, '>>', AGENT_LOG_FILE)
- or die("Can't open " . AGENT_LOG_FILE . " - $!");
- flock(LOGFILE, LOCK_EX) or die("Failed to lock log file.");
- seek(LOGFILE, 0, 2) or die("Failed to seek to end of file.");
- print LOGFILE "$logcmd" or die("Failed to write to log file.");
- flock(LOGFILE, LOCK_UN) or die("Failed to unlock log file.");
- close(LOGFILE) or die("Failed to close log file.");
- }
- # Rotate the log file
- if (-e AGENT_LOG_FILE)
- {
- if (-e AGENT_LOG_FILE . ".bak")
- {
- unlink(AGENT_LOG_FILE . ".bak");
- }
- logger "Rotating log file";
- move(AGENT_LOG_FILE, AGENT_LOG_FILE . ".bak");
- logger "New log file created";
- }
- open INPUTFILE, "<", SCREENRC_FILE or die $!;
- open OUTPUTFILE, ">", SCREENRC_TMP_FILE or die $!;
- my $dest = SCREEN_LOGS_DIR . "/screenlog.%t";
- while (<INPUTFILE>)
- {
- $_ =~ s/logfile.*/logfile $dest/g;
- print OUTPUTFILE $_;
- }
- close INPUTFILE;
- close OUTPUTFILE;
- unlink SCREENRC_FILE;
- move(SCREENRC_TMP_FILE,SCREENRC_FILE);
- # Check the screen logs folder
- if (!-d SCREEN_LOGS_DIR && !mkdir SCREEN_LOGS_DIR)
- {
- logger "Could not create " . SCREEN_LOGS_DIR . " directory $!.", 1;
- exit -1;
- }
- if (check_steam_cmd_client() == -1)
- {
- print "ERROR: You must download and uncompress the new steamcmd package.";
- print "BE SURE TO INSTALL IT IN " . AGENT_RUN_DIR . "/steamcmd directory,";
- print "so it can be managed by the agent to install servers.";
- exit 1;
- }
- # create the directory for startup flags
- if (!-e GAME_STARTUP_DIR)
- {
- logger "Creating the startups directory " . GAME_STARTUP_DIR . "";
- if (!mkdir GAME_STARTUP_DIR)
- {
- my $message =
- "Failed to create the "
- . GAME_STARTUP_DIR
- . " directory - check permissions. Errno: $!";
- logger $message, 1;
- exit 1;
- }
- }
- elsif ($clear_startups)
- {
- opendir(STARTUPDIR, GAME_STARTUP_DIR);
- while (my $startup_file = readdir(STARTUPDIR))
- {
- # Skip . and ..
- next if $startup_file =~ /^\./;
- $startup_file = Path::Class::File->new(GAME_STARTUP_DIR, $startup_file);
- logger "Removing " . $startup_file . ".";
- unlink($startup_file);
- }
- closedir(STARTUPDIR);
- }
- # If the directory already existed check if we need to start some games.
- elsif ($no_startups != 1)
- {
- # Loop through all the startup flags, and call universal startup
- opendir(STARTUPDIR, GAME_STARTUP_DIR);
- logger "Reading startup flags from " . GAME_STARTUP_DIR . "";
- while (my $dirlist = readdir(STARTUPDIR))
- {
- # Skip . and ..
- next if $dirlist =~ /^\./;
- logger "Found $dirlist";
- open(STARTFILE, '<', Path::Class::Dir->new(GAME_STARTUP_DIR, $dirlist))
- || logger "Error opening start flag $!";
- while (<STARTFILE>)
- {
- my (
- $home_id, $home_path, $server_exe,
- $run_dir, $startup_cmd, $server_port,
- $server_ip, $cpu, $nice, $preStart, $envVars
- ) = split(',', $_);
- if (is_screen_running_without_decrypt(SCREEN_TYPE_HOME, $home_id) ==
- 1)
- {
- logger
- "This server ($server_exe on $server_ip : $server_port) is already running (ID: $home_id).";
- next;
- }
- logger "Starting server_exe $server_exe from home $home_path.";
- universal_start_without_decrypt(
- $home_id, $home_path, $server_exe,
- $run_dir, $startup_cmd, $server_port,
- $server_ip, $cpu, $nice, $preStart, $envVars
- );
- }
- close(STARTFILE);
- }
- closedir(STARTUPDIR);
- }
- # Create the pid file
- open(PID, '>', AGENT_PID_FILE)
- or die("Can't write to pid file - " . AGENT_PID_FILE . "\n");
- print PID "$$\n";
- close(PID);
- logger "Open Game Panel - Agent started - "
- . AGENT_VERSION
- . " - port "
- . AGENT_PORT
- . " - PID $$", 1;
- # Stop previous scheduler process if exists
- scheduler_stop();
- # Create new object with default dispatcher for scheduled tasks
- my $cron = new Schedule::Cron( \&scheduler_dispatcher, {
- nofork => 1,
- loglevel => 0,
- log => sub { print $_[1], "\n"; }
- } );
- $cron->add_entry( "* * * * * *", \&scheduler_read_tasks );
- # Run scheduler
- $cron->run( {detach=>1, pid_file=>SCHED_PID} );
- if(-e Path::Class::File->new(FD_DIR, 'Settings.pm'))
- {
- require "FastDownload/Settings.pm"; # Settings for Fast Download Daemon.
- if(defined($FastDownload::Settings{autostart_on_agent_startup}) && $FastDownload::Settings{autostart_on_agent_startup} eq "1")
- {
- start_fastdl();
- }
- }
- my $d = Frontier::Daemon::Forking->new(
- methods => {
- is_screen_running => \&is_screen_running,
- universal_start => \&universal_start,
- renice_process => \&renice_process,
- cpu_count => \&cpu_count,
- rfile_exists => \&rfile_exists,
- quick_chk => \&quick_chk,
- steam_cmd => \&steam_cmd,
- fetch_steam_version => \&fetch_steam_version,
- installed_steam_version => \&installed_steam_version,
- automatic_steam_update => \&automatic_steam_update,
- get_log => \&get_log,
- stop_server => \&stop_server,
- send_rcon_command => \&send_rcon_command,
- dirlist => \&dirlist,
- dirlistfm => \&dirlistfm,
- readfile => \&readfile,
- writefile => \&writefile,
- rebootnow => \&rebootnow,
- what_os => \&what_os,
- start_file_download => \&start_file_download,
- lock_additional_files => \&lock_additional_files,
- is_file_download_in_progress => \&is_file_download_in_progress,
- uncompress_file => \&uncompress_file,
- discover_ips => \&discover_ips,
- mon_stats => \&mon_stats,
- exec => \&exec,
- clone_home => \&clone_home,
- remove_home => \&remove_home,
- start_rsync_install => \&start_rsync_install,
- rsync_progress => \&rsync_progress,
- restart_server => \&restart_server,
- sudo_exec => \&sudo_exec,
- master_server_update => \&master_server_update,
- secure_path => \&secure_path,
- get_chattr => \&get_chattr,
- ftp_mgr => \&ftp_mgr,
- compress_files => \&compress_files,
- stop_fastdl => \&stop_fastdl,
- restart_fastdl => \&restart_fastdl,
- fastdl_status => \&fastdl_status,
- fastdl_get_aliases => \&fastdl_get_aliases,
- fastdl_add_alias => \&fastdl_add_alias,
- fastdl_del_alias => \&fastdl_del_alias,
- fastdl_get_info => \&fastdl_get_info,
- fastdl_create_config => \&fastdl_create_config,
- agent_restart => \&agent_restart,
- scheduler_add_task => \&scheduler_add_task,
- scheduler_del_task => \&scheduler_del_task,
- scheduler_list_tasks => \&scheduler_list_tasks,
- scheduler_edit_task => \&scheduler_edit_task,
- get_file_part => \&get_file_part,
- stop_update => \&stop_update,
- shell_action => \&shell_action,
- remote_query => \&remote_query
- },
- debug => 4,
- LocalPort => AGENT_PORT,
- LocalAddr => AGENT_IP,
- ReuseAddr => '1'
- ) or die "Couldn't start OGP Agent: $!";
- sub backup_home_log
- {
- my ($home_id, $log_file) = @_;
-
- my $home_backup_dir = SCREEN_LOGS_DIR . "/home_id_" . $home_id;
-
- if( ! -e $home_backup_dir )
- {
- if( ! mkdir $home_backup_dir )
- {
- logger "Can not create a backup directory at $home_backup_dir.";
- return 1;
- }
- }
-
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
-
- my $backup_file_name = $mday . $mon . $year . '_' . $hour . 'h' . $min . 'm' . $sec . "s.log";
-
- my $output_path = $home_backup_dir . "/" . $backup_file_name;
-
- # Used for deleting log files older than DELETE_LOGS_AFTER
- my @file_list;
- my @find_dirs; # directories to search
- my $now = time(); # get current time
- my $days;
- if((DELETE_LOGS_AFTER =~ /^[+-]?\d+$/) && (DELETE_LOGS_AFTER > 0)){
- $days = DELETE_LOGS_AFTER; # how many days old
- }else{
- $days = 30; # how many days old
- }
- my $seconds_per_day = 60*60*24; # seconds in a day
- my $AGE = $days*$seconds_per_day; # age in seconds
- push (@find_dirs, $home_backup_dir);
-
- # Create local copy of log file backup in the log_backups folder and current user home directory if SCREEN_LOG_LOCAL = 1
- if(SCREEN_LOG_LOCAL == 1)
- {
- # Create local backups folder
- my $local_log_folder = Path::Class::Dir->new("logs_backup");
-
- if(!-e $local_log_folder){
- mkdir($local_log_folder);
- }
-
- # Add full path to @find_dirs so that log files older than DELETE_LOGS_AFTER are deleted
- my $fullpath_to_local_logs = Path::Class::Dir->new(getcwd(), "logs_backup");
- push (@find_dirs, $fullpath_to_local_logs);
-
- my $log_local = $local_log_folder . "/" . $backup_file_name;
-
- # Delete the local log file if it already exists
- if(-e $log_local){
- unlink $log_local;
- }
-
- # If the log file contains UPDATE in the filename, do not allow users to see it since it will contain steam credentials
- # Will return -1 for not existing
- my $isUpdate = index($log_file,SCREEN_TYPE_UPDATE);
-
- if($isUpdate == -1){
- copy($log_file,$log_local);
- }
- }
-
- # Delete all files in @find_dirs older than DELETE_LOGS_AFTER days
- find ( sub {
- my $file = $File::Find::name;
- if ( -f $file ) {
- push (@file_list, $file);
- }
- }, @find_dirs);
-
- for my $file (@file_list) {
- my @stats = stat($file);
- if ($now-$stats[9] > $AGE) {
- unlink $file;
- }
- }
-
- move($log_file,$output_path);
-
- return 0;
- }
- sub get_home_pids
- {
- my ($home_id) = @_;
- my $screen_id = create_screen_id(SCREEN_TYPE_HOME, $home_id);
- my ($pid, @pids);
- ($pid) = split(/\./, `screen -ls | grep -E -o "[0-9]+\.$screen_id"`, 2);
- chomp($pid);
- while ($pid =~ /^[0-9]+$/)
- {
- push(@pids,$pid);
- $pid = `pgrep -P $pid`;
- chomp($pid);
- }
- return @pids;
- }
- sub create_screen_id
- {
- my ($screen_type, $home_id) = @_;
- return sprintf("OGP_%s_%09d", $screen_type, $home_id);
- }
- sub create_screen_cmd
- {
- my ($screen_id, $exec_cmd) = @_;
- $exec_cmd = replace_OGP_Vars($screen_id, $exec_cmd);
-
- return
- sprintf('export WINEDEBUG="fixme-all" && export DISPLAY=:1 && screen -d -m -t "%1$s" -c ' . SCREENRC_FILE . ' -S %1$s %2$s',
- $screen_id, $exec_cmd);
- }
- sub create_screen_cmd_loop
- {
- my ($screen_id, $exec_cmd, $envVars, $skipLoop) = @_;
- my $server_start_bashfile = $screen_id . "_startup_scr.sh";
-
- $exec_cmd = replace_OGP_Vars($screen_id, $exec_cmd);
-
- # Allow file to be overwritten
- if(-e $server_start_bashfile){
- secure_path_without_decrypt('chattr-i', $server_start_bashfile);
- }
-
- # Create bash file that screen will run which spawns the server
- # If it crashes without user intervention, it will restart
- open (SERV_START_SCRIPT, '>', $server_start_bashfile);
-
- my $respawn_server_command = "#!/bin/bash" . "\n";
-
- if(!$skipLoop){
- $respawn_server_command .= "function startServer(){" . "\n";
- }
-
- if(defined $envVars && $envVars ne ""){
- $respawn_server_command .= $envVars;
- }
-
- if(!$skipLoop){
- $respawn_server_command .= "NUMSECONDS=`expr \$(date +%s)`" . "\n"
- . "until " . $exec_cmd . "; do" . "\n"
- . "let DIFF=(`date +%s` - \"\$NUMSECONDS\")" . "\n"
- . "if [ \"\$DIFF\" -gt 15 ]; then" . "\n"
- . "NUMSECONDS=`expr \$(date +%s)`" . "\n"
- . "echo \"Server '" . $exec_cmd . "' crashed with exit code \$?. Respawning...\" >&2 " . "\n"
- . "fi" . "\n"
- . "sleep 3" . "\n"
- . "done" . "\n"
- . "let DIFF=(`date +%s` - \"\$NUMSECONDS\")" . "\n"
-
- . "if [ ! -e \"SERVER_STOPPED\" ] && [ \"\$DIFF\" -gt 15 ]; then" . "\n"
- . "startServer" . "\n"
- . "fi" . "\n"
- . "}" . "\n"
- . "startServer" . "\n";
- }else{
- $respawn_server_command .= $exec_cmd . "\n";
- }
-
- print SERV_START_SCRIPT $respawn_server_command;
- close (SERV_START_SCRIPT);
-
- # Secure file
- secure_path_without_decrypt('chattr+i', $server_start_bashfile);
-
- my $screen_exec_script = "bash " . $server_start_bashfile;
-
- return
- sprintf('export WINEDEBUG="fixme-all" && export DISPLAY=:1 && screen -d -m -t "%1$s" -c ' . SCREENRC_FILE . ' -S %1$s %2$s',
- $screen_id, $screen_exec_script);
- }
- sub replace_OGP_Vars{
- # This function replaces constants from game server XML Configs with OGP paths for Steam Auto Updates for example
- my ($screen_id, $exec_cmd) = @_;
- my $screen_id_for_txt_update = substr ($screen_id, rindex($screen_id, '_') + 1);
- my $steamInsFile = $screen_id_for_txt_update . "_install.txt";
- my $steamCMDPath = STEAMCMD_CLIENT_DIR;
- my $fullPath = Path::Class::File->new($steamCMDPath, $steamInsFile);
-
- # If the install file exists, the game can be auto updated, else it will be ignored by the game for improper syntax
- # To generate the install file, the "Install/Update via Steam" button must be clicked on at least once!
- if(-e $fullPath){
- $exec_cmd =~ s/{OGP_STEAM_CMD_DIR}/$steamCMDPath/g;
- $exec_cmd =~ s/{STEAMCMD_INSTALL_FILE}/$steamInsFile/g;
- }
-
- return $exec_cmd;
- }
- sub handle_lock_command_line{
- my ($command) = @_;
- if(defined $command && $command ne ""){
- if ($command =~ m/{OGP_LOCK_FILE}/) {
- $command =~ s/{OGP_LOCK_FILE}\s*//g;
- return secure_path_without_decrypt("chattr+i", $command);
- }
- }
-
- return 0;
- }
- sub replace_OGP_Env_Vars{
- # This function replaces constants from environment variables set in the XML
- my ($homeid, $homepath, $strToReplace) = @_;
- $strToReplace =~ s/{OGP_HOME_DIR}/$homepath/g;
-
- return $strToReplace;
- }
- sub encode_list
- {
- my $encoded_content = '';
- if(@_)
- {
- foreach my $line (@_)
- {
- $encoded_content .= encode_base64($line, "") . '\n';
- }
- }
- return $encoded_content;
- }
- sub decrypt_param
- {
- my ($param) = @_;
- $param = decode_base64($param);
- $param = Crypt::XXTEA::decrypt($param, AGENT_KEY);
- $param = decode_base64($param);
- return $param;
- }
- sub decrypt_params
- {
- my @params;
- foreach my $param (@_)
- {
- $param = &decrypt_param($param);
- push(@params, $param);
- }
- return @params;
- }
- sub check_steam_cmd_client
- {
- if (STEAM_LICENSE ne STEAM_LICENSE_OK)
- {
- logger "Steam license not accepted, stopping Steam client check.";
- return 0;
- }
- if (!-d STEAMCMD_CLIENT_DIR && !mkdir STEAMCMD_CLIENT_DIR)
- {
- logger "Could not create " . STEAMCMD_CLIENT_DIR . " directory $!.", 1;
- exit -1;
- }
- if (!-w STEAMCMD_CLIENT_DIR)
- {
- logger "Steam client dir '"
- . STEAMCMD_CLIENT_DIR
- . "' not writable. Unable to get Steam client.";
- return -1;
- }
- if (!-f STEAMCMD_CLIENT_BIN)
- {
- logger "The Steam client, steamcmd, does not exist yet, installing...";
- my $steam_client_file = 'steamcmd_linux.tar.gz';
- my $steam_client_path = Path::Class::File->new(STEAMCMD_CLIENT_DIR, $steam_client_file);
- my $steam_client_url =
- "http://media.steampowered.com/client/" . $steam_client_file;
- logger "Downloading the Steam client from $steam_client_url to '"
- . $steam_client_path . "'.";
-
- my $ua = LWP::UserAgent->new;
- $ua->agent('Mozilla/5.0');
- my $response = $ua->get($steam_client_url, ':content_file' => "$steam_client_path");
-
- unless ($response->is_success)
- {
- logger "Failed to download steam installer from "
- . $steam_client_url
- . ".", 1;
- return -1;
- }
- if (-f $steam_client_path)
- {
- logger "Uncompressing $steam_client_path";
- if ( uncompress_file_without_decrypt($steam_client_path, STEAMCMD_CLIENT_DIR) != 1 )
- {
- unlink($steam_client_path);
- logger "Unable to uncompress $steam_client_path, the file has been removed.";
- return -1;
- }
- unlink($steam_client_path);
- }
- }
- if (!-x STEAMCMD_CLIENT_BIN)
- {
- if ( ! chmod 0755, STEAMCMD_CLIENT_BIN )
- {
- logger "Unable to apply execution permission to ".STEAMCMD_CLIENT_BIN.".";
- }
- }
- return 1;
- }
- sub is_screen_running
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($screen_type, $home_id) = decrypt_params(@_);
- return is_screen_running_without_decrypt($screen_type, $home_id);
- }
- sub is_screen_running_without_decrypt
- {
- my ($screen_type, $home_id) = @_;
- my $screen_id = create_screen_id($screen_type, $home_id);
- my $is_running = `screen -list | grep $screen_id`;
- if ($is_running =~ /^\s*$/)
- {
- return 0;
- }
- else
- {
- return 1;
- }
- }
- # Delete Server Stopped Status File:
- sub deleteStoppedStatFile
- {
- my ($home_path) = @_;
- my $server_stop_status_file = Path::Class::File->new($home_path, "SERVER_STOPPED");
- if(-e $server_stop_status_file)
- {
- unlink $server_stop_status_file;
- }
- }
- # Universal startup function
- sub universal_start
- {
- chomp(@_);
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return universal_start_without_decrypt(decrypt_params(@_));
- }
- # Split to two parts because of internal calls.
- sub universal_start_without_decrypt
- {
- my (
- $home_id, $home_path, $server_exe, $run_dir,
- $startup_cmd, $server_port, $server_ip, $cpu, $nice, $preStart, $envVars
- ) = @_;
-
- # Replace any {OGP_HOME_DIR} in the $start_cmd with the server's home directory path
- $startup_cmd = replace_OGP_Env_Vars($home_id, $home_path, $startup_cmd);
-
- if (is_screen_running_without_decrypt(SCREEN_TYPE_HOME, $home_id) == 1)
- {
- logger "This server is already running (ID: $home_id).";
- return -14;
- }
-
- if (!-e $home_path)
- {
- logger "Can't find server's install path [ $home_path ].";
- return -10;
- }
-
- my $uid = `id -u`;
- chomp $uid;
- my $gid = `id -g`;
- chomp $gid;
- my $path = $home_path;
- $path =~ s/('+)/'\"$1\"'/g;
- sudo_exec_without_decrypt('chown -Rf '.$uid.':'.$gid.' \''.$path.'\'');
-
- # Some game require that we are in the directory where the binary is.
- my $game_binary_dir = Path::Class::Dir->new($home_path, $run_dir);
- if ( -e $game_binary_dir && !chdir $game_binary_dir)
- {
- logger "Could not change to server binary directory $game_binary_dir.";
- return -12;
- }
-
- secure_path_without_decrypt('chattr-i', $server_exe);
-
- if (!-x $server_exe)
- {
- if (!chmod 0755, $server_exe)
- {
- logger "The $server_exe file is not executable.";
- return -13;
- }
- }
-
- if(defined $preStart && $preStart ne ""){
- # Get it in the format that the startup file can use
- $preStart = multiline_to_startup_comma_format($preStart);
- }else{
- $preStart = "";
- }
-
- if(defined $envVars && $envVars ne ""){
- # Replace variables in the envvars if they exist
- my @prestartenvvars = split /[\r\n]+/, $envVars;
- my $envVarStr = "";
- foreach my $line (@prestartenvvars) {
- $line = replace_OGP_Env_Vars($home_id, $home_path, $line);
- if($line ne ""){
- logger "Configuring environment variable: $line";
- $envVarStr .= "$line\n";
- }
- }
-
- if(defined $envVarStr && $envVarStr ne ""){
- $envVars = $envVarStr;
- }
-
- # Get it in the format that the startup file can use
- $envVars = multiline_to_startup_comma_format($envVars);
- }else{
- $envVars = "";
- }
-
- secure_path_without_decrypt('chattr+i', $server_exe);
-
- # Create startup file for the server.
- my $startup_file =
- Path::Class::File->new(GAME_STARTUP_DIR, "$server_ip-$server_port");
- if (open(STARTUP, '>', $startup_file))
- {
- print STARTUP
- "$home_id,$home_path,$server_exe,$run_dir,$startup_cmd,$server_port,$server_ip,$cpu,$nice,$preStart,$envVars";
- logger "Created startup flag for $server_ip-$server_port";
- close(STARTUP);
- }
- else
- {
- logger "Cannot create file in " . $startup_file . " : $!";
- }
-
- if(defined $preStart && $preStart ne ""){
- # Get it in the format that the startup file can use
- $preStart = startup_comma_format_to_multiline($preStart);
- }else{
- $preStart = "";
- }
-
- if(defined $envVars && $envVars ne ""){
- # Get it in the format that the startup file can use
- $envVars = startup_comma_format_to_multiline($envVars);
- }else{
- $envVars = "";
- }
-
- # Create the startup string.
- my $screen_id = create_screen_id(SCREEN_TYPE_HOME, $home_id);
- my $file_extension = substr $server_exe, -4;
- my $cli_bin;
- my $command;
- my $run_before_start;
-
- if($file_extension eq ".exe" or $file_extension eq ".bat")
- {
- $command = "wine $server_exe $startup_cmd";
-
- if ($cpu ne 'NA')
- {
- $command = "taskset -c $cpu wine $server_exe $startup_cmd";
- }
-
- if(defined($Cfg::Preferences{ogp_autorestart_server}) && $Cfg::Preferences{ogp_autorestart_server} eq "1"){
- deleteStoppedStatFile($home_path);
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars);
- }else{
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars, 1);
- }
- }
- elsif($file_extension eq ".jar")
- {
- $command = "$startup_cmd";
-
- if ($cpu ne 'NA')
- {
- $command = "taskset -c $cpu $startup_cmd";
- }
-
- if(defined($Cfg::Preferences{ogp_autorestart_server}) && $Cfg::Preferences{ogp_autorestart_server} eq "1"){
- deleteStoppedStatFile($home_path);
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars);
- }else{
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars, 1);
- }
- }
- else
- {
- $command = "./$server_exe $startup_cmd";
-
- if ($cpu ne 'NA')
- {
- $command = "taskset -c $cpu ./$server_exe $startup_cmd";
- }
-
- if(defined($Cfg::Preferences{ogp_autorestart_server}) && $Cfg::Preferences{ogp_autorestart_server} eq "1"){
- deleteStoppedStatFile($home_path);
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars);
- }else{
- $cli_bin = create_screen_cmd_loop($screen_id, $command, $envVars, 1);
- }
- }
-
- my $log_file = Path::Class::File->new(SCREEN_LOGS_DIR, "screenlog.$screen_id");
- backup_home_log( $home_id, $log_file );
-
- logger
- "Startup command [ $cli_bin ] will be executed in dir $game_binary_dir.";
-
- # Run before start script
- $run_before_start = run_before_start_commands($home_id, $home_path, $preStart);
-
- system($cli_bin);
-
- sleep(1);
-
- renice_process_without_decrypt($home_id, $nice);
-
- chdir AGENT_RUN_DIR;
- return 1;
- }
- # This is used to change the priority of process
- # @return 1 if successfully set prosess priority
- # @return -1 in case of an error.
- sub renice_process
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return renice_process_without_decrypt(decrypt_params(@_));
- }
- sub renice_process_without_decrypt
- {
- my ($home_id, $nice) = @_;
- if ($nice != 0)
- {
- my @pids = get_home_pids($home_id);
- logger
- "Renicing pids [ @pids ] from home_id $home_id with nice value $nice.";
- foreach my $pid (@pids)
- {
- my $rpid = kill 0, $pid;
- if ($rpid == 1)
- {
- my $ret = sudo_exec_without_decrypt('/usr/bin/renice '.$nice.' '.$pid);
- ($ret) = split(/;/, $ret, 2);
- if($ret != 1)
- {
- logger "Unable to renice process, probably bad sudo password or not in sudoers list.";
- return -1
- }
- }
- }
- }
- return 1;
- }
- # This is used to force a process to run on a particular CPU
- sub force_cpu
- {
- return force_cpu_without_decrypt(decrypt_params(@_));
- }
- sub force_cpu_without_decrypt
- {
- my ($home_id, $cpu) = @_;
- if ($cpu ne 'NA')
- {
- my @pids = get_home_pids($home_id);
- logger
- "Setting server from home_id $home_id with pids @pids to run on CPU $cpu.";
- foreach my $pid (@pids)
- {
- my $rpid = kill 0, $pid;
- if ($rpid == 1)
- {
- my $ret = sudo_exec_without_decrypt('/usr/bin/taskset -pc '.$cpu.' '.$pid);
- ($ret) = split(/;/, $ret, 2);
- if($ret != 1)
- {
- logger "Unable to set cpu, probably a bad sudo password or not in sudoers list.";
- return -1
- }
- }
- }
- }
- return 1;
- }
- # Returns the number of CPUs available.
- sub cpu_count
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- if (!-e "/proc/cpuinfo")
- {
- return "ERROR - Missing /proc/cpuinfo";
- }
- open(CPUINFO, '<', "/proc/cpuinfo")
- or return "ERROR - Cannot open /proc/cpuinfo";
- my $cpu_count = 0;
- while (<CPUINFO>)
- {
- chomp;
- next if $_ !~ /^processor/;
- $cpu_count++;
- }
- close(CPUINFO);
- return "$cpu_count";
- }
- ### File exists check ####
- # Simple a way to check if a file exists using the remote agent
- #
- # @return 0 when file exists.
- # @return 1 when file does not exist.
- sub rfile_exists
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- chdir AGENT_RUN_DIR;
- my $checkFile = decrypt_param(@_);
- if (-e $checkFile)
- {
- return 0;
- }
- else
- {
- return 1;
- }
- }
- #### Quick check to verify agent is up and running
- # Used to quickly see if the agent is online, and if the keys match.
- # The message that is sent to the agent must be hello, if not then
- # it is intrepret as encryption key missmatch.
- #
- # @return 1 when encrypted message is not 'hello'
- # @return 0 when check is ok.
- sub quick_chk
- {
- my $dec_check = &decrypt_param(@_);
- if ($dec_check ne 'hello')
- {
- logger "ERROR - Encryption key mismatch! Returning 1 to asker.";
- return 1;
- }
- return 0;
- }
- ### Return -10 If home path is not found.
- ### Return -9 If log type was invalid.
- ### Return -8 If log file was not found.
- ### 0 reserved for connection problems.
- ### Return 1;content If log found and screen running.
- ### Return 2;content If log found but screen is not running.
- sub get_log
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($screen_type, $home_id, $home_path, $nb_of_lines, $log_file) = decrypt_params(@_);
- if (!chdir $home_path)
- {
- logger "Can't change to server's install path [ $home_path ].";
- return -10;
- }
- if ( ($screen_type eq SCREEN_TYPE_UPDATE)
- && ($screen_type eq SCREEN_TYPE_HOME))
- {
- logger "Invalid screen type '$screen_type'.";
- return -9;
- }
- if(!$log_file)
- {
- my $screen_id = create_screen_id($screen_type, $home_id);
- $log_file = Path::Class::File->new(SCREEN_LOGS_DIR, "screenlog.$screen_id");
- }
- else
- {
- $log_file = Path::Class::File->new($home_path, $log_file);
- }
-
- chmod 0644, $log_file;
-
- # Create local copy of current log file if SCREEN_LOG_LOCAL = 1
- if(SCREEN_LOG_LOCAL == 1)
- {
- my $log_local = Path::Class::File->new($home_path, "LOG_$screen_type.txt");
- if ( -e $log_local )
- {
- unlink $log_local;
- }
-
- # Copy log file only if it's not an UPDATE type as it may contain steam credentials
- if($screen_type eq SCREEN_TYPE_HOME){
- copy($log_file, $log_local);
- }
- }
-
- # Regenerate the log file if it doesn't exist
- unless ( -e $log_file )
- {
- if (open(NEWLOG, '>', $log_file))
- {
- logger "Log file missing, regenerating: " . $log_file;
- print NEWLOG "Log file missing, started new log\n";
- close(NEWLOG);
- }
- else
- {
- logger "Cannot regenerate log file in " . $log_file . " : $!";
- return -8;
- }
- }
-
- # Return a few lines of output to the web browser
- my(@modedlines) = `tail -n $nb_of_lines $log_file`;
-
- my $linecount = 0;
-
- foreach my $line (@modedlines) {
- #Text replacements to remove the Steam user login from steamcmd logs for security reasons.
- $line =~ s/login .*//g;
- $line =~ s/Logging .*//g;
- $line =~ s/set_steam_guard_code.*//g;
- $line =~ s/force_install_dir.*//g;
- #Text replacements to remove empty lines.
- $line =~ s/^ +//g;
- $line =~ s/^\t+//g;
- $line =~ s/^\e+//g;
- #Remove � from console output when master server update is running.
- $line =~ s/�//g;
- $modedlines[$linecount]=$line;
- $linecount++;
- }
-
- my $encoded_content = encode_list(@modedlines);
- chdir AGENT_RUN_DIR;
- if(is_screen_running_without_decrypt($screen_type, $home_id) == 1)
- {
- return "1;" . $encoded_content;
- }
- else
- {
- return "2;" . $encoded_content;
- }
- }
- # stop server function
- sub stop_server
- {
- chomp(@_);
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return stop_server_without_decrypt(decrypt_params(@_));
- }
- ##### Stop server without decrypt
- ### Return 1 when error occurred on decryption.
- ### Return 0 on success
- sub stop_server_without_decrypt
- {
- my ($home_id, $server_ip, $server_port, $control_protocol,
- $control_password, $control_type, $home_path) = @_;
-
- my $startup_file = Path::Class::File->new(GAME_STARTUP_DIR, "$server_ip-$server_port");
-
- if (-e $startup_file)
- {
- logger "Removing startup flag " . $startup_file . "";
- unlink($startup_file)
- or logger "Cannot remove the startup flag file $startup_file $!";
- }
-
- # Create file indicator that the game server has been stopped if defined
- if(defined($Cfg::Preferences{ogp_autorestart_server}) && $Cfg::Preferences{ogp_autorestart_server} eq "1"){
-
- # Get current directory and chdir into the game's home dir
- my $curDir = getcwd();
- chdir $home_path;
- # Create stopped indicator file used by autorestart of OGP if server crashes
- open(STOPFILE, '>', "SERVER_STOPPED");
- close(STOPFILE);
-
- # Return to original directory
- chdir $curDir;
- }
-
- # Some validation checks for the variables.
- if ($server_ip =~ /^\s*$/ || $server_port < 0 || $server_port > 65535)
- {
- logger("Invalid IP:Port given $server_ip:$server_port.");
- return 1;
- }
- if ($control_password !~ /^\s*$/ and $control_protocol ne "")
- {
- if ($control_protocol eq "rcon")
- {
- use KKrcon::KKrcon;
- my $rcon = new KKrcon(
- Password => $control_password,
- Host => $server_ip,
- Port => $server_port,
- Type => $control_type
- );
- my $rconCommand = "quit";
- $rcon->execute($rconCommand);
- }
- elsif ($control_protocol eq "rcon2")
- {
- use KKrcon::HL2;
- my $rcon2 = new HL2(
- hostname => $server_ip,
- port => $server_port,
- password => $control_password,
- timeout => 2
- );
- my $rconCommand = "quit";
- $rcon2->run($rconCommand);
- }
-
- if (is_screen_running_without_decrypt(SCREEN_TYPE_HOME, $home_id) == 0)
- {
- logger "Stopped server $server_ip:$server_port with rcon quit.";
- return 0;
- }
- else
- {
- logger "Failed to send rcon quit. Stopping server with kill command.";
- }
- my @server_pids = get_home_pids($home_id);
-
- my $cnt;
- foreach my $pid (@server_pids)
- {
- chomp($pid);
- $cnt = kill 15, $pid;
-
- if ($cnt != 1)
- {
- $cnt = kill 9, $pid;
- if ($cnt == 1)
- {
- logger "Stopped process with pid $pid successfully using kill 9.";
- }
- else
- {
- logger "Process $pid can not be stopped.";
- }
- }
- else
- {
- logger "Stopped process with pid $pid successfully using kill 15.";
- }
- }
- system('screen -wipe > /dev/null 2>&1');
- return 0;
- }
- else
- {
- logger "Remote control protocol not available or PASSWORD NOT SET. Using kill signal instead.";
- my @server_pids = get_home_pids($home_id);
-
- my $cnt;
- foreach my $pid (@server_pids)
- {
- chomp($pid);
- $cnt = kill 15, $pid;
-
- if ($cnt != 1)
- {
- $cnt = kill 9, $pid;
- if ($cnt == 1)
- {
- logger "Stopped process with pid $pid successfully using kill 9.";
- }
- else
- {
- logger "Process $pid can not be stopped.";
- }
- }
- else
- {
- logger "Stopped process with pid $pid successfully using kill 15.";
- }
- }
- system('screen -wipe > /dev/null 2>&1');
- return 0;
- }
- }
- ##### Send RCON command
- ### Return 0 when error occurred on decryption.
- ### Return 1 on success
- sub send_rcon_command
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($home_id, $server_ip, $server_port, $control_protocol,
- $control_password, $control_type, $rconCommand) = decrypt_params(@_);
- # legacy console
- if ($control_protocol eq "lcon")
- {
- my $screen_id = create_screen_id(SCREEN_TYPE_HOME, $home_id);
- system('screen -S '.$screen_id.' -p 0 -X stuff "'.$rconCommand.'$(printf \\\\r)"');
- logger "Sending legacy console command to ".$screen_id.": \n$rconCommand \n .";
- if ($? == -1)
- {
- my(@modedlines) = "$rconCommand";
- my $encoded_content = encode_list(@modedlines);
- return "1;" . $encoded_content;
- }
- return 0;
- }
-
- # Some validation checks for the variables.
- if ($server_ip =~ /^\s*$/ || $server_port < 0 || $server_port > 65535)
- {
- logger("Invalid IP:Port given $server_ip:$server_port.");
- return 0;
- }
-
- if ($control_password !~ /^\s*$/)
- {
- if ($control_protocol eq "rcon")
- {
- use KKrcon::KKrcon;
- my $rcon = new KKrcon(
- Password => $control_password,
- Host => $server_ip,
- Port => $server_port,
- Type => $control_type
- );
- logger "Sending RCON command to $server_ip:$server_port: \n$rconCommand \n .";
-
- my(@modedlines) = $rcon->execute($rconCommand);
- my $encoded_content = encode_list(@modedlines);
- return "1;" . $encoded_content;
- }
- else
- {
- if ($control_protocol eq "rcon2")
- {
- use KKrcon::HL2;
- my $rcon2 = new HL2(
- hostname => $server_ip,
- port => $server_port,
- password => $control_password,
- timeout => 2
- );
-
- logger "Sending RCON command to $server_ip:$server_port: \n $rconCommand \n .";
-
- my(@modedlines) = $rcon2->run($rconCommand);
- my $encoded_content = encode_list(@modedlines);
- return "1;" . $encoded_content;
- }
- }
- }
- else
- {
- logger "Control protocol PASSWORD NOT SET.";
- return -10;
- }
- }
- ##### Returns a directory listing
- ### @return List of directories if everything OK.
- ### @return 0 If the directory is not found.
- ### @return -1 If cannot open the directory.
- sub dirlist
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($datadir) = &decrypt_param(@_);
- logger "Asked for dirlist of $datadir directory.";
- if (!-d $datadir)
- {
- logger "ERROR - Directory [ $datadir ] not found!";
- return -1;
- }
- if (!opendir(DIR, $datadir))
- {
- logger "ERROR - Can't open $datadir: $!";
- return -2;
- }
- my @dirlist = readdir(DIR);
- closedir(DIR);
- return join(";", @dirlist);
- }
- ##### Returns a directory listing with extra info the filemanager
- ### @return List of directories if everything OK.
- ### @return 1 If the directory is empty.
- ### @return -1 If the directory is not found.
- ### @return -2 If cannot open the directory.
- sub dirlistfm
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $datadir = &decrypt_param(@_);
-
- logger "Asked for dirlist of $datadir directory.";
-
- if (!-d $datadir)
- {
- logger "ERROR - Directory [ $datadir ] not found!";
- return -1;
- }
-
- if (!opendir(DIR, $datadir))
- {
- logger "ERROR - Can't open $datadir: $!";
- return -2;
- }
-
- my $dir = $datadir;
- $dir =~ s/('+)/'"$1"'/g;
- my $lsattr = `lsattr '$dir' 2>/dev/null`;
-
- my @attr_all = split /\n+/, $lsattr;
-
- my %attr = ();
-
- my ($a, $p, @f);
-
- foreach (@attr_all)
- {
- ($a, $p) = split(/\s/, $_, 2);
- @f = split /\//, $p;
- $attr{$f[-1]} = $a;
- }
-
- my %dirfiles = ();
-
- my (
- $dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
- $size, $atime, $mtime, $ctime, $blksize, $blocks
- );
-
- my $count = 0;
-
- chdir($datadir);
-
- while (my $item = readdir(DIR))
- {
- #skip the . and .. special dirs
- next if $item eq '.';
- next if $item eq '..';
- #print "Dir list is" . $item."\n";
- #Stat the file to get ownership and size
- (
- $dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
- $size, $atime, $mtime, $ctime, $blksize, $blocks
- ) = stat($item);
-
- $uid = getpwuid($uid);
- $gid = getgrgid($gid);
- #This if else logic determines what it is, File, Directory, other
- if (-T $item)
- {
- # print "File\n";
- $dirfiles{'files'}{$count}{'filename'} = encode_base64($item);
- $dirfiles{'files'}{$count}{'size'} = $size;
- $dirfiles{'files'}{$count}{'user'} = $uid;
- $dirfiles{'files'}{$count}{'group'} = $gid;
- $dirfiles{'files'}{$count}{'attr'} = $attr{$item};
- }
- elsif (-d $item)
- {
- # print "Dir\n";
- $dirfiles{'directorys'}{$count}{'filename'} = encode_base64($item);
- $dirfiles{'directorys'}{$count}{'size'} = $size;
- $dirfiles{'directorys'}{$count}{'user'} = $uid;
- $dirfiles{'directorys'}{$count}{'group'} = $gid;
- }
- elsif (-B $item)
- {
- #print "File\n";
- $dirfiles{'binarys'}{$count}{'filename'} = encode_base64($item);
- $dirfiles{'binarys'}{$count}{'size'} = $size;
- $dirfiles{'binarys'}{$count}{'user'} = $uid;
- $dirfiles{'binarys'}{$count}{'group'} = $gid;
- $dirfiles{'binarys'}{$count}{'attr'} = $attr{$item};
- }
- else
- {
- #print "Unknown\n"
- #will be listed as common files;
- $dirfiles{'files'}{$count}{'filename'} = encode_base64($item);
- $dirfiles{'files'}{$count}{'size'} = $size;
- $dirfiles{'files'}{$count}{'user'} = $uid;
- $dirfiles{'files'}{$count}{'group'} = $gid;
- $dirfiles{'files'}{$count}{'attr'} = $attr{$item};
- }
- $count++;
- }
- closedir(DIR);
-
- if ($count eq 0)
- {
- logger "Empty directory $datadir.";
- return 1;
- }
-
- chdir AGENT_RUN_DIR;
- #Now we return it to the webpage, as array
- return {%dirfiles};
- }
- ###### Returns the contents of a text file
- sub readfile
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- chdir AGENT_RUN_DIR;
- my $userfile = &decrypt_param(@_);
- unless ( -e $userfile )
- {
- if (open(BLANK, '>', $userfile))
- {
- close(BLANK);
- }
- }
-
- if (!open(USERFILE, '<', $userfile))
- {
- logger "ERROR - Can't open file $userfile for reading.";
- return -1;
- }
- my ($wholefile, $buf);
- while (read(USERFILE, $buf, 60 * 57))
- {
- $wholefile .= encode_base64($buf);
- }
- close(USERFILE);
-
- if(!defined $wholefile)
- {
- return "1; ";
- }
-
- return "1;" . $wholefile;
- }
- ###### Backs up file, then writes data to new file
- ### @return 1 On success
- ### @return 0 In case of a failure
- sub writefile
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- chdir AGENT_RUN_DIR;
- # $writefile = file we're editing, $filedata = the contents were writing to it
- my ($writefile, $filedata) = &decrypt_params(@_);
- if (!-e $writefile)
- {
- open FILE, ">", $writefile;
- }
- else
- {
- # backup the existing file
- logger
- "Backing up file $writefile to $writefile.bak before writing new data.";
- if (!copy("$writefile", "$writefile.bak"))
- {
- logger
- "ERROR - Failed to backup $writefile to $writefile.bak. Error: $!";
- return 0;
- }
- }
- if (!-w $writefile)
- {
- logger "ERROR - File [ $writefile ] is not writeable!";
- return 0;
- }
- if (!open(WRITER, '>', $writefile))
- {
- logger "ERROR - Failed to open $writefile for writing.";
- return 0;
- }
- $filedata = decode_base64($filedata);
- $filedata =~ s/\r//g;
- print WRITER "$filedata";
- close(WRITER);
- logger "Wrote $writefile successfully!";
- return 1;
- }
- ###### Reboots the server remotely through panel
- ### @return 1 On success
- ### @return 0 In case of a failure
- sub rebootnow
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- sudo_exec_without_decrypt('sleep 10s; shutdown -r now');
- logger "Scheduled system reboot to occur in 10 seconds successfully!";
- return 1;
- }
- # Determine the os of the agent machine.
- sub what_os
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- logger "Asking for OS type";
- my $which_uname = `which uname`;
- chomp $which_uname;
- if ($which_uname ne "")
- {
- my $os;
- my $os_name;
- my $os_arch;
- my $wine_ver = "";
- $os_name = `$which_uname`;
- chomp $os_name;
- $os_arch = `$which_uname -m`;
- chomp $os_arch;
- my $which_wine = `which wine`;
- chomp $which_wine;
- if ($which_wine ne "")
- {
- $wine_ver = `$which_wine --version`;
- chomp $wine_ver;
- $wine_ver = "|".$wine_ver;
- }
- $os = $os_name." ".$os_arch.$wine_ver;
- logger "OS is $os";
- return "$os";
- }
- else
- {
- logger "Cannot determine OS..that is odd";
- return "Unknown";
- }
- }
- ### @return PID of the download process if started succesfully.
- ### @return -1 If could not create temporary download directory.
- ### @return -2 If could not create destination directory.
- ### @return -3 If resources unavailable.
- sub start_file_download
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($url, $destination, $filename, $action, $post_script) = &decrypt_params(@_);
- logger
- "Starting to download URL $url. Destination: $destination - Filename: $filename";
- if (!-e $destination)
- {
- logger "Creating destination directory.";
- if (!mkpath $destination )
- {
- logger "Could not create destination '$destination' directory : $!";
- return -2;
- }
- }
-
- my $download_file_path = Path::Class::File->new($destination, "$filename");
- my $pid = fork();
- if (not defined $pid)
- {
- logger "Could not allocate resources for download.";
- return -3;
- }
-
- # Only the forked child goes here.
- elsif ($pid == 0)
- {
- my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0,
- SSL_verify_mode => 0x00 } );
- $ua->agent('Mozilla/5.0');
- my $response = $ua->get($url, ':content_file' => "$download_file_path");
-
- if ($response->is_success)
- {
- logger "Successfully fetched $url and stored it to $download_file_path. Retval: ".$response->status_line;
-
- if (!-e $download_file_path)
- {
- logger "File $download_file_path does not exist.";
- exit(0);
- }
- if ($action eq "uncompress")
- {
- logger "Starting file uncompress as ordered.";
- uncompress_file_without_decrypt($download_file_path,
- $destination);
- }
-
- # Run post scripts if any
- if ($post_script ne "")
- {
- logger "Running postscript commands.";
- my @postcmdlines = split /[\r\n]+/, $post_script;
- my $postcmdfile = $destination."/".'postinstall.sh';
- open FILE, '>', $postcmdfile;
- print FILE "cd $destination\n";
- foreach my $line (@postcmdlines) {
- logger "Postscript command received \"" . $line ."\".";
- if(handle_lock_command_line($line) == 0){
- print FILE "$line\n";
- }else{
- logger "Lock command completed successfully";
- }
- }
- print FILE "rm -f $destination/postinstall.sh\n";
- close FILE;
- chmod 0755, $postcmdfile;
- my $screen_id = create_screen_id("post_script", $$);
- my $cli_bin = create_screen_cmd($screen_id, "bash $postcmdfile");
- system($cli_bin);
- }
- }
- else
- {
- logger
- "Unable to fetch $url, or save to $download_file_path. Retval: ".$response->status_line;
- exit(0);
- }
- # Child process must exit.
- exit(0);
- }
- else
- {
- logger "Download process for $download_file_path has pid number $pid.";
- return "$pid";
- }
- }
- sub lock_additional_files{
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($homedir, $files, $action) = &decrypt_params(@_);
- return lock_additional_files_logic($homedir, $files, $action);
- }
- sub lock_additional_files_logic{
- my ($homedir, $filesToLock, $action, $returnType) = @_;
-
- logger "Locking additional files specified in the XML.";
-
- my $commandStr = "";
- $filesToLock = startup_comma_format_to_multiline($filesToLock);
- $filesToLock = replace_OGP_Env_Vars("", $homedir, $filesToLock);
- my @filesToProcess = split /[\r\n]+/, $filesToLock;
- foreach my $line (@filesToProcess) {
- my $fullPath = $homedir . "/" . $line;
- if($action eq "lock"){
- if(defined $returnType && $returnType eq "str"){
- $commandStr .= "echo '".$SUDOPASSWD."' | sudo -S -p \"\" sh -c \"" . secure_path_without_decrypt("chattr+i", $fullPath, $returnType) . "\" > /dev/null 2>&1" . "\n";
- $commandStr .= "echo '".$SUDOPASSWD."' | sudo -S -p \"\" sh -c \"" . secure_path_without_decrypt("chattr+i", $line, $returnType) . "\" > /dev/null 2>&1" . "\n";
- }else{
- secure_path_without_decrypt("chattr+i", $fullPath);
- secure_path_without_decrypt("chattr+i", $line);
- }
- }else{
- if(defined $returnType && $returnType eq "str"){
- $commandStr .= "echo '".$SUDOPASSWD."' | sudo -S -p \"\" sh -c \"" . secure_path_without_decrypt("chattr-i", $fullPath, $returnType) . "\" > /dev/null 2>&1" . "\n";
- $commandStr .= "echo '".$SUDOPASSWD."' | sudo -S -p \"\" sh -c \"" . secure_path_without_decrypt("chattr-i", $line, $returnType) . "\" > /dev/null 2>&1" . "\n";
- }else{
- secure_path_without_decrypt("chattr-i", $fullPath);
- secure_path_without_decrypt("chattr-i", $line);
- }
- }
- }
-
- if($commandStr ne ""){
- return $commandStr;
- }
-
- return "";
- }
- sub run_before_start_commands
- {
- #return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($server_id, $homedir, $beforestartcmd) = @_;
-
- if ($homedir ne "" && $server_id ne ""){
- # Run any prestart scripts
- if (defined $beforestartcmd && $beforestartcmd ne "")
- {
- logger "Running pre-start XML commands before starting server ID $server_id with a home directory of $homedir.";
- my @prestartcmdlines = split /[\r\n]+/, $beforestartcmd;
- my $prestartcmdfile = $homedir."/".'prestart_ogp.sh';
- open FILE, '>', $prestartcmdfile;
- print FILE "#!/bin/bash" . "\n";
- print FILE "cd $homedir\n";
- foreach my $line (@prestartcmdlines) {
- print FILE "$line\n";
- }
- print FILE "rm -f $prestartcmdfile\n";
- close FILE;
- chmod 0755, $prestartcmdfile;
- system("bash $prestartcmdfile");
- }
- }else{
- return -2;
- }
-
- return 1;
- }
- sub multiline_to_startup_comma_format{
- my ($multiLineVar) = @_;
- $multiLineVar =~ s/,//g; # commas are invalid anyways in bash
- $multiLineVar =~ s/[\r]+//g;
- $multiLineVar =~ s/[\n]+/{OGPNEWLINE}/g;
- return $multiLineVar;
- }
- sub multiline_to_bash_commands{
- my ($multiLineVar) = @_;
- $multiLineVar =~ s/[\n]+/ && /g;
- return $multiLineVar;
- }
- sub startup_comma_format_to_multiline{
- my ($multiLineVar) = @_;
- $multiLineVar =~ s/{OGPNEWLINE}/\n/g;
- return $multiLineVar;
- }
- sub create_secure_script
- {
- my ($home_path, $exec_folder_path, $exec_path) = @_;
- secure_path_without_decrypt('chattr-i', $home_path);
- my $secure = "$home_path/secure.sh";
- $home_path =~ s/('+)/'\"$1\"'/g;
- $exec_folder_path =~ s/('+)/'\"$1\"'/g;
- $exec_path =~ s/('+)/'\"$1\"'/g;
- my $sec = $secure;
- $sec =~ s/('+)/'\"$1\"'/g;
- open FILE, '>', $secure;
- print FILE "chmod 771 '$exec_folder_path'\n".
- "chmod 750 '$exec_path'\n".
- "chmod +x '$exec_path'\n".
- "chattr +i '$exec_path'\n".
- "rm -f '$sec'";
- close FILE;
- chmod 0770, $secure;
- sudo_exec_without_decrypt("chown 0:0 '$sec'");
- return 0;
- }
- sub check_b4_chdir
- {
- my ( $path ) = @_;
-
- my $uid = `id -u`;
- chomp $uid;
- my $gid = `id -g`;
- chomp $gid;
-
- if (!-e $path)
- {
- logger "$path does not exist yet. Trying to create it...";
- if (!mkpath($path))
- {
- logger "Error creating $path . Errno: $!";
- return -1;
- }
-
- # Set perms on it as well
- sudo_exec_without_decrypt('chown -Rf '.$uid.':'.$gid.' \''.$path.'\'');
-
- }
- else
- {
- # File or directory already exists
- # Make sure it's owned by the agent
- secure_path_without_decrypt('chattr-i', $path);
- }
-
- if (!chdir $path)
- {
- logger "Unable to change dir to '$path'.";
- return -1;
- }
-
- return 0;
- }
- sub create_bash_scripts
- {
- my ( $home_path, $bash_scripts_path, $precmd, $postcmd, @installcmds ) = @_;
-
- $home_path =~ s/('+)/'\"$1\"'/g;
- $bash_scripts_path =~ s/('+)/'\"$1\"'/g;
-
- my @precmdlines = split /[\r\n]+/, $precmd;
- my $precmdfile = 'preinstall.sh';
- open FILE, '>', $precmdfile;
- print FILE "cd '$home_path'\n";
- foreach my $line (@precmdlines) {
- print FILE "$line\n";
- }
- close FILE;
- chmod 0755, $precmdfile;
-
- my @postcmdlines = split /[\r\n]+/, $postcmd;
- my $postcmdfile = 'postinstall.sh';
- open FILE, '>', $postcmdfile;
- print FILE "cd '$home_path'\n";
- foreach my $line (@postcmdlines) {
- print FILE "$line\n";
- }
- print FILE "cd '$home_path'\n".
- "echo '".$SUDOPASSWD."' | sudo -S -p \"\" bash secure.sh\n".
- "rm -f secure.sh\n".
- "cd '$bash_scripts_path'\n".
- "rm -f preinstall.sh\n".
- "rm -f postinstall.sh\n".
- "rm -f runinstall.sh\n";
- close FILE;
- chmod 0755, $postcmdfile;
-
- my $installfile = 'runinstall.sh';
- open FILE, '>', $installfile;
- print FILE "#!/bin/bash\n".
- "cd '$bash_scripts_path'\n".
- "./$precmdfile\n";
- foreach my $installcmd (@installcmds)
- {
- print FILE "$installcmd\n";
- }
- print FILE "wait ".'${!}'."\n".
- "cd '$bash_scripts_path'\n".
- "./$postcmdfile\n";
- close FILE;
- chmod 0755, $installfile;
-
- return $installfile;
- }
- #### Run the rsync update ####
- ### @return 1 If update started
- ### @return 0 In error case.
- sub start_rsync_install
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($home_id, $home_path, $url, $exec_folder_path, $exec_path, $precmd, $postcmd, $filesToLockUnlock) = decrypt_params(@_);
- if ( check_b4_chdir($home_path) != 0)
- {
- return 0;
- }
-
- secure_path_without_decrypt('chattr-i', $home_path);
-
- create_secure_script($home_path, $exec_folder_path, $exec_path);
- my $bash_scripts_path = MANUAL_TMP_DIR . "/home_id_" . $home_id;
-
- if ( check_b4_chdir($bash_scripts_path) != 0)
- {
- return 0;
- }
-
- # Rsync install require the rsync binary to exist in the system
- # to enable this functionality.
- my $rsync_binary = Path::Class::File->new("/usr/bin", "rsync");
-
- if (!-f $rsync_binary)
- {
- logger "Failed to start rsync update from "
- . $url
- . " to $home_path. Error: Rsync client not installed.";
- return 0;
- }
- my $screen_id = create_screen_id(SCREEN_TYPE_UPDATE, $home_id);
-
- my $log_file = Path::Class::File->new(SCREEN_LOGS_DIR, "screenlog.$screen_id");
-
- if(defined $filesToLockUnlock && $filesToLockUnlock ne ""){
- $postcmd .= "\n" . lock_additional_files_logic($home_path, $filesToLockUnlock, "lock", "str");
- }
-
- backup_home_log( $home_id, $log_file );
- my $path = $home_path;
- $path =~ s/('+)/'\"$1\"'/g;
- my @installcmds = ("/usr/bin/rsync --archive --compress --copy-links --update --verbose rsync://$url '$path'");
- my $installfile = create_bash_scripts( $home_path, $bash_scripts_path, $precmd, $postcmd, @installcmds );
- my $screen_cmd = create_screen_cmd($screen_id, "./$installfile");
- logger "Running rsync update: /usr/bin/rsync --archive --compress --copy-links --update --verbose rsync://$url '$home_path'";
- system($screen_cmd);
-
- chdir AGENT_RUN_DIR;
- return 1;
- }
- ### @return PID of the download process if started succesfully.
- ### @return -1 If could not create temporary download directory.
- ### @return -2 If could not create destination directory.
- ### @return -3 If resources unavailable.
- sub master_server_update
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($home_id,$home_path,$ms_home_id,$ms_home_path,$exec_folder_path,$exec_path,$precmd,$postcmd) = decrypt_params(@_);
-
- if ( check_b4_chdir($home_path) != 0)
- {
- return 0;
- }
-
- secure_path_without_decrypt('chattr-i', $home_path);
-
- create_secure_script($home_path, $exec_folder_path, $exec_path);
-
- my $bash_scripts_path = MANUAL_TMP_DIR . "/home_id_" . $home_id;
-
- if ( check_b4_chdir($bash_scripts_path) != 0)
- {
- return 0;
- }
- my $screen_id = create_screen_id(SCREEN_TYPE_UPDATE, $home_id);
-
- my $log_file = Path::Class::File->new(SCREEN_LOGS_DIR, "screenlog.$screen_id");
-
- backup_home_log( $home_id, $log_file );
-
- my $my_home_path = $home_path;
- $my_home_path =~ s/('+)/'\"$1\"'/g;
- $exec_path =~ s/\Q$home_path\E//g;
- $exec_path =~ s/^\///g;
- $exec_path =~ s/('+)/'\"$1\"'/g;
- $ms_home_path =~ s/('+)/'\"$1\"'/g;
-
- my @installcmds = ("cd '$ms_home_path'");
-
- ## Copy files that match the extensions listed at extPatterns.txt
- open(EXT_PATTERNS, '<', Path::Class::File->new(AGENT_RUN_DIR, "extPatterns.txt"))
- || logger "Error reading patterns file $!";
- my @ext_paterns = <EXT_PATTERNS>;
- foreach my $patern (@ext_paterns)
- {
- chop $patern;
- push (@installcmds, "find -iname \\\*.$patern -exec cp -Rfp --parents {} '$my_home_path'/ \\\;");
- }
- close EXT_PATTERNS;
-
- ## Copy the server executable so it can be secured with chattr +i
- push (@installcmds, "cp -vf --parents '$exec_path' '$my_home_path'");
-
- ## Do symlinks for each of the other files
- push (@installcmds, "cp -vuRfs '$ms_home_path'/* '$my_home_path'");
-
- my $installfile = create_bash_scripts( $home_path, $bash_scripts_path, $precmd, $postcmd, @installcmds );
- my $screen_cmd = create_screen_cmd($screen_id, "./$installfile");
- logger "Running master server update from home ID $home_id to home ID $ms_home_id";
- system($screen_cmd);
-
- chdir AGENT_RUN_DIR;
- return 1;
- }
- sub steam_cmd
- {
- chomp(@_);
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return steam_cmd_without_decrypt(decrypt_params(@_));
- }
- #### Run the steam client ####
- ### @return 1 If update started
- ### @return 0 In error case.
- sub steam_cmd_without_decrypt
- {
- my ($home_id, $home_path, $mod, $modname, $betaname, $betapwd, $user, $pass, $guard, $exec_folder_path, $exec_path, $precmd, $postcmd, $cfg_os, $filesToLockUnlock) = @_;
-
- if ( check_b4_chdir($home_path) != 0)
- {
- return 0;
- }
-
- secure_path_without_decrypt('chattr-i', $home_path);
-
- create_secure_script($home_path, $exec_folder_path, $exec_path);
-
- my $bash_scripts_path = MANUAL_TMP_DIR . "/home_id_" . $home_id;
-
- if ( check_b4_chdir($bash_scripts_path) != 0)
- {
- return 0;
- }
-
- my $screen_id = create_screen_id(SCREEN_TYPE_UPDATE, $home_id);
- my $screen_id_for_txt_update = substr ($screen_id, rindex($screen_id, '_') + 1);
- my $steam_binary = Path::Class::File->new(STEAMCMD_CLIENT_DIR, "steamcmd.sh");
- my $installSteamFile = $screen_id_for_txt_update . "_install.txt";
- my $installtxt = Path::Class::File->new(STEAMCMD_CLIENT_DIR, $installSteamFile);
- open FILE, '>', $installtxt;
- print FILE "\@ShutdownOnFailedCommand 1\n";
- print FILE "\@NoPromptForPassword 1\n";
- if($cfg_os eq 'windows')
- {
- print FILE "\@sSteamCmdForcePlatformType windows\n";
- }
- if($guard ne '')
- {
- print FILE "set_steam_guard_code $guard\n";
- }
- if($user ne '' && $user ne 'anonymous')
- {
- print FILE "login $user $pass\n";
- }
- else
- {
- print FILE "login anonymous\n";
- }
-
- print FILE "force_install_dir \"$home_path\"\n";
- if($modname ne "")
- {
- print FILE "app_set_config $mod mod $modname\n";
- print FILE "app_update $mod mod $modname validate\n";
- }
- if($betaname ne "" && $betapwd ne "")
- {
- print FILE "app_update $mod -beta $betaname -betapassword $betapwd\n";
- }
- elsif($betaname ne "" && $betapwd eq "")
- {
- print FILE "app_update $mod -beta $betaname\n";
- }
- else
- {
- print FILE "app_update $mod\n";
- }
-
- print FILE "exit\n";
- close FILE;
-
- my $log_file = Path::Class::File->new(SCREEN_LOGS_DIR, "screenlog.$screen_id");
- backup_home_log( $home_id, $log_file );
-
- my $postcmd_mod = $postcmd;
-
- if(defined $filesToLockUnlock && $filesToLockUnlock ne ""){
- $postcmd_mod .= "\n" . lock_additional_files_logic($home_path, $filesToLockUnlock, "lock", "str");
- }
-
- my @installcmds = ("$steam_binary +runscript $installtxt +exit");
-
- my $installfile = create_bash_scripts( $home_path, $bash_scripts_path, $precmd, $postcmd_mod, @installcmds );
-
- my $screen_cmd = create_screen_cmd($screen_id, "./$installfile");
-
- logger "Running steam update: $steam_binary +runscript $installtxt +exit";
- system($screen_cmd);
- return 1;
- }
- sub fetch_steam_version
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($appId, $pureOutput) = &decrypt_params(@_);
- my $steam_binary = Path::Class::File->new(STEAMCMD_CLIENT_DIR, "steamcmd.sh");
- my $steam_options = "+login anonymous +app_info_update 1 +app_info_print \"$appId\" +quit";
- my $grep = $pureOutput != "0" ? "" : '| grep -EA 1000 "^\s+\"branches\"$" | grep -EA 5 "^\s+\"public\"$" | grep -m 1 -EB 10 "^\s+}$" | grep -E "^\s+\"buildid\"\s+" | tr \'[:blank:]"\' \' \' | tr -s \' \' | cut -d\' \' -f3';
- logger "Getting latest version info for AppId $appId";
- my $response = `$steam_binary $steam_options $grep`;
- return $response;
- }
- sub installed_steam_version
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($game_home, $mod, $pureOutput) = &decrypt_params(@_);
- my $appFile = $game_home."/steamapps/appmanifest_$mod.acf";
- my $grep = $pureOutput != "0" ? "" : '| grep buildid | tr \'[:blank:]"\' \' \' | tr -s \' \' | cut -d\' \' -f3';
- if ( ! -f $appFile)
- {
- return "-10";
- }
- return `cat $appFile $grep`;
- }
- sub automatic_steam_update
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($home_id, $game_home, $server_ip, $server_port, $exec_path, $exec_folder_path,
- $control_protocol, $control_password, $control_type,
- $appId, $modname, $betaname, $betapwd, $user, $pass, $guard, $precmd, $postcmd, $cfg_os, $filesToLockUnlock,
- $startup_cmd, $cpu, $nice, $preStart, $envVars) = &decrypt_params(@_);
- # Is the server currently running? if it is, we'll try to start it after updating.
- my $isServerRunning = is_screen_running_without_decrypt(SCREEN_TYPE_HOME, $home_id) == 1 ? 1 : 0;
- # Check if an update is already happening.
- if (is_screen_running_without_decrypt(SCREEN_TYPE_UPDATE, $home_id) == 1)
- {
- logger("Update already running for server $home_id, unable to start automatic update.");
- return -10;
- }
- # Stop the server if it's running.
- if ($isServerRunning == 1)
- {
- logger("Stopping server $home_id for automatic update.");
- if (stop_server_without_decrypt($home_id, $server_ip, $server_port, $control_protocol, $control_password, $control_type, $game_home) != 0)
- {
- logger("Failed to stop server $home_id for automatic update. Exiting update procedure.");
- return -9
- }
- }
- # steam_cmd: Returns 0 if the update failed, in which case, don't try starting the server - because we may have an incomplete or corrupt installation.
- if (steam_cmd_without_decrypt($home_id, $game_home, $appId, $modname, $betaname, $betapwd, $user, $pass, $guard, $exec_folder_path, $exec_path, $precmd, $postcmd, $cfg_os, $filesToLockUnlock) == 0)
- {
- logger("Failed to start steam_cmd for server $home_id.");
- return -8;
- } else {
- if ($isServerRunning == 1)
- {
- while (1)
- {
- # If the update screen for $home_id isn't running, attempt to start the server.
- if (is_screen_running_without_decrypt(SCREEN_TYPE_UPDATE, $home_id) == 0)
- {
- if (universal_start_without_decrypt($home_id, $game_home, $exec_path, $exec_folder_path, $startup_cmd, $server_port, $server_ip, $cpu, $nice, $preStart, $envVars) != 1)
- {
- logger("Failed to start server $home_id after automatic update.");
- return -7;
- } else {
- logger("Starting server $home_id after automatic update.");
- return 1;
- }
- last;
- }
- sleep 5;
- }
- } else {
- # Update was started, but server wasn't initially running.
- return 2;
- }
- }
- }
- sub rsync_progress
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($running_home) = &decrypt_param(@_);
- logger "User requested progress on rsync job on home $running_home.";
- if (-r $running_home)
- {
- $running_home =~ s/('+)/'"$1"'/g;
- my $progress = `du -sk '$running_home'`;
- chomp($progress);
- my ($bytes, $junk) = split(/\s+/, $progress);
- logger("Found $bytes and $junk");
- return $bytes;
- }
- return "0";
- }
- sub is_file_download_in_progress
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($pid) = &decrypt_param(@_);
- logger "User requested if download is in progress with pid $pid.";
- my @pids = `ps -ef`;
- @pids = grep(/$pid/, @pids);
- logger "Number of pids for file download: @pids";
- if (@pids > '0')
- {
- return 1;
- }
- return 0;
- }
- ### \return 1 If file is uncompressed succesfully.
- ### \return 0 If file does not exist.
- ### \return -1 If file could not be uncompressed.
- sub uncompress_file
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return uncompress_file_without_decrypt(decrypt_params(@_));
- }
- sub uncompress_file_without_decrypt
- {
- # File must include full path.
- my ($file, $destination) = @_;
- logger "Uncompression called for file $file to dir $destination.";
- if (!-e $file)
- {
- logger "File $file could not be found for uncompression.";
- return 0;
- }
- if (!-e $destination)
- {
- mkpath($destination, {error => \my $err});
- if (@$err)
- {
- logger "Failed to create destination dir $destination.";
- return 0;
- }
- }
- my $ae = Archive::Extract->new(archive => $file);
- if (!$ae)
- {
- logger "Could not create archive instance for file $file.";
- return -1;
- }
- my $ok = $ae->extract(to => $destination);
- if (!$ok)
- {
- logger "File $file could not be uncompressed.";
- return -1;
- }
- logger "File uncompressed/extracted successfully.";
- return 1;
- }
- ### \return 1 If files are compressed succesfully.
- ### \return -1 If files could not be compressed.
- sub compress_files
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return compress_files_without_decrypt(decrypt_params(@_));
- }
- sub compress_files_without_decrypt
- {
- my ($files,$destination,$archive_name,$archive_type) = @_;
- if (!-e $destination)
- {
- logger "compress_files: Destination path ( $destination ) could not be found.";
- return -1;
- }
-
- chdir $destination;
- my @items = split /\Q\n/, $files;
- my @inventory;
- if($archive_type eq "zip")
- {
- logger $archive_type." compression called, destination archive is: $destination$archive_name.$archive_type";
- my $zip = Archive::Zip->new();
- foreach my $item (@items) {
- if(-e $item)
- {
- if (-f $item)
- {
- $zip->addFile( $item );
- }
- elsif (-d $item)
- {
- $zip->addTree( $item, $item );
- }
- }
- }
- # Save the file
- unless ( $zip->writeToFileNamed($archive_name.'.zip') == AZ_OK ) {
- logger "Write Error at $destination/$archive_name.$archive_type";
- return -1
- }
- logger $archive_type." archive $destination$archive_name.$archive_type created successfully";
- return 1;
- }
- elsif($archive_type eq "tbz")
- {
- logger $archive_type." compression called, destination archive is: $destination$archive_name.$archive_type";
- my $tar = Archive::Tar->new;
- foreach my $item (@items) {
- if(-e $item)
- {
- if (-f $item)
- {
- $tar->add_files( $item );
- }
- elsif (-d $item)
- {
- @inventory = ();
- find (sub { push @inventory, $File::Find::name }, $item);
- $tar->add_files( @inventory );
- }
- }
- }
- # Save the file
- unless ( $tar->write("$archive_name.$archive_type", COMPRESS_BZIP) ) {
- logger "Write Error at $destination/$archive_name.$archive_type";
- return -1
- }
- logger $archive_type." archive $destination$archive_name.$archive_type created successfully";
- return 1;
- }
- elsif($archive_type eq "tgz")
- {
- logger $archive_type." compression called, destination archive is: $destination$archive_name.$archive_type";
- my $tar = Archive::Tar->new;
- foreach my $item (@items) {
- if(-e $item)
- {
- if (-f $item)
- {
- $tar->add_files( $item );
- }
- elsif (-d $item)
- {
- @inventory = ();
- find (sub { push @inventory, $File::Find::name }, $item);
- $tar->add_files( @inventory );
- }
- }
- }
- # Save the file
- unless ( $tar->write("$archive_name.$archive_type", COMPRESS_GZIP) ) {
- logger "Write Error at $destination/$archive_name.$archive_type";
- return -1
- }
- logger $archive_type." archive $destination$archive_name.$archive_type created successfully";
- return 1;
- }
- elsif($archive_type eq "tar")
- {
- logger $archive_type." compression called, destination archive is: $destination$archive_name.$archive_type";
- my $tar = Archive::Tar->new;
- foreach my $item (@items) {
- if(-e $item)
- {
- if (-f $item)
- {
- $tar->add_files( $item );
- }
- elsif (-d $item)
- {
- @inventory = ();
- find (sub { push @inventory, $File::Find::name }, $item);
- $tar->add_files( @inventory );
- }
- }
- }
- # Save the file
- unless ( $tar->write("$archive_name.$archive_type") ) {
- logger "Write Error at $destination/$archive_name.$archive_type";
- return -1
- }
- logger $archive_type." archive $destination$archive_name.$archive_type created successfully";
- return 1;
- }
- elsif($archive_type eq "bz2")
- {
- logger $archive_type." compression called.";
- foreach my $item (@items) {
- if(-e $item)
- {
- if (-f $item)
- {
- bzip2 $item => "$item.bz2";
- }
- elsif (-d $item)
- {
- @inventory = ();
- find (sub { push @inventory, $File::Find::name }, $item);
- foreach my $relative_item (@inventory) {
- bzip2 $relative_item => "$relative_item.bz2";
- }
- }
- }
- }
- logger $archive_type." archives created successfully at $destination";
- return 1;
- }
- }
- sub discover_ips
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($check) = decrypt_params(@_);
- if ($check ne "chk")
- {
- logger "Invalid parameter '$check' given for discover_ips function.";
- return "";
- }
- my $iplist = "";
- my $ipfound;
- my $junk;
- my @ipraw = `/sbin/ifconfig`;
- while (<@ipraw>)
- {
- chomp;
- next if $_ !~ /^inet:/ ;
- logger "Found addr on line: $_";
- ($junk, $ipfound) = split(":", $_);
- next if $ipfound eq '';
- next if $ipfound eq '127.0.0.1';
- logger "Found an IP $ipfound";
- $iplist .= "$ipfound,";
- logger "IPlist is now $iplist";
- }
- while (<@ipraw>)
- {
- chomp;
- next if $_ !~ /^addr:/ ;
- logger "Found addr on line: $_";
- ($junk, $ipfound) = split(":", $_);
- next if $ipfound eq '';
- next if $ipfound eq '127.0.0.1';
- logger "Found an IP $ipfound";
- $iplist .= "$ipfound,";
- logger "IPlist is now $iplist";
- }
- chop $iplist;
- return "$iplist";
- }
- ### Return -1 In case of invalid param
- ### Return 1;content in case of success
- sub mon_stats
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($mon_stats) = decrypt_params(@_);
- if ($mon_stats ne "mon_stats")
- {
- logger "Invalid parameter '$mon_stats' given for $mon_stats function.";
- return -1;
- }
- my @disk = `df -hP -x tmpfs`;
- my $encoded_content = encode_list(@disk);
- my @uptime = `uptime`;
- $encoded_content .= encode_list(@uptime);
- return "1;$encoded_content";
- }
- sub exec
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($command) = decrypt_params(@_);
- my @cmdret = `$command 2>/dev/null`;
- my $encoded_content = encode_list(@cmdret);
- return "1;$encoded_content";
- }
- # used in conjunction with the clone_home feature in the web panel
- # this actually does the file copies
- sub clone_home
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($source_home, $dest_home, $owner) = decrypt_params(@_);
- my ($time_start, $time_stop, $time_diff);
- logger "Copying from $source_home to $dest_home...";
- # check size of source_home, make sure we have space to copy
- if (!-e $source_home)
- {
- logger "ERROR - $source_home does not exist";
- return 0;
- }
- logger "Game home $source_home exists...copy will proceed";
- # start the copy, and a timer
- $time_start = time();
- if (!dircopy("$source_home", "$dest_home"))
- {
- $time_stop = time();
- $time_diff = $time_stop - $time_start;
- logger
- "Error occured after $time_diff seconds during copy of $source_home to $dest_home - $!";
- return 0;
- }
- else
- {
- $time_stop = time();
- $time_diff = $time_stop - $time_start;
- logger
- "Home clone completed successfully to $dest_home in $time_diff seconds";
- return 1;
- }
- }
- # used to delete the game home from the file system when it's removed from the panel
- sub remove_home
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($home_path_del) = decrypt_params(@_);
- if (!-e $home_path_del)
- {
- logger "ERROR - $home_path_del does not exist...nothing to do";
- return 0;
- }
- secure_path_without_decrypt('chattr-i', $home_path_del);
- sleep 1 while ( !pathrmdir("$home_path_del") );
- logger "Deletetion of $home_path_del successful!";
- return 1;
- }
- sub restart_server
- {
- chomp(@_);
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return restart_server_without_decrypt(decrypt_params(@_));
- }
- ### Restart the server
- ## return -2 CANT STOP
- ## return -1 CANT START (no startup file found that mach the home_id, port and ip)
- ## return 1 Restart OK
- sub restart_server_without_decrypt
- {
- my ($home_id, $server_ip, $server_port, $control_protocol,
- $control_password, $control_type, $home_path, $server_exe, $run_dir,
- $cmd, $cpu, $nice, $preStart, $envVars) = @_;
- if (stop_server_without_decrypt($home_id, $server_ip,
- $server_port, $control_protocol,
- $control_password, $control_type, $home_path) == 0)
- {
- if (universal_start_without_decrypt($home_id, $home_path, $server_exe, $run_dir,
- $cmd, $server_port, $server_ip, $cpu, $nice, $preStart, $envVars) == 1)
- {
- return 1;
- }
- else
- {
- return -1;
- }
- }
- else
- {
- return -2;
- }
- }
- sub sudo_exec
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $sudo_exec = &decrypt_param(@_);
- return sudo_exec_without_decrypt($sudo_exec);
- }
- sub sudo_exec_without_decrypt
- {
- my ($sudo_exec) = @_;
- $sudo_exec =~ s/('+)/'"$1"'/g;
- logger "Running the following command \"" . $sudo_exec . "\" with sudo.";
- my $command = "echo '$SUDOPASSWD'|sudo -kS -p \"\" su -c '$sudo_exec;echo \$?' root 2>&1";
- my @cmdret = qx($command);
- chomp(@cmdret);
- my $ret = pop(@cmdret);
- chomp($ret);
- if ("X$ret" eq "X0")
- {
- logger "Command \"" . $sudo_exec . "\" was successfully run with sudo.";
- return "1;".encode_list(@cmdret);
- }
- logger "Command \"" . $sudo_exec . "\" run with sudo failed with exit code $ret.";
- return -1;
- }
- sub secure_path
- {
- chomp(@_);
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return secure_path_without_decrypt(decrypt_params(@_));
- }
- sub secure_path_without_decrypt
- {
- my ($action, $file_path, $returnType) = @_;
- my $checkIfFileExists = 1;
-
- if(defined $returnType && $returnType eq "str"){
- $checkIfFileExists = 0;
- }
-
- if($checkIfFileExists){
- if(! -e $file_path){
- return -1;
- }
- }
-
- my $uid = `id -u`;
- chomp $uid;
- my $gid = `id -g`;
- chomp $gid;
- $file_path =~ s/('+)/'\"$1\"'/g;
- if($action eq "chattr+i")
- {
- if(defined $returnType && $returnType eq "str"){
- return 'chown -Rf '.$uid.':'.$gid.' \''.$file_path.'\' && chattr -Rf +i \''.$file_path.'\'';
- }else{
- return sudo_exec_without_decrypt('chown -Rf '.$uid.':'.$gid.' \''.$file_path.'\' && chattr -Rf +i \''.$file_path.'\'');
- }
- }
- elsif($action eq "chattr-i")
- {
- if(defined $returnType && $returnType eq "str"){
- return 'chattr -Rf -i \''.$file_path.'\' && chown -Rf '.$uid.':'.$gid.' \''.$file_path.'\'';
- }else{
- return sudo_exec_without_decrypt('chattr -Rf -i \''.$file_path.'\' && chown -Rf '.$uid.':'.$gid.' \''.$file_path.'\'');
- }
- }
-
- return -1;
- }
- sub get_chattr
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($file_path) = decrypt_params(@_);
- my $file = $file_path;
- $file_path =~ s/('+)/'\"$1\"'/g;
- return sudo_exec_without_decrypt('(lsattr \''.$file_path.'\' | sed -e "s#'.$file.'##g")|grep -o i');
- }
- sub ftp_mgr
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($action, $login, $password, $home_path) = decrypt_params(@_);
-
- my $uid = `id -u`;
- chomp $uid;
- my $gid = `id -g`;
- chomp $gid;
-
- $login =~ s/('+)/'\"$1\"'/g;
- $password =~ s/('+)/'\"$1\"'/g;
- $home_path =~ s/('+)/'\"$1\"'/g;
-
- if(!defined($Cfg::Preferences{ogp_manages_ftp}) || (defined($Cfg::Preferences{ogp_manages_ftp}) && $Cfg::Preferences{ogp_manages_ftp} eq "1")){
- if( defined($Cfg::Preferences{ftp_method}) && $Cfg::Preferences{ftp_method} eq "IspConfig")
- {
- use constant ISPCONFIG_DIR => Path::Class::Dir->new(AGENT_RUN_DIR, 'IspConfig');
- use constant FTP_USERS_DIR => Path::Class::Dir->new(ISPCONFIG_DIR, 'ftp_users');
-
- if (!-d FTP_USERS_DIR && !mkdir FTP_USERS_DIR)
- {
- print "Could not create " . FTP_USERS_DIR . " directory $!.";
- return -1;
- }
-
- chdir ISPCONFIG_DIR;
-
- if($action eq "list")
- {
- my $users_list;
- opendir(USERS, FTP_USERS_DIR);
- while (my $username = readdir(USERS))
- {
- # Skip . and ..
- next if $username =~ /^\./;
- $users_list .= `php-cgi -f sites_ftp_user_get.php username=\'$username\'`;
- }
- closedir(USERS);
- if( defined($users_list) )
- {
- return "1;".encode_list($users_list);
- }
- }
- elsif($action eq "userdel")
- {
- return "1;".encode_list(`php-cgi -f sites_ftp_user_delete.php username=\'$login\'`);
- }
- elsif($action eq "useradd")
- {
- return "1;".encode_list(`php-cgi -f sites_ftp_user_add.php username=\'$login\' password=\'$password\' dir=\'$home_path\' uid=$uid gid=$gid`);
- }
- elsif($action eq "passwd")
- {
- return "1;".encode_list(`php-cgi -f sites_ftp_user_update.php type=passwd username=\'$login\' password=\'$password\'`);
- }
- elsif($action eq "show")
- {
- return "1;".encode_list(`php-cgi -f sites_ftp_user_get.php type=detail username=\'$login\'`);
- }
- elsif($action eq "usermod")
- {
- return "1;".encode_list(`php-cgi -f sites_ftp_user_update.php username=\'$login\' password=\'$password\'`);
- }
- }
- elsif(defined($Cfg::Preferences{ftp_method}) && $Cfg::Preferences{ftp_method} eq "EHCP" && -e "/etc/init.d/ehcp")
- {
- use constant EHCP_DIR => Path::Class::Dir->new(AGENT_RUN_DIR, 'EHCP');
- chdir EHCP_DIR;
- my $phpScript;
- my $phpOut;
-
- chmod 0777, 'ehcp_ftp_log.txt';
-
- # In order to access the FTP files, the vsftpd user needs to be added to the ogp group
- sudo_exec_without_decrypt("usermod -a -G '$gid' ftp");
- sudo_exec_without_decrypt("usermod -a -G '$gid' vsftpd");
-
- if($action eq "list")
- {
- return "1;".encode_list(`php-cgi -f listAllUsers.php`);
- }
- elsif($action eq "userdel")
- {
- $phpScript = `php-cgi -f delAccount.php username=\'$login\'`;
- $phpOut = `php-cgi -f syncftp.php`;
- return $phpScript;
- }
- elsif($action eq "useradd")
- {
- $phpScript = `php-cgi -f addAccount.php username=\'$login\' password=\'$password\' dir=\'$home_path\' uid=$uid gid=$gid`;
- $phpOut = `php-cgi -f syncftp.php`;
- return $phpScript;
- }
- elsif($action eq "passwd")
- {
- $phpScript = `php-cgi -f updatePass.php username=\'$login\' password=\'$password\'`;
- $phpOut = `php-cgi -f syncftp.php`;
- return $phpScript ;
- }
- elsif($action eq "show")
- {
- return "1;".encode_list(`php-cgi -f showAccount.php username=\'$login\'`);
- }
- elsif($action eq "usermod")
- {
- $phpScript = `php-cgi -f updateInfo.php username=\'$login\' password=\'$password\'`;
- $phpOut = `php-cgi -f syncftp.php`;
- return $phpScript;
- }
- }
- elsif(defined($Cfg::Preferences{ftp_method}) && $Cfg::Preferences{ftp_method} eq "proftpd" && -e $Cfg::Preferences{proftpd_conf_path})
- {
- chdir $Cfg::Preferences{proftpd_conf_path};
- if($action eq "list")
- {
- my $users;
- open(PASSWD, 'ftpd.passwd');
- while (<PASSWD>) {
- chomp;
- my($login, $passwd, $uid, $gid, $gcos, $home, $shell) = split(/:/);
- $users .= "$login\t$home\n";
- }
- close(PASSWD);
- return "1;".encode_list($users);
- }
- elsif($action eq "userdel")
- {
- return sudo_exec_without_decrypt("ftpasswd --passwd --delete-user --name='$login'");
- }
- elsif($action eq "useradd")
- {
- return sudo_exec_without_decrypt("echo '$password' | ftpasswd --passwd --name='$login' --home='$home_path' --shell=/bin/false --uid=$uid --gid=$gid --stdin");
- }
- elsif($action eq "passwd")
- {
- return sudo_exec_without_decrypt("echo '$password' | ftpasswd --passwd --change-password --name='$login' --stdin");
- }
- elsif($action eq "show")
- {
- return 1;
- }
- elsif($action eq "usermod")
- {
- return 1;
- }
- chdir AGENT_RUN_DIR;
- }
- else
- {
- if($action eq "list")
- {
- return sudo_exec_without_decrypt("pure-pw list");
- }
- elsif($action eq "userdel")
- {
- return sudo_exec_without_decrypt("pure-pw userdel '$login' && pure-pw mkdb");
- }
- elsif($action eq "useradd")
- {
- return sudo_exec_without_decrypt("(echo '$password'; echo '$password') | pure-pw useradd '$login' -u $uid -g $gid -d '$home_path' && pure-pw mkdb");
- }
- elsif($action eq "passwd")
- {
- return sudo_exec_without_decrypt("(echo '$password'; echo '$password') | pure-pw passwd '$login' && pure-pw mkdb");
- }
- elsif($action eq "show")
- {
- return sudo_exec_without_decrypt("pure-pw show '$login'");
- }
- elsif($action eq "usermod")
- {
- my $update_account = "pure-pw usermod '$login' -u $uid -g $gid";
-
- my @account_settings = split /[\n]+/, $password;
-
- foreach my $setting (@account_settings) {
- my ($key, $value) = split /[\t]+/, $setting;
-
- if( $key eq 'Directory' )
- {
- $value =~ s/('+)/'\"$1\"'/g;
- $update_account .= " -d '$value'";
- }
-
- if( $key eq 'Full_name' )
- {
- if( $value ne "" )
- {
- $value =~ s/('+)/'\"$1\"'/g;
- $update_account .= " -c '$value'";
- }
- else
- {
- $update_account .= ' -c ""';
- }
- }
-
- if( $key eq 'Download_bandwidth' && $value ne "" )
- {
- my $Download_bandwidth;
- if($value eq 0)
- {
- $Download_bandwidth = "\"\"";
- }
- else
- {
- $Download_bandwidth = $value;
- }
- $update_account .= " -t " . $Download_bandwidth;
- }
-
- if( $key eq 'Upload___bandwidth' && $value ne "" )
- {
- my $Upload___bandwidth;
- if($value eq 0)
- {
- $Upload___bandwidth = "\"\"";
- }
- else
- {
- $Upload___bandwidth = $value;
- }
- $update_account .= " -T " . $Upload___bandwidth;
- }
-
- if( $key eq 'Max_files' )
- {
- if( $value eq "0" )
- {
- $update_account .= ' -n ""';
- }
- elsif( $value ne "" )
- {
- $update_account .= " -n " . $value;
- }
- else
- {
- $update_account .= ' -n ""';
- }
- }
-
- if( $key eq 'Max_size' )
- {
- if( $value ne "" && $value ne "0" )
- {
- $update_account .= " -N " . $value;
- }
- else
- {
- $update_account .= ' -N ""';
- }
- }
-
- if( $key eq 'Ratio' && $value ne "" )
- {
- my($upload_ratio,$download_ratio) = split/:/,$value;
-
- if($upload_ratio eq "0")
- {
- $upload_ratio = "\"\"";
- }
- $update_account .= " -q " . $upload_ratio;
-
- if($download_ratio eq "0")
- {
- $download_ratio = "\"\"";
- }
- $update_account .= " -Q " . $download_ratio;
- }
-
- if( $key eq 'Allowed_client_IPs' )
- {
- if( $value ne "" )
- {
- $update_account .= " -r " . $value;
- }
- else
- {
- $update_account .= ' -r ""';
- }
- }
-
- if( $key eq 'Denied__client_IPs' )
- {
- if( $value ne "" )
- {
- $update_account .= " -R " . $value;
- }
- else
- {
- $update_account .= ' -R ""';
- }
- }
-
- if( $key eq 'Allowed_local__IPs' )
- {
- if( $value ne "" )
- {
- $update_account .= " -i " . $value;
- }
- else
- {
- $update_account .= ' -i ""';
- }
- }
-
- if( $key eq 'Denied__local__IPs' )
- {
- if( $value ne "" )
- {
- $update_account .= " -I " . $value;
- }
- else
- {
- $update_account .= ' -I ""';
- }
- }
-
-
- if( $key eq 'Max_sim_sessions' && $value ne "" )
- {
- $update_account .= " -y " . $value;
- }
-
- if ( $key eq 'Time_restrictions' )
- {
- if( $value eq "0000-0000")
- {
- $update_account .= ' -z ""';
- }
- elsif( $value ne "" )
- {
- $update_account .= " -z " . $value;
- }
- else
- {
- $update_account .= ' -z ""';
- }
- }
- }
- $update_account .=" && pure-pw mkdb";
- # print $update_account;
- return sudo_exec_without_decrypt($update_account);
- }
- }
- }
- return 0;
- }
- sub start_fastdl
- {
- if(-e Path::Class::File->new(FD_DIR, 'Settings.pm'))
- {
- system('perl FastDownload/ForkedDaemon.pm &');
- sleep(1);
- return 1;
- }
- else
- {
- return -2;
- }
- }
- sub stop_fastdl
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return stop_fastdl_without_decrypt();
- }
- sub stop_fastdl_without_decrypt
- {
- my $pid;
- open(PIDFILE, '<', FD_PID_FILE)
- || logger "Error reading pid file $!",1;
- while (<PIDFILE>)
- {
- $pid = $_;
- chomp $pid;
- }
- close(PIDFILE);
- my $cnt = kill 9, $pid;
- if ($cnt == 1)
- {
- logger "Fast Download Daemon Stopped.",1;
- return 1;
- }
- else
- {
- logger "Fast Download Daemon with pid $pid can not be stopped.",1;
- return -1;
- }
- }
- sub restart_fastdl
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return restart_fastdl_without_decrypt();
- }
- sub restart_fastdl_without_decrypt
- {
- if((fastdl_status_without_decrypt() == -1) || (stop_fastdl_without_decrypt() == 1))
- {
- if(start_fastdl() == 1)
- {
- # Success
- return 1;
- }
- # Cant start
- return -2;
- }
- # Cant stop
- return -3;
- }
- sub fastdl_status
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- return fastdl_status_without_decrypt();
- }
- sub fastdl_status_without_decrypt
- {
- my $pid;
- if(!open(PIDFILE, '<', FD_PID_FILE))
- {
- logger "Error reading pid file $!";
- return -1;
- }
- while (<PIDFILE>)
- {
- $pid = $_;
- chomp $pid;
- }
- close(PIDFILE);
- my $cnt = kill 0, $pid;
- if ($cnt == 1)
- {
- return 1;
- }
- else
- {
- return -1;
- }
- }
- sub fastdl_get_aliases
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my %aliases;
- my $i;
- my @file_lines;
- if(-d FD_ALIASES_DIR)
- {
- if( !opendir(ALIASES, FD_ALIASES_DIR) )
- {
- logger "Error openning aliases directory " . FD_ALIASES_DIR . ", $!";
- }
- else
- {
- while (my $alias = readdir(ALIASES))
- {
- # Skip . and ..
- next if $alias =~ /^\./;
- if( !open(ALIAS, '<', Path::Class::Dir->new(FD_ALIASES_DIR, $alias)) )
- {
- logger "Error reading alias '$alias', $!";
- }
- else
- {
- $i = 0;
- @file_lines = ();
- while (<ALIAS>)
- {
- chomp $_;
- $file_lines[$i] = $_;
- $i++;
- }
- close(ALIAS);
- $aliases{$alias}{home} = $file_lines[0];
- $aliases{$alias}{match_file_extension} = $file_lines[1];
- $aliases{$alias}{match_client_ip} = $file_lines[2];
- }
- }
- closedir(ALIASES);
- }
- }
- else
- {
- logger "Aliases directory '" . FD_ALIASES_DIR . "' does not exist or is inaccessible.";
- }
- return {%aliases};
- }
- sub fastdl_del_alias
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- foreach my $alias (decrypt_params(@_))
- {
- unlink Path::Class::File->new(FD_ALIASES_DIR, $alias);
- }
- return restart_fastdl_without_decrypt();
- }
- sub fastdl_add_alias
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($alias,$home,$match_file_extension,$match_client_ip) = decrypt_params(@_);
- if(!-e FD_ALIASES_DIR)
- {
- if(!mkdir FD_ALIASES_DIR)
- {
- logger "ERROR - Failed to create " . FD_ALIASES_DIR . " directory.";
- return -1;
- }
- }
- my $alias_path = Path::Class::File->new(FD_ALIASES_DIR, $alias);
- if (!open(ALIAS, '>', $alias_path))
- {
- logger "ERROR - Failed to open ".$alias_path." for writing.";
- return -1;
- }
- else
- {
- print ALIAS "$home\n";
- print ALIAS "$match_file_extension\n";
- print ALIAS "$match_client_ip";
- close(ALIAS);
- return restart_fastdl_without_decrypt();
- }
- }
- sub fastdl_get_info
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- if(-e Path::Class::File->new(FD_DIR, 'Settings.pm'))
- {
- delete $INC{"FastDownload/Settings.pm"};
- require "FastDownload/Settings.pm"; # Settings for Fast Download Daemon.
- if(not defined $FastDownload::Settings{autostart_on_agent_startup})
- {
- $FastDownload::Settings{autostart_on_agent_startup} = 0;
- }
- return {'port' => $FastDownload::Settings{port},
- 'ip' => $FastDownload::Settings{ip},
- 'listing' => $FastDownload::Settings{listing},
- 'autostart_on_agent_startup'=> $FastDownload::Settings{autostart_on_agent_startup}};
- }
- return -1
- }
- sub fastdl_create_config
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- if(!-e FD_DIR)
- {
- if(!mkdir FD_DIR)
- {
- logger "ERROR - Failed to create " . FD_DIR . " directory.";
- return -1;
- }
- }
- my ($fd_address, $fd_port, $listing, $autostart_on_agent_startup) = decrypt_params(@_);
- my $settings_string = "%FastDownload::Settings = (\n".
- "\tport => $fd_port,\n".
- "\tip => '$fd_address',\n".
- "\tlisting => $listing,\n".
- "\tautostart_on_agent_startup => $autostart_on_agent_startup,\n".
- ");";
- my $settings = Path::Class::File->new(FD_DIR, 'Settings.pm');
- if (!open(SETTINGS, '>', $settings))
- {
- logger "ERROR - Failed to open $settings for writing.";
- return -1;
- }
- else
- {
- print SETTINGS $settings_string;
- close(SETTINGS);
- }
- logger "$settings file written successfully.";
- return 1;
- }
- sub agent_restart
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $dec_check = decrypt_param(@_);
- if ($dec_check eq 'restart')
- {
- chdir AGENT_RUN_DIR;
- if(-e "ogp_agent_run.pid")
- {
- my $init_pid = `cat ogp_agent_run.pid`;
- chomp($init_pid);
-
- if(kill 0, $init_pid)
- {
- my $or_exist = "";
- my $rm_pid_file = "";
- if(-e "ogp_agent.pid")
- {
- $rm_pid_file = " ogp_agent.pid";
- my $agent_pid = `cat ogp_agent.pid`;
- chomp($agent_pid);
- if( kill 0, $agent_pid )
- {
- $or_exist = " -o -e /proc/$agent_pid";
- }
- }
-
- open (AGENT_RESTART_SCRIPT, '>', 'tmp_restart.sh');
- my $restart = "echo -n \"Stopping OGP Agent...\"\n".
- "kill $init_pid\n".
- "while [ -e /proc/$init_pid $or_exist ];do echo -n .;sleep 1;done\n".
- "rm -f ogp_agent_run.pid $rm_pid_file\necho \" [OK]\"\n".
- "echo -n \"Starting OGP Agent...\"\n".
- "screen -d -m -t \"ogp_agent\" -c \"" . SCREENRC_FILE . "\" -S ogp_agent bash ogp_agent_run -pidfile ogp_agent_run.pid\n".
- "while [ ! -e ogp_agent_run.pid -o ! -e ogp_agent.pid ];do echo -n .;sleep 1;done\n".
- "echo \" [OK]\"\n".
- "rm -f tmp_restart.sh\n".
- "exit 0\n";
- print AGENT_RESTART_SCRIPT $restart;
- close (AGENT_RESTART_SCRIPT);
- if( -e 'tmp_restart.sh' )
- {
- system('screen -d -m -t "agent_restart" -c "' . SCREENRC_FILE . '" -S agent_restart bash tmp_restart.sh');
- }
- }
- }
- }
- return -1;
- }
- # Subroutines to be called
- sub scheduler_dispatcher {
- my ($task, $args) = @_;
- my $response = `$args`;
- chomp($response);
- my $log = "Executed command: $args";
- if($response ne "")
- {
- $log .= ", response:\n$response";
- }
- scheduler_log_events($log);
- }
- sub scheduler_server_action
- {
- my ($task, $args) = @_;
- my ($action, @server_args) = split('\|\%\|', $args);
- if($action eq "%ACTION=start")
- {
- my ($home_id, $ip, $port) = ($server_args[0], $server_args[6], $server_args[5]);
- my $ret = universal_start_without_decrypt(@server_args);
- if($ret == 1)
- {
- scheduler_log_events("Started server home ID $home_id on address $ip:$port");
- }
- else
- {
- scheduler_log_events("Failed starting server home ID $home_id on address $ip:$port (Check agent log)");
- }
- }
- elsif($action eq "%ACTION=stop")
- {
- my ($home_id, $ip, $port) = ($server_args[0], $server_args[1], $server_args[2]);
- my $ret = stop_server_without_decrypt(@server_args);
- if($ret == 0)
- {
- scheduler_log_events("Stopped server home ID $home_id on address $ip:$port");
- }
- elsif($ret == 1)
- {
- scheduler_log_events("Failed stopping server home ID $home_id on address $ip:$port (Invalid IP:Port given)");
- }
- }
- elsif($action eq "%ACTION=restart")
- {
- my ($home_id, $ip, $port) = ($server_args[0], $server_args[1], $server_args[2]);
- my $ret = restart_server_without_decrypt(@server_args);
- if($ret == 1)
- {
- scheduler_log_events("Restarted server home ID $home_id on address $ip:$port");
- }
- elsif($ret == -1)
- {
- scheduler_log_events("Failed restarting server home ID $home_id on address $ip:$port (Server could not be started, check agent log)");
- }
- elsif($ret == -2)
- {
- scheduler_log_events("Failed restarting server home ID $home_id on address $ip:$port (Server could not be stopped, check agent log)");
- }
- }
- return 1;
- }
- sub scheduler_log_events
- {
- my $logcmd = $_[0];
- $logcmd = localtime() . " $logcmd\n";
- logger "Can't open " . SCHED_LOG_FILE . " - $!" unless open(LOGFILE, '>>', SCHED_LOG_FILE);
- logger "Failed to lock " . SCHED_LOG_FILE . "." unless flock(LOGFILE, LOCK_EX);
- logger "Failed to seek to end of " . SCHED_LOG_FILE . "." unless seek(LOGFILE, 0, 2);
- logger "Failed to write to " . SCHED_LOG_FILE . "." unless print LOGFILE "$logcmd";
- logger "Failed to unlock " . SCHED_LOG_FILE . "." unless flock(LOGFILE, LOCK_UN);
- logger "Failed to close " . SCHED_LOG_FILE . "." unless close(LOGFILE);
- }
- sub scheduler_add_task
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $new_task = decrypt_param(@_);
- if (open(TASKS, '>>', SCHED_TASKS))
- {
- print TASKS "$new_task\n";
- logger "Created new task: $new_task";
- close(TASKS);
- scheduler_stop();
- # Create new object with default dispatcher for scheduled tasks
- $cron = new Schedule::Cron( \&scheduler_dispatcher, {
- nofork => 1,
- loglevel => 0,
- log => sub { print $_[1], "\n"; }
- } );
- $cron->add_entry( "* * * * * *", \&scheduler_read_tasks );
- # Run scheduler
- $cron->run( {detach=>1, pid_file=>SCHED_PID} );
- return 1;
- }
- logger "Cannot create task: $new_task ( $! )";
- return -1;
- }
- sub scheduler_del_task
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $name = decrypt_param(@_);
- if( scheduler_read_tasks() == -1 )
- {
- return -1;
- }
- my @entries = $cron->list_entries();
- if(open(TASKS, '>', SCHED_TASKS))
- {
- foreach my $task ( @entries ) {
- next if $task->{args}[0] eq $name;
- next unless $task->{args}[0] =~ /task_[0-9]*/;
- if(defined $task->{args}[1])
- {
- print TASKS join(" ", $task->{time}, $task->{args}[1]) . "\n";
- }
- else
- {
- print TASKS $task->{time} . "\n";
- }
- }
- close( TASKS );
- scheduler_stop();
- # Create new object with default dispatcher for scheduled tasks
- $cron = new Schedule::Cron( \&scheduler_dispatcher, {
- nofork => 1,
- loglevel => 0,
- log => sub { print $_[1], "\n"; }
- } );
- $cron->add_entry( "* * * * * *", \&scheduler_read_tasks );
- # Run scheduler
- $cron->run( {detach=>1, pid_file=>SCHED_PID} );
- return 1;
- }
- logger "Cannot open file " . SCHED_TASKS . " for deleting task id: $name ( $! )",1;
- return -1;
- }
- sub scheduler_edit_task
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($name, $new_task) = decrypt_params(@_);
- if( scheduler_read_tasks() == -1 )
- {
- return -1;
- }
- my @entries = $cron->list_entries();
- if(open(TASKS, '>', SCHED_TASKS))
- {
- foreach my $task ( @entries ) {
- next unless $task->{args}[0] =~ /task_[0-9]*/;
- if($name eq $task->{args}[0])
- {
- print TASKS "$new_task\n";
- }
- else
- {
- if(defined $task->{args}[1])
- {
- print TASKS join(" ", $task->{time}, $task->{args}[1]) . "\n";
- }
- else
- {
- print TASKS $task->{time} . "\n";
- }
- }
- }
- close( TASKS );
- scheduler_stop();
- # Create new object with default dispatcher for scheduled tasks
- $cron = new Schedule::Cron( \&scheduler_dispatcher, {
- nofork => 1,
- loglevel => 0,
- log => sub { print $_[1], "\n"; }
- } );
- $cron->add_entry( "* * * * * *", \&scheduler_read_tasks );
- # Run scheduler
- $cron->run( {detach=>1, pid_file=>SCHED_PID} );
- return 1;
- }
- logger "Cannot open file " . SCHED_TASKS . " for editing task id: $name ( $! )",1;
- return -1;
- }
- sub scheduler_read_tasks
- {
- if( open(TASKS, '<', SCHED_TASKS) )
- {
- $cron->clean_timetable();
- }
- else
- {
- logger "Error reading tasks file $!";
- scheduler_stop();
- return -1;
- }
-
- my $i = 0;
- while (<TASKS>)
- {
- next if $_ =~ /^(#.*|[\s|\t]*?\n)/;
- my ($minute, $hour, $dayOfTheMonth, $month, $dayOfTheWeek, @args) = split(' ', $_);
- my $time = "$minute $hour $dayOfTheMonth $month $dayOfTheWeek";
- if("@args" =~ /^\%ACTION.*/)
- {
- $cron->add_entry($time, \&scheduler_server_action, 'task_' . $i++, "@args");
- }
- else
- {
- $cron->add_entry($time, 'task_' . $i++, "@args");
- }
- }
- close(TASKS);
- return 1;
- }
- sub scheduler_stop
- {
- my $pid;
- if(open(PIDFILE, '<', SCHED_PID))
- {
- $pid = <PIDFILE>;
- chomp $pid;
- close(PIDFILE);
- if($pid ne "")
- {
- if( kill 0, $pid )
- {
- my $cnt = kill 9, $pid;
- if ($cnt == 1)
- {
- unlink SCHED_PID;
- return 1;
- }
- }
- }
- }
- return -1;
- }
- sub scheduler_list_tasks
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- if( scheduler_read_tasks() == -1 )
- {
- return -1;
- }
- my @entries = $cron->list_entries();
- my %entries_array;
- foreach my $task ( @entries ) {
- if( defined $task->{args}[1] )
- {
- $entries_array{$task->{args}[0]} = encode_base64(join(" ", $task->{time}, $task->{args}[1]));
- }
- else
- {
- $entries_array{$task->{args}[0]} = encode_base64($task->{time});
- }
- }
- if( %entries_array )
- {
- return {%entries_array};
- }
- return -1;
- }
- sub get_file_part
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($file, $offset) = decrypt_params(@_);
- if (!open(FILE, '<', $file))
- {
- logger "ERROR - Can't open file $file for reading.";
- return -1;
- }
-
- binmode(FILE);
-
- if($offset != 0)
- {
- return -1 unless seek FILE, $offset, 0;
- }
-
- my $data = "";
- my ($n, $buf);
- my $limit = $offset + 60 * 57 * 1000; #Max 3420Kb (1000 iterations) (top statistics ~ VIRT 116m, RES 47m)
- while (($n = read FILE, $buf, 60 * 57) != 0 && $offset <= $limit ) {
- $data .= $buf;
- $offset += $n;
- }
- close(FILE);
-
- if( $data ne "" )
- {
- my $b64zlib = encode_base64(compress($data,9));
- return "$offset;$b64zlib";
- }
- else
- {
- return -1;
- }
- }
- sub stop_update
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my $home_id = decrypt_param(@_);
- my $screen_id = create_screen_id(SCREEN_TYPE_UPDATE, $home_id);
- system('screen -S '.$screen_id.' -p 0 -X stuff $\'\003\'');
- if ($? == 0)
- {
- return 0;
- }
- return 1
- }
- sub shell_action
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($action, $arguments) = decrypt_params(@_);
-
- if($action eq 'remove_file')
- {
- chomp($arguments);
- unlink($arguments);
- return "1;";
- }
- elsif($action eq 'remove_recursive')
- {
- my @items = split(';', $arguments);
- foreach my $item ( @items ) {
- chomp($item);
- if(-d $item)
- {
- pathrmdir($item);
- }
- else
- {
- unlink($item);
- }
- }
- return "1;";
- }
- elsif($action eq 'create_dir')
- {
- chomp($arguments);
- mkpath($arguments);
- return "1;";
- }
- elsif($action eq 'move')
- {
- my($src, $dest) = split(';', $arguments);
- chomp($src);
- chomp($dest);
- if(-d $src)
- {
- $dest = Path::Class::Dir->new($dest, basename($src));
- dirmove($src, $dest);
- }
- else
- {
- fmove($src, $dest);
- }
- return "1;";
- }
- elsif($action eq 'copy')
- {
- my($src, $dest) = split(';', $arguments);
- chomp($src);
- chomp($dest);
- if(-d $src)
- {
- $dest = Path::Class::Dir->new($dest, basename($src));
- dircopy($src, $dest);
- }
- else
- {
- fcopy($src, $dest);
- }
- return "1;";
- }
- elsif($action eq 'touch')
- {
- chomp($arguments);
- open(FH, '>', $arguments);
- print FH "";
- close(FH);
- return "1;";
- }
- elsif($action eq 'size')
- {
- chomp($arguments);
- my $size = 0;
- if(-d $arguments)
- {
- find(sub { $size += -s }, $arguments ? $arguments : '.');
- }
- else
- {
- $size += (stat($arguments))[7];
- }
- return "1;" . encode_list($size);
- }
- elsif($action eq 'get_cpu_usage')
- {
- my %prev_idle;
- my %prev_total;
- open(STAT, '/proc/stat');
- while (<STAT>) {
- next unless /^cpu([0-9]+)/;
- my @stat = split /\s+/, $_;
- $prev_idle{$1} = $stat[4];
- $prev_total{$1} = $stat[1] + $stat[2] + $stat[3] + $stat[4];
- }
- close STAT;
- sleep 1;
- my %idle;
- my %total;
- open(STAT, '/proc/stat');
- while (<STAT>) {
- next unless /^cpu([0-9]+)/;
- my @stat = split /\s+/, $_;
- $idle{$1} = $stat[4];
- $total{$1} = $stat[1] + $stat[2] + $stat[3] + $stat[4];
- }
- close STAT;
- my %cpu_percent_usage;
- foreach my $key ( keys %idle )
- {
- my $diff_idle = $idle{$key} - $prev_idle{$key};
- my $diff_total = $total{$key} - $prev_total{$key};
- my $percent = (100 * ($diff_total - $diff_idle)) / $diff_total;
- $percent = sprintf "%.2f", $percent unless $percent == 0;
- $cpu_percent_usage{$key} = encode_base64($percent);
- }
- return {%cpu_percent_usage};
- }
- elsif($action eq 'get_ram_usage')
- {
- my($total, $buffers, $cached, $free) = qw(0 0 0 0);
- open(STAT, '/proc/meminfo');
- while (<STAT>) {
- $total += $1 if /MemTotal\:\s+(\d+) kB/;
- $buffers += $1 if /Buffers\:\s+(\d+) kB/;
- $cached += $1 if /Cached\:\s+(\d+) kB/;
- $free += $1 if /MemFree\:\s+(\d+) kB/;
- }
- close STAT;
- my $used = $total - $free - $cached - $buffers;
- my $percent = 100 * $used / $total;
- my %mem_usage;
- $mem_usage{'used'} = encode_base64($used * 1024);
- $mem_usage{'total'} = encode_base64($total * 1024);
- $mem_usage{'percent'} = encode_base64($percent);
- return {%mem_usage};
- }
- elsif($action eq 'get_disk_usage')
- {
- my($total, $used, $free) = split(' ', `df -lP 2>/dev/null|grep "^/dev/.*"|awk '{total+=\$2}{used+=\$3}{free+=\$4} END {print total, used, free}'`);
- my $percent = 100 * $used / $total;
- my %disk_usage;
- $disk_usage{'free'} = encode_base64($free * 1024);
- $disk_usage{'used'} = encode_base64($used * 1024);
- $disk_usage{'total'} = encode_base64($total * 1024);
- $disk_usage{'percent'} = encode_base64($percent);
- return {%disk_usage};
- }
- elsif($action eq 'get_uptime')
- {
- open(STAT, '/proc/uptime');
- my $uptime = 0;
- while (<STAT>) {
- $uptime += $1 if /^([0-9]+)/;
- }
- close STAT;
- my %upsince;
- $upsince{'0'} = encode_base64($uptime);
- $upsince{'1'} = encode_base64(time - $uptime);
- return {%upsince};
- }
- elsif($action eq 'get_tasklist')
- {
- my %taskList;
- $taskList{'task'} = encode_base64(`top -b -c -i -w512 -n2 | awk '/^top/{i++}i==2' | grep "COMMAND" -A 30`);
- return {%taskList};
- }
- elsif($action eq 'get_timestamp')
- {
- return "1;" . encode_list(time);
- }
- return 0;
- }
- sub remote_query
- {
- return "Bad Encryption Key" unless(decrypt_param(pop(@_)) eq "Encryption checking OK");
- my ($protocol, $game_type, $ip, $c_port, $q_port, $s_port) = decrypt_params(@_);
- my $command = "which php-cgi 2>&1;echo \$?";
- my @cmdret = qx($command);
- chomp(@cmdret);
- my $ret = pop(@cmdret);
- chomp($ret);
- if ("X$ret" ne "X0")
- {
- return -1;
- }
- my $PHP_CGI = "@cmdret";
- my $php_query_dir = Path::Class::Dir->new(AGENT_RUN_DIR, 'php-query');
- if($protocol eq 'lgsl')
- {
- chdir($php_query_dir->subdir('lgsl'));
- my $cmd = $PHP_CGI .
- " -f lgsl_feed.php" .
- " lgsl_type=" . $game_type .
- " ip=" . $ip .
- " c_port=" . $c_port .
- " q_port=" . $q_port .
- " s_port=" . $s_port .
- " request=sp";
- my $response = `$cmd`;
- chomp($response);
- chdir(AGENT_RUN_DIR);
- if($response eq "FAILURE")
- {
- return -1;
- }
- return encode_base64($response, "");
- }
- elsif($protocol eq 'gameq')
- {
- chdir($php_query_dir->subdir('gameq'));
- my $cmd = $PHP_CGI .
- " -f gameq_feed.php" .
- " game_type=" . $game_type .
- " ip=" . $ip .
- " c_port=" . $c_port .
- " q_port=" . $q_port .
- " s_port=" . $s_port;
- my $response = `$cmd`;
- chomp($response);
- chdir(AGENT_RUN_DIR);
- if($response eq "FAILURE")
- {
- return -1;
- }
- return encode_base64($response, "");
- }
- return -1;
- }
|