<?php

// En todas las funciones, la llamada a gestionAlerta debe ser anterior a meter los datos en el historico, sino no se puede comparar.

function cron_ping($db_conn,$time,$pc){

    $res = ping($pc['IP']); //Created func.
    if ($res != '-1'){
        gestionAlerta($pc,'PING','ping',1); //1 -> OK, 0 -> Not OK
        dbw_query($db_conn,"UPDATE SERVERS SET `Online` = 1 WHERE ID_SERV='$pc[ID_SERV]'");
	
    }else{ //Off / No ping
        gestionAlerta($pc,'PING','ping',0);
        dbw_query($db_conn,"UPDATE SERVERS SET `Online` = 0, Uptime = 0 WHERE ID_SERV='$pc[ID_SERV]'");
    }

    //Only change if ping number changes
    if ((int)dbw_query_fetch_array($db_conn,"SELECT * FROM S_HISTPING WHERE ID_SERV='$pc[ID_SERV]' ORDER BY `Timestamp` DESC LIMIT 1")['Value'] !== (int)$res){
        dbw_query($db_conn,"INSERT INTO S_HISTPING (ID_SERV,`Timestamp`,`Value`) VALUES ('$pc[ID_SERV]','$time','$res')");
    }else if (dbw_query_fetch_array($db_conn,"SELECT COUNT(*) FROM S_HISTPING WHERE ID_SERV='$pc[ID_SERV]'")[0] == 0){ //If empty.
        dbw_query($db_conn,"INSERT INTO S_HISTPING (ID_SERV,`Timestamp`,`Value`) VALUES ('$pc[ID_SERV]','$time','$res')");
    }
	
	if (DEBUG){
		$log[] = "Ping: ".$res;
    }
	
	return $res;

}


function cron_service($db_conn,$time,$pc,$service){

    switch ($pc['SO']){
        case 'WINDOWS':
            $resu = shell_exec('net rpc service status '.$service['Name'].' -I '.$pc['IP'].' -U  \''.$pc['User'].'%'.$pc['Password'].'\' 2>&1');

            if (strpos($resu, 'stop') !== false || strpos($resu, 'WERR') !== false){
                $status = 0; //Not Working
            }else{
                $status = 1;
            }
        break;
        case 'LINUX_SYSTEMD':
            $lines = explode(PHP_EOL,commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'systemctl status '.$service['Name'].'>/dev/null;echo $?'));
            $lines = removeEmptyLines($lines);
            $lastline = $lines[count($lines)-1];
            $status = $lastline != 0 ? 0 : 1; //3 is stop, 4 is non exist
        break;
        case 'LINUX_SERVICE':
        case 'BSD_SERVICE': //BSD Has too the service command, but I don't know if it's same as Linux
            $lines = explode(PHP_EOL,commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'service '.$service['Name'].' status;echo $?'));
            $lastline = $lines[count($lines)-1];
            $status = $lastline != 0 ? 0 : 1; //3 is stop (TODO see number)
        break;
        case 'LINUX': //Proceso
        case 'BSD': //BSD Uses process too
            $lines = explode(PHP_EOL,commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'ps -A | grep '.$service['Name']));
            //$lastline = $lines[count($lines)-1];
            if (count($lines)){
                $status = 1;
            }else{
                $status = 0; //Not found
            }
        break;
    }

    gestionAlerta($pc,'SERVICE',$service['Name'],$status);
    //Update in tables
    dbw_query($db_conn,"UPDATE S_SERVICES SET `Status` = '$status' WHERE ID_SERV='$pc[ID_SERV]' AND `Name` = '$service[Name]'");



    //Only change if ping number changes
    if ((int)dbw_query_fetch_array($db_conn,"SELECT * FROM S_HISTSERVICES WHERE ID_SERV='$pc[ID_SERV]' ORDER BY `Timestamp` DESC LIMIT 1")['Status'] !== (int)$status){
        dbw_query($db_conn,"INSERT INTO S_HISTSERVICES (ID_SERV,`Name`,`Timestamp`,`Status`) VALUES ('$pc[ID_SERV]','$service[Name]','$time','$status')");
    }else if (dbw_query_fetch_array($db_conn,"SELECT COUNT(*) FROM S_HISTSERVICES WHERE ID_SERV='$pc[ID_SERV]'")[0] == 0){ //If empty.
        dbw_query($db_conn,"INSERT INTO S_HISTSERVICES (ID_SERV,`Name`,`Timestamp`,`Status`) VALUES ('$pc[ID_SERV]','$service[Name]','$time','$status')");
    }    
}


function cron_webservice($db_conn,$time,$pc,$service){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $service['Name']);
    curl_setopt($ch, CURLOPT_HEADER, TRUE);
    curl_setopt($ch, CURLOPT_NOBODY, TRUE); // remove body
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_TIMEOUT, 3); //timeout in seconds
    $head = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($head = 200){
        $status = 1;
    }else{
        $status = 0;
    }

    gestionAlerta($pc,'WEBSERVICE',$service['Name'],$status);

    dbw_query($db_conn,"UPDATE S_SERVICES SET `Status` = '$status' WHERE ID_SERV='$pc[ID_SERV]' AND `Name` = '$service[Name]'");

    //Only change if ping number changes
    if ((int)dbw_query_fetch_array($db_conn,"SELECT * FROM S_HISTSERVICES WHERE ID_SERV='$pc[ID_SERV]' ORDER BY `Timestamp` DESC LIMIT 1")['Status'] !== (int)$status){
        dbw_query($db_conn,"INSERT INTO S_HISTSERVICES (ID_SERV,`Name`,`Timestamp`,`Status`) VALUES ('$pc[ID_SERV]','$service[Name]','$time','$status')");
    }else if (dbw_query_fetch_array($db_conn,"SELECT COUNT(*) FROM S_HISTSERVICES WHERE ID_SERV='$pc[ID_SERV]'")[0] == 0){ //If empty.
        dbw_query($db_conn,"INSERT INTO S_HISTSERVICES (ID_SERV,`Name`,`Timestamp`,`Status`) VALUES ('$pc[ID_SERV]','$service[Name]','$time','$status')");
    } 
}


//Function status for cron
function cron_status($db_conn,$time,$pc){
    $pass =$pc['Password'];
    
    //Get Free RAM and total RAM
    switch ($pc['SO']){
        case 'WINDOWS':
            $wql = "select FreePhysicalMemory from Win32_OperatingSystem";
            $freeramwmic = shell_exec('wmic -U \''.$pc['User'].'%'.$pass.'\' //'.$pc['IP'].' "'.$wql.'"');

            //showdeb($freeramwmic);

            $freeramexp = explode(PHP_EOL,$freeramwmic);
            $freeram = explode('|',$freeramexp[2])[0]*1024; //Third line. Windows doesn't have tail -n+3 and cut. Also show in KB
            
            $wql = "select TotalPhysicalMemory from Win32_ComputerSystem";
            $totalramwmic = shell_exec('wmic -U '.$pc['User'].'%'.$pass.' //'.$pc['IP'].' "'.$wql.'"');
            $totalramexp = explode(PHP_EOL,$totalramwmic);
            $detram = explode('|',$totalramexp[2])[1]; //Third line. Windows doesn't have tail an cut. This is in KB directly
        break;
        case 'LINUX_SYSTEMD':
        case 'LINUX_SERVICE':
        case 'LINUX': //Systemd and init goes same way
            $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'free -b | tail -n+2 | head -1');
            $line = preg_replace("/[[:blank:]]+/",' ',$resu);
            $part = explode(' ',$line);
            //Mem:    total        used        free      shared  buff/cache   available
            $detram = $part[1]; //Total RAM
            if (isset($part[6])){
                $freeram = $part[6];//Avaiable
            }else{ //Some systems do not have avaiable col
                $freeram = $part[4];//Free
            }
        break;
        case 'BSD':
            $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'sysctl hw.physmem');
            $line = preg_replace("/[[:blank:]]+/",' ',$resu);
            $part = explode(' ',$line);
            $detram = $part[1]; //Total RAM

            $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'vmstat | grep -E \'([0-9]+\w+)+\' | awk \'{print $5}\'');
            $line = preg_replace("/[[:blank:]]+/",' ',$resu);
            $freeram = $line*1024; //Free RAM (In Bytes, program shows in Kb)
        break;
    }
    dbw_query($db_conn,"INSERT INTO S_HISTRAM (ID_SERV,`Timestamp`,Freeram,Detram) VALUES ('$pc[ID_SERV]','$time','$freeram','$detram')");

    if (percalertfor('RAM')){ //Only set if alert percent is configured.
        $percent = percent($freeram,$detram);
        if  (percent($freeram,$detram) < percalertfor('RAM')){ //HDD Lower than alert position
            gestionAlerta($pc,'RAM',$percent,0); //1 -> OK, 0 -> Not OK
        }else{
            gestionAlerta($pc,'RAM',$percent,1); //1 -> OK, 0 -> Not OK
        }
    }


    
    //Get drives and free space
    if ($pc['SO'] == "WINDOWS"){
        $resu = shell_exec('wmic -U \''.$pc['User'].'%'.$pass.'\' //'.$pc['IP'].' "select FreeSpace,Size from Win32_LogicalDisk where DriveType=3"');
        $explines = explode(PHP_EOL,$resu);
        $explines = removeEmptyLines($explines);
        //As Windows doesnt have tail command, I have to emulate " | tail -n+2"
        if (DEBUG)
            var_dump($explines);
        for ($x = 0;$x < 2;$x++){array_shift($explines);}

        
        foreach($explines as $line){
            $part = explode('|',$line);
            //Drive, Space, FreeSpace
            if (isset($part[1]) && $part[2] != 0){
                $unidades[] = array ($part[0],$part[2],$part[1]);
            }  
        }
    }else if ($pc['SO'] == "BSD"){ //BSD "Standard" command df, not as GNU/Linux df one
        $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'exec df -P -k -t notmpfs,devfs,fdescfs | tail -n+2');
        $explines = preg_split('/[\r\n]+/', $resu);
        foreach($explines as $line){
            $line = preg_replace("/[[:blank:]]+/",' ',$line);
            $part = explode(' ',$line);
            //Filesystem         1024-blocks    Used     Avail Capacity  Mounted on
            if (isset($part[1])){ 
                $unidades[] = array ($part[5],$part[1]*1024,$part[3]*1024);//Drive, Space, FreeSpace  (*1024 because has to be in bytes)
            }  
        }
    }else{ //LINUX. Almost standard df
        //I use exec for avoid alias that bash can have (Anarchy has a custom df alias for example)
        $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'exec df --output=source,size,used,avail,pcent,target -B1 -x tmpfs -x udev -x devtmpfs | tail -n+2');        
        
        if (strpos ($resu , 'df --help')){ //This can happen in some OS like redhat or centos because no support of --output. We try to use standard POSIX option
            $resu = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pass,'exec df -P -B1 -x tmpfs -x udev -x devtmpfs | tail -n+2');
        }

        $explines = preg_split('/[\r\n]+/', $resu);
        foreach($explines as $line){
            $line = preg_replace("/[[:blank:]]+/",' ',$line);
            $part = explode(' ',$line);
            //S.ficheros         Bloques de 1    Usado    Dispon  Ocupado Montado en
            if (isset($part[1])){ 
                $unidades[] = array ($part[5],$part[1],$part[3]);//Drive, Space, FreeSpace
            }  
        }

    }
    //showdeb($unidades);

    foreach ($unidades as $disk){ //Array disks and space, put in database, and see if I want to alert (Low space)
        if ($disk[1] > 0){ //Only save if disk is a real one
            dbw_query($db_conn,"INSERT INTO S_HDDSTAT (ID_SERV,`Timestamp`,`HDD`,`Space`,`Freespace`) VALUES ('$pc[ID_SERV]','$time','$disk[0]','$disk[1]','$disk[2]')");

            if (percalertfor('HDD')){ //Only set if alert percent is configured.
                if  (percent($disk[2],$disk[1]) < percalertfor('HDD')){ //HDD Lower than alert position
                    gestionAlerta($pc,'HDD',"$disk[0]",0); //1 -> OK, 0 -> Not OK
                }else{
                    gestionAlerta($pc,'HDD',"$disk[0]",1); //1 -> OK, 0 -> Not OK
                }
            }
        }

    }

}


function cron_uptime($db_conn,$time,$pc){
    //Get Uptime
    if ($pc['SO'] == "WINDOWS"){
        $resu = shell_exec('wmic -U \''.$pc['User'].'%'.$pc['Password'].'\' //'.$pc['IP'].' "select lastBootupTime from Win32_OperatingSystem" | grep "\." | cut -d"." -f1');
        $datetime = date_create_from_format ('YmdHis', (int)$resu );
        $timestamp = date_timestamp_get ($datetime);
        $uptime = time() - $timestamp;
    }else if ($pc['SO'] == "BSD"){
        $line = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'uptime');
        $line = trim($line);
        $line = preg_replace("/[[:blank:]]+/",' ',$line);
        $part = explode(' ',$line);
        //Example: 6:07PM  up 2 days, 20:30, 1 user, load averages: 0.20, 0.16, 0.15.
        $exphour = explode(':',$part[4]);
        $uptime = $line[2]*86400 + $exphour[0]*3600 + $exphour[1] * 60;

    }else{  //Linux is standard reading /proc/uptime
        $uptime = explode('.',commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'cat /proc/uptime'))[0];
		if (DEBUG)
			echo $uptime;
    }

    dbw_query($db_conn,"UPDATE SERVERS SET Uptime='$uptime' WHERE ID_SERV='$pc[ID_SERV]'");
}

function cron_getversion($db_conn,$pc){
    if ($pc['SO'] == "WINDOWS"){
        $resu = shell_exec('wmic -U \''.$pc['User'].'%'.$pc['Password'].'\' //'.$pc['IP'].' "select Caption from Win32_OperatingSystem"');
        
        $explines = preg_split('/[\r\n]+/', $resu);
        $part = explode('|',$explines[2]);
        $version = $part[0];
    }else{  //Systemd and init goes same way
        $part = explode('"',commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'cat /etc/os-release | grep PRETTY_NAME'));
        if (isset($part[1])){
            $version = $part[1];
        }else{
            $version = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'cat /etc/redhat-release');
        }
        
    }

    dbw_query($db_conn,"UPDATE SERVERS SET `Version`='$version' WHERE ID_SERV='$pc[ID_SERV]'");
}


function try_login($pc){
    if ($pc['SO'] == "WINDOWS"){

        exec ('wmic -U \''.$pc['User'].'%'.$pc['Password'].'\' //'.$pc['IP'].' "select Caption from Win32_OperatingSystem" 2>&1', $resu, $return_var );

        foreach ($resu as $line){
            if (strpos($line, '0x80041045') !== FALSE){ //Error de WMI bloqueado
                return 2;
            }
        }
        if ($return_var != 0){
            return NULL;
        }else{
            return 1;
        }
    }else{  //Systemd and init goes same way
        $part = commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'echo "TRY"');
        if ($part == NULL){
            return NULL;
        }else{
            return 1;
        } 
    }
}


function detect_linux($pc,$forcedetect = NULL){
    if ($pc['SO'] == 'LINUX' ||$forcedetect){


        //Search for systemd
        $lines = explode(PHP_EOL,commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'systemctl --version &>/dev/null;echo $?'));
        $lines = removeEmptyLines($lines);
        $lastline = $lines[count($lines)-1];
        if (! ($lastline > 0)){
            dbw_query(dbconn(),"UPDATE SERVERS SET SO='LINUX_SYSTEMD' WHERE ID_SERV='$pc[ID_SERV]'");
            return;
        }
       

        //Search for "service"
        $lines = explode(PHP_EOL,commandbyssh($pc['IP'],$pc['SSHPort'],$pc['User'],$pc['Password'],'service --status-all &>/dev/null;echo $?'));
        $lines = removeEmptyLines($lines);
        $lastline = $lines[count($lines)-1];
        if (! ($lastline > 0)){
            dbw_query(dbconn(),"UPDATE SERVERS SET SO='LINUX_SERVICE' WHERE ID_SERV='$pc[ID_SERV]'");
            return;
        }

    }

}
?>