"Fossies" - the Fresh Open Source Software Archive

Member "fogproject-1.5.9/packages/web/lib/fog/fogbase.class.php" (13 Sep 2020, 70601 Bytes) of package /linux/misc/fogproject-1.5.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "fogbase.class.php": 1.5.8_vs_1.5.9.

    1 <?php
    2 /**
    3  * FOGBase, the base class for pretty much all of fog.
    4  *
    5  * PHP version 5
    6  *
    7  * This gives all the rest of the classes a common frame to work from.
    8  *
    9  * @category FOGBase
   10  * @package  FOGProject
   11  * @author   Tom Elliott <tommygunsster@gmail.com>
   12  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   13  * @link     https://fogproject.org
   14  */
   15 /**
   16  * FOGBase, the base class for pretty much all of fog.
   17  *
   18  * @category FOGBase
   19  * @package  FOGProject
   20  * @author   Tom Elliott <tommygunsster@gmail.com>
   21  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   22  * @link     https://fogproject.org
   23  */
   24 abstract class FOGBase
   25 {
   26     /**
   27      * Locale
   28      *
   29      * @var string
   30      */
   31     public static $locale = '';
   32     /**
   33      * Ping is active?
   34      *
   35      * @var bool
   36      */
   37     public static $fogpingactive = false;
   38     /**
   39      * Delete auth is active?
   40      *
   41      * @var bool
   42      */
   43     public static $fogdeleteactive = false;
   44     /**
   45      * Export auth is active?
   46      *
   47      * @var bool
   48      */
   49     public static $fogexportactive = false;
   50     /**
   51      * The pending macs count.
   52      *
   53      * @var int
   54      */
   55     public static $pendingMACs = 0;
   56     /**
   57      * The pending hosts count.
   58      *
   59      * @var int
   60      */
   61     public static $pendingHosts = 0;
   62     /**
   63      * Default screen.
   64      *
   65      * @var string
   66      */
   67     public static $defaultscreen = '';
   68     /**
   69      * Plugins installed.
   70      *
   71      * @var array
   72      */
   73     public static $pluginsinstalled = array();
   74     /**
   75      * User agent string.
   76      *
   77      * @var string
   78      */
   79     public static $useragent;
   80     /**
   81      * Language variables brought in from text.php.
   82      *
   83      * @var array
   84      */
   85     public static $foglang;
   86     /**
   87      * Sets if the requesting call is ajax requested.
   88      *
   89      * @var bool
   90      */
   91     public static $ajax = false;
   92     /**
   93      * Sets if this is a form submit.
   94      *
   95      * @var bool
   96      */
   97     public static $post = false;
   98     /**
   99      * Tells whether or not its a fog/service request.
  100      *
  101      * @var bool
  102      */
  103     public static $service = false;
  104     /**
  105      * Tells if we are json or not
  106      *
  107      * @var bool
  108      */
  109     public static $json = false;
  110     /**
  111      * Tells if we are new service or not
  112      *
  113      * @var bool
  114      */
  115     public static $newService = false;
  116     /**
  117      * Tests/sets if a given key is loaded already.
  118      *
  119      * @var array
  120      */
  121     protected $isLoaded = array();
  122     /**
  123      * The length of a given string item.
  124      *
  125      * @var int
  126      */
  127     protected static $strlen;
  128     /**
  129      * Display debug information.
  130      *
  131      * @var bool
  132      */
  133     protected static $debug = false;
  134     /**
  135      * Display extra information about items.
  136      *
  137      * @var bool
  138      */
  139     protected static $info = false;
  140     /**
  141      * Select box creator function stored in variable.
  142      *
  143      * @var callable
  144      */
  145     protected static $buildSelectBox;
  146     /**
  147      * Sets what's selected for the select box.
  148      *
  149      * @var bool|int
  150      */
  151     protected static $selected;
  152     /**
  153      * The database handler.
  154      *
  155      * @var object
  156      */
  157     protected static $DB;
  158     /**
  159      * FTP Handler.
  160      *
  161      * @var object
  162      */
  163     protected static $FOGFTP;
  164     /**
  165      * Core usage elements as FOGBase is abstract.
  166      *
  167      * @var object
  168      */
  169     protected static $FOGCore;
  170     /**
  171      * Event handling.
  172      *
  173      * @var object
  174      */
  175     protected static $EventManager;
  176     /**
  177      * Hook handling.
  178      *
  179      * @var object
  180      */
  181     protected static $HookManager;
  182     /**
  183      * The default timezone for all of fog to use.
  184      *
  185      * @var object
  186      */
  187     protected static $TimeZone;
  188     /**
  189      * The logged in user.
  190      *
  191      * @var object
  192      */
  193     protected static $FOGUser;
  194     /**
  195      * View/Page Controller-Manager.
  196      *
  197      * @var object
  198      */
  199     protected static $FOGPageManager;
  200     /**
  201      * URL Manager | mainly for ajax, and externel getters.
  202      *
  203      * @var object
  204      */
  205     protected static $FOGURLRequests;
  206     /**
  207      * Side/Sub menu manager.
  208      *
  209      * @var object
  210      */
  211     protected static $FOGSubMenu;
  212     /**
  213      * Current requests script name.
  214      *
  215      * @var string
  216      */
  217     public static $scriptname;
  218     /**
  219      * Current requests query string.
  220      *
  221      * @var string
  222      */
  223     public static $querystring;
  224     /**
  225      * Current requests http requested with string.
  226      *
  227      * @var string
  228      */
  229     public static $httpreqwith;
  230     /**
  231      * Current request method.
  232      *
  233      * @var string
  234      */
  235     public static $reqmethod;
  236     /**
  237      * Current remote address.
  238      *
  239      * @var string
  240      */
  241     public static $remoteaddr;
  242     /**
  243      * Current http referer.
  244      *
  245      * @var string
  246      */
  247     public static $httpreferer;
  248     /**
  249      * The current server's IP information.
  250      *
  251      * @var array
  252      */
  253     protected static $ips = array();
  254     /**
  255      * The current server's Interface information.
  256      *
  257      * @var array
  258      */
  259     protected static $interface = array();
  260     /**
  261      * The current base pages requiring search functionality.
  262      *
  263      * @var array
  264      */
  265     protected static $searchPages = array(
  266         'user',
  267         'host',
  268         'group',
  269         'image',
  270         //'storage',
  271         'snapin',
  272         'printer',
  273         'task',
  274     );
  275     /**
  276      * Is our current element already initialized?
  277      *
  278      * @var bool
  279      */
  280     private static $_initialized = false;
  281     /**
  282      * The current running schema information.
  283      *
  284      * @var int
  285      */
  286     public static $mySchema = 0;
  287     /**
  288      * Allows pages to include the main gui or not.
  289      *
  290      * @var bool
  291      */
  292     public static $showhtml = true;
  293     /**
  294      * HTTPS set or not store protocol to use.
  295      *
  296      * @var string
  297      */
  298     public static $httpproto = false;
  299     /**
  300      * HTTP_HOST variable.
  301      *
  302      * @var string
  303      */
  304     public static $httphost = '';
  305     /**
  306      * Hosts are what we work with.
  307      * To help simplify changing elements using hosts,
  308      * store as a static variable.
  309      *
  310      * @var Host
  311      */
  312     public static $Host = null;
  313     /**
  314      * Initializes the FOG System if needed.
  315      *
  316      * @return void
  317      */
  318     private static function _init()
  319     {
  320         if (self::$_initialized === true) {
  321             return;
  322         }
  323         global $foglang;
  324         global $FOGFTP;
  325         global $FOGCore;
  326         global $DB;
  327         global $currentUser;
  328         global $EventManager;
  329         global $HookManager;
  330         global $FOGURLRequests;
  331         global $FOGPageManager;
  332         global $TimeZone;
  333         self::$foglang = &$foglang;
  334         self::$FOGFTP = &$FOGFTP;
  335         self::$FOGCore = &$FOGCore;
  336         self::$DB = &$DB;
  337         self::$EventManager = &$EventManager;
  338         self::$HookManager = &$HookManager;
  339         self::$FOGUser = &$currentUser;
  340         global $sub;
  341         $scriptPattern = 'service';
  342         $queryPattern = 'sub=requestClientInfo';
  343         self::$querystring = filter_input(INPUT_SERVER, 'QUERY_STRING');
  344         self::$scriptname = filter_input(INPUT_SERVER, 'SCRIPT_NAME');
  345         self::$httpreqwith = filter_input(INPUT_SERVER, 'HTTP_X_REQUESTED_WITH');
  346         self::$reqmethod = filter_input(INPUT_SERVER, 'REQUEST_METHOD');
  347         self::$remoteaddr = filter_input(INPUT_SERVER, 'REMOTE_ADDR');
  348         self::$httpreferer = filter_input(INPUT_SERVER, 'HTTP_REFERER');
  349         if (false !== stripos(self::$scriptname, $scriptPattern)) {
  350             self::$service = true;
  351         } elseif (false !== stripos(self::$querystring, $queryPattern)) {
  352             self::$service = true;
  353         }
  354         self::$ajax = false !== stripos(self::$httpreqwith, 'xmlhttprequest');
  355         self::$post = false !== stripos(self::$reqmethod, 'post');
  356         self::$newService = isset($_POST['newService'])
  357             || isset($_GET['newService'])
  358             || $sub == 'requestClientInfo';
  359         self::$json = isset($_POST['json'])
  360             || isset($_GET['json'])
  361             || self::$newService
  362             || $sub == 'requestClientInfo';
  363         self::$FOGURLRequests = &$FOGURLRequests;
  364         self::$FOGPageManager = &$FOGPageManager;
  365         self::$TimeZone = &$TimeZone;
  366         /*
  367          * Lambda function to allow building of select boxes.
  368          *
  369          * @param string $option the option to iterate
  370          * @param bool|int $index the index to operate on if needed.
  371          *
  372          * @return void
  373          */
  374         self::$buildSelectBox = function ($option, $index = false) {
  375             $value = $option;
  376             if ($index) {
  377                 $value = $index;
  378             }
  379             printf(
  380                 '<option value="%s"%s>%s</option>',
  381                 $value,
  382                 (self::$selected == $value ? ' selected' : ''),
  383                 $option
  384             );
  385         };
  386         /**
  387          * Set proto and host.
  388          */
  389         self::$httpproto = 'http'
  390             . (
  391                 filter_input(INPUT_SERVER, 'HTTPS') ?
  392                 's' :
  393                 ''
  394             );
  395         self::$httphost = filter_input(INPUT_SERVER, 'HTTP_HOST');
  396         self::$_initialized = true;
  397     }
  398     /**
  399      * Initiates the base class for FOG.
  400      *
  401      * @return this
  402      */
  403     public function __construct()
  404     {
  405         self::$useragent = self::_getUserAgent();
  406         self::_init();
  407 
  408         return $this;
  409     }
  410     /**
  411      * Return the user agent.
  412      *
  413      * @return string
  414      */
  415     private static function _getUserAgent()
  416     {
  417         return filter_input(INPUT_SERVER, 'HTTP_USER_AGENT');
  418     }
  419     /**
  420      * Defines string as class name.
  421      *
  422      * @return string
  423      */
  424     public function __toString()
  425     {
  426         return get_class($this);
  427     }
  428     /**
  429      * Returns the class after verifying reflection of the class.
  430      *
  431      * @param string $class the name of the class to load
  432      * @param mixed  $data  the data to load into the class
  433      * @param bool   $props return just properties or full object
  434      *
  435      * @throws Exception
  436      *
  437      * @return class Returns the instantiated class
  438      */
  439     public static function getClass($class, $data = '', $props = false)
  440     {
  441         if (!is_string($class)) {
  442             throw new Exception(_('Class name must be a string'));
  443         }
  444         // Get all args, even unnamed args.
  445         $args = func_get_args();
  446         array_shift($args);
  447 
  448         // Trim the class var
  449         $class = trim($class);
  450 
  451         // Test what the class is and return if it is Reflection.
  452         $lClass = strtolower($class);
  453         if ($lClass === 'reflectionclass') {
  454             return new ReflectionClass(count($args) === 1 ? $args[0] : $args);
  455         }
  456 
  457         global $sub;
  458         // If class is Storage, test if sub is group or node.
  459         if ($class === 'Storage') {
  460             $class = 'StorageNode';
  461             if (preg_match('#storage[-|_]group#i', $sub)) {
  462                 $class = 'StorageGroup';
  463             }
  464         }
  465 
  466         // Initiate Reflection item.
  467         $obj = new ReflectionClass($class);
  468 
  469         // If props is set to true return the properties of the class.
  470         if ($props === true) {
  471             return $obj->getDefaultProperties();
  472         }
  473 
  474         // Return the main object
  475         if ($obj->getConstructor()) {
  476             // If there's only one argument return the instance using it.
  477             // Otherwise return with full call.
  478             if (count($args) === 1) {
  479                 $class = $obj->newInstance($args[0]);
  480             } else {
  481                 $class = $obj->newInstanceArgs($args);
  482             }
  483         } else {
  484             $class = $obj->newInstanceWithoutConstructor();
  485         }
  486 
  487         return $class;
  488     }
  489     /**
  490      * Get's the relevant host item.
  491      *
  492      * @param bool $service         Is this a service request
  493      * @param bool $encoded         Is this data encoded
  494      * @param bool $hostnotrequired Is the host return needed
  495      * @param bool $returnmacs      Only return macs?
  496      * @param bool $override        Perform an override of the items?
  497      * @param bool $mac             Mac Override?
  498      *
  499      * @throws Exception
  500      *
  501      * @return array|object Returns either th macs or the host
  502      */
  503     public static function getHostItem(
  504         $service = true,
  505         $encoded = false,
  506         $hostnotrequired = false,
  507         $returnmacs = false,
  508         $override = false,
  509         $mac = false
  510     ) {
  511         self::$Host = new Host(0);
  512         // Store the mac
  513         if (!$mac) {
  514             $mac = filter_input(INPUT_POST, 'mac');
  515             if (!$mac) {
  516                 $mac = filter_input(INPUT_GET, 'mac');
  517             }
  518             if (!$mac) {
  519                 parse_str(
  520                     file_get_contents('php://input'),
  521                     $vars
  522                 );
  523                 $mac = $vars['mac'];
  524             }
  525         }
  526         // disabling sysuuid detection code for now as it is causing
  527         // trouble with machines having the same UUID like we've seen
  528         // on some MSI motherboards having FFFFFFFF-FFFF-FFFF-FFFF...
  529         /*        $sysuuid = filter_input(INPUT_POST, 'sysuuid');
  530                 if (!$sysuuid) {
  531                     $sysuuid = filter_input(INPUT_GET, 'sysuuid');
  532                 }
  533          */
  534         // If encoded decode and store value
  535         if ($encoded === true) {
  536             $mac = base64_decode($mac);
  537             //            $sysuuid = base64_decode($sysuuid);
  538         }
  539         // See if we can find the host by system uuid rather than by mac's first.
  540         /*        if ($sysuuid) {
  541                     $Inventory = self::getClass('Inventory')
  542                         ->set('sysuuid', $sysuuid)
  543                         ->load('sysuuid');
  544                     $Host = self::getClass('Inventory')
  545                         ->set('sysuuid', $sysuuid)
  546                         ->load('sysuuid')
  547                         ->getHost();
  548                     if ($Host->isValid() && !$returnmacs) {
  549                         self::$Host = $Host;
  550                         return;
  551                     }
  552                 }
  553          */
  554         // Trim the mac list.
  555         $mac = trim($mac);
  556         // Parsing the macs
  557         $MACs = self::parseMacList(
  558             $mac,
  559             !$service,
  560             $service
  561         );
  562         $macs = array();
  563         foreach ((array) $MACs as &$mac) {
  564             if (!$mac->isValid()) {
  565                 continue;
  566             }
  567             $macs[] = $mac->__toString();
  568             unset($mac);
  569         }
  570         // Get the host element based on the mac address
  571         self::getClass('HostManager')->getHostByMacAddresses($macs);
  572         // If no macs are returned and the host is not required,
  573         // throw message that it's an invalid mac.
  574         if (count($macs) < 1 && $hostnotrequired === false) {
  575             if ($service) {
  576                 $msg = '#!im';
  577             } else {
  578                 $msg = sprintf(
  579                     '%s %s',
  580                     self::$foglang['InvalidMAC'],
  581                     $mac
  582                 );
  583             }
  584             throw new Exception($msg);
  585         }
  586 
  587         // If returnmacs parameter is true, return the macs as an array
  588         if ($returnmacs) {
  589             if (!is_array($macs)) {
  590                 $macs = (array) $macs;
  591             }
  592 
  593             return $macs;
  594         }
  595 
  596         if ($hostnotrequired === false && $override === false) {
  597             if (self::$Host->get('pending')) {
  598                 self::$Host = new Host(0);
  599             }
  600             if (!self::$Host->isValid()) {
  601                 if ($service) {
  602                     $msg = '#!ih';
  603                 } else {
  604                     $msg = _('Invalid Host');
  605                 }
  606                 throw new Exception($msg);
  607             }
  608         }
  609         return;
  610     }
  611     /**
  612      * Get's blamed nodes for failures.
  613      *
  614      * @param Host $Host The host to work with.
  615      *
  616      * @return array
  617      */
  618     public static function getAllBlamedNodes($Host)
  619     {
  620         $DateInterval = self::niceDate()->modify('-5 minutes');
  621         /**
  622          * Returns the node id if still accurate
  623          * or will clean up past time nodes.
  624          *
  625          * @param object $NodeFailure the node that is in failed state
  626          *
  627          * @return int|bool
  628          */
  629         $nodeFail = function ($NodeFailure) use ($DateInterval) {
  630             if ($NodeFailure->isValid()) {
  631                 return false;
  632             }
  633             $DateTime = self::niceDate($NodeFailure->get('failureTime'));
  634             if ($DateTime < $DateInterval) {
  635                 $NodeFailure->destroy();
  636 
  637                 return false;
  638             }
  639 
  640             return $NodeFailure->get('id');
  641         };
  642         $find = array(
  643             'taskID' => self::$Host->get('task')->get('id'),
  644             'hostID' => self::$Host->get('id'),
  645         );
  646         $nodeRet = array_map(
  647             $nodeFail,
  648             (array)self::getClass('NodeFailureManager')->find($find)
  649         );
  650         $nodeRet = array_filter($nodeRet);
  651         $nodeRet = array_unique($nodeRet);
  652         $nodeRet = array_values($nodeRet);
  653 
  654         return $nodeRet;
  655     }
  656     /**
  657      * Returns array of plugins installed.
  658      *
  659      * @return array
  660      */
  661     protected static function getActivePlugins()
  662     {
  663         $plugins = self::getSubObjectIDs(
  664             'Plugin',
  665             array(
  666                 'installed' => 1,
  667                 'state' => 1,
  668             ),
  669             'name'
  670         );
  671 
  672         return array_map('strtolower', (array) $plugins);
  673     }
  674     /**
  675      * Converts our string if needed.
  676      *
  677      * @param string $txt  the string to use
  678      * @param array  $data the data if txt is formatted string
  679      *
  680      * @return string
  681      */
  682     private static function _setString($txt, $data = array())
  683     {
  684         if (count($data)) {
  685             $data = vsprintf($txt, $data);
  686         } else {
  687             $data = $txt;
  688         }
  689 
  690         return $data;
  691     }
  692     /**
  693      * Prints fatal errors.
  694      *
  695      * @param string $txt  the string to use
  696      * @param array  $data the data if txt is formatted string
  697      *
  698      * @return void
  699      */
  700     protected static function fatalError($txt, $data = array())
  701     {
  702         if (self::$service || self::$ajax) {
  703             return;
  704         }
  705         $data = self::_setString($txt, $data);
  706         $string = sprintf(
  707             'FOG FATAL ERROR: %s: %s',
  708             get_class($this),
  709             $data
  710         );
  711         printf('<div class="debug debug-error">%s</div>', $string);
  712     }
  713     /**
  714      * Prints error.
  715      *
  716      * @param string $txt  the string to use
  717      * @param array  $data the data if txt is formatted string
  718      *
  719      * @return void
  720      */
  721     protected static function error($txt, $data = array())
  722     {
  723         if ((self::$service || self::$ajax) || !self::$debug) {
  724             return;
  725         }
  726         $data = self::_setString($txt, $data);
  727         $string = sprintf(
  728             'FOG ERROR: %s: %s',
  729             get_class($this),
  730             $data
  731         );
  732         printf('<div class="debug debug-error">%s</div>', $string);
  733     }
  734     /**
  735      * Prints debug.
  736      *
  737      * @param string $txt  the string to use
  738      * @param array  $data the data if txt is formatted string
  739      *
  740      * @return void
  741      */
  742     protected static function debug($txt, $data = array())
  743     {
  744         if ((self::$service || self::$ajax) || !self::$debug) {
  745             return;
  746         }
  747         $data = self::_setString($txt, $data);
  748         $string = sprintf(
  749             'FOG DEBUG: %s: %s',
  750             get_class($this),
  751             $data
  752         );
  753         printf('<div class="debug debug-error">%s</div>', $string);
  754     }
  755     /**
  756      * Prints info.
  757      *
  758      * @param string $txt  the string to use
  759      * @param array  $data the data if txt is formatted string
  760      *
  761      * @return void
  762      */
  763     protected static function info($txt, $data = array())
  764     {
  765         if (!self::$info || self::$service || self::$ajax) {
  766             return;
  767         }
  768         $data = self::_setString($txt, $data);
  769         $string = sprintf(
  770             'FOG INFO: %s: %s',
  771             get_class($this),
  772             $data
  773         );
  774         printf('<div class="debug debug-info">%s</div>', $string);
  775     }
  776     /**
  777      * Sets message banner at top of pages.
  778      *
  779      * @param string $txt  the string to use
  780      * @param array  $data the data if txt is formatted string
  781      *
  782      * @return void
  783      */
  784     protected static function setMessage($txt, $data = array())
  785     {
  786         if (session_status() != PHP_SESSION_NONE) {
  787             $_SESSION['FOG_MESSAGES'] = self::_setString($txt, $data);
  788         }
  789     }
  790     /**
  791      * Gets message banner and prepares to display it.
  792      *
  793      * @return string
  794      */
  795     protected static function getMessages()
  796     {
  797         if (session_status() == PHP_SESSION_NONE) {
  798             return;
  799         }
  800         if (!isset($_SESSION['FOG_MESSAGES'])) {
  801             $_SESSION['FOG_MESSAGES'] = array();
  802         }
  803         $messages = (array) $_SESSION['FOG_MESSAGES'];
  804         unset($_SESSION['FOG_MESSAGES']);
  805         // Create a hook in for messages
  806         if (self::$HookManager instanceof HookManager) {
  807             self::$HookManager->processEvent(
  808                 'MessageBox',
  809                 array('data' => &$messages)
  810             );
  811         }
  812         /**
  813          * Lambda that simply prints the messages as passed.
  814          *
  815          * @param string $message the message to print
  816          */
  817         $print_messages = function ($message) {
  818             printf('<div class="fog-message-box">%s</div>', $message);
  819         };
  820         // Print the messages
  821         array_map($print_messages, $messages);
  822         unset($messages);
  823     }
  824     /**
  825      * Redirect pages where/when necessary.
  826      *
  827      * @param string $url The url to redirect to
  828      *
  829      * @return void
  830      */
  831     protected static function redirect($url = '')
  832     {
  833         if (self::$service) {
  834             return;
  835         }
  836         header('Strict-Transport-Security: "max-age=15768000"');
  837         header('X-Content-Type-Options: nosniff');
  838         header('X-XSS-Protection: 1; mode=block');
  839         header('X-Robots-Tag: none');
  840         header('X-Frame-Options: SAMEORIGIN');
  841         header("Location: $url");
  842         exit;
  843     }
  844     /**
  845      * Insert before key in array.
  846      *
  847      * @param string $key       the key to insert before
  848      * @param array  $array     the array to modify
  849      * @param string $new_key   the new key to insert
  850      * @param mixed  $new_value the value to insert
  851      *
  852      * @throws Exception
  853      * @return void
  854      */
  855     protected static function arrayInsertBefore(
  856         $key,
  857         array &$array,
  858         $new_key,
  859         $new_value
  860     ) {
  861         if (!is_string($key)) {
  862             throw new Exception(_('Key must be a string or index'));
  863         }
  864         $new = array();
  865         foreach ($array as $k => &$value) {
  866             if ($k === $key) {
  867                 $new[$new_key] = $new_value;
  868             }
  869             $new[$k] = $value;
  870             unset($k, $value);
  871         }
  872         $array = $new;
  873     }
  874     /**
  875      * Insert after key in array.
  876      *
  877      * @param string $key       the key to insert after
  878      * @param array  $array     the array to modify
  879      * @param string $new_key   the new key to insert
  880      * @param mixed  $new_value the value to insert
  881      *
  882      * @throws Exception
  883      * @return void
  884      */
  885     protected static function arrayInsertAfter(
  886         $key,
  887         array &$array,
  888         $new_key,
  889         $new_value
  890     ) {
  891         if (!is_string($key) && !is_numeric($key)) {
  892             throw new Exception(_('Key must be a string or index'));
  893         }
  894         $new = array();
  895         foreach ($array as $k => &$value) {
  896             $new[$k] = $value;
  897             if ($k === $key) {
  898                 $new[$new_key] = $new_value;
  899             }
  900             unset($k, $value);
  901         }
  902         $array = $new;
  903     }
  904     /**
  905      * Remove value based on the key from array.
  906      *
  907      * @param string|array $key   the key to remove
  908      * @param array        $array the array to work with
  909      *
  910      * @throws Exception
  911      * @return void
  912      */
  913     protected static function arrayRemove($key, array &$array)
  914     {
  915         if (!(is_string($key) || is_array($key))) {
  916             throw new Exception(_('Key must be an array of keys or a string.'));
  917         }
  918         if (is_array($key)) {
  919             foreach ($key as &$k) {
  920                 self::arrayRemove($k, $array);
  921                 unset($k);
  922             }
  923         } else {
  924             foreach ($array as &$value) {
  925                 if (is_array($value)) {
  926                     self::arrayRemove($key, $value);
  927                 } else {
  928                     unset($array[$key]);
  929                 }
  930                 unset($value);
  931             }
  932         }
  933     }
  934     /**
  935      * Find the key of a needle within the haystack that is an array.
  936      *
  937      * @param mixed      $needle     the needle to find
  938      * @param array      $haystack   the array to search in
  939      * @param bool|mixed $ignorecase whether to care about case
  940      *
  941      * @return key or false
  942      */
  943     protected static function arrayFind(
  944         $needle,
  945         array $haystack,
  946         $ignorecase = false
  947     ) {
  948         $key = array_search($needle, $haystack);
  949         if (false !== $key) {
  950             return $key;
  951         }
  952         $cmd = $ignorecase !== false ? 'stripos' : 'strpos';
  953         foreach ($haystack as $key => &$value) {
  954             if (false !== $cmd($value, $needle)) {
  955                 return $key;
  956             }
  957             unset($value);
  958         }
  959 
  960         return -1;
  961     }
  962     /**
  963      * Check if isLoaded.
  964      *
  965      * @param string|int $key the key to see if loaded
  966      *
  967      * @return bool|string
  968      */
  969     protected function isLoaded($key)
  970     {
  971         $key = $this->key($key);
  972         $result = isset($this->isLoaded[$key]) ? $this->isLoaded[$key] : 0;
  973         $this->isLoaded[$key] = true;
  974         ++$this->isLoaded[$key];
  975 
  976         return $result ? $result : false;
  977     }
  978     /**
  979      * Reset request variables.
  980      *
  981      * @return void
  982      */
  983     protected static function resetRequest()
  984     {
  985         if (session_status() == PHP_SESSION_NONE) {
  986             return;
  987         }
  988         if (!isset($_SESSION['post_request_vals'])) {
  989             $_SESSION['post_request_vals'] = array();
  990         }
  991         $sesVars = $_SESSION['post_request_vals'];
  992         $setReq = function (&$val, &$key) {
  993             $_POST[$key] = $val;
  994             unset($val, $key);
  995         };
  996         if (count($sesVars) > 0) {
  997             array_walk($sesVars, $setReq);
  998         }
  999         unset($_SESSION['post_request_vals'], $sesVars, $reqVars);
 1000     }
 1001     /**
 1002      * Set request vars particularly for post failures really.
 1003      *
 1004      * @return void
 1005      */
 1006     protected function setRequest()
 1007     {
 1008         if (session_status() == PHP_SESSION_NONE) {
 1009             return;
 1010         }
 1011         if (!isset($_SESSION['post_request_vals'])) {
 1012             $_SESSION['post_request_vals'] = array();
 1013         }
 1014         if (!$_SESSION['post_request_vals'] && self::$post) {
 1015             $_SESSION['post_request_vals'] = $_POST;
 1016         }
 1017     }
 1018     /**
 1019      * Return nicely formatted byte sizes.
 1020      *
 1021      * @param int|float $size the size to convert
 1022      *
 1023      * @return float
 1024      */
 1025     protected static function formatByteSize($size)
 1026     {
 1027         $units = array('iB', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB');
 1028         $factor = floor((strlen($size) - 1) / 3);
 1029 
 1030         return sprintf('%3.2f %s', $size / pow(1024, $factor), $units[$factor]);
 1031     }
 1032     /**
 1033      * Gets the global module status.
 1034      *
 1035      * Can return just the shortnames or the long.
 1036      *
 1037      * @param bool $names if set will return the services as set
 1038      * @param bool $keys  will return just the shortnames if set
 1039      *
 1040      * @return array
 1041      */
 1042     protected static function getGlobalModuleStatus($names = false, $keys = false)
 1043     {
 1044         // The shortnames are on the left, the long names are on the right
 1045         // If the right is true it means the short is accurate.
 1046         // If the left is not the right caller in form of:
 1047         //     FOG_CLIENT_<name>_ENABLED in lowercase.
 1048         $services = array(
 1049             'autologout' => 'autologoff',
 1050             'clientupdater' => true,
 1051             'dircleanup' => 'directorycleaner',
 1052             'displaymanager' => true,
 1053             'greenfog' => true,
 1054             'hostnamechanger' => true,
 1055             'hostregister' => true,
 1056             'powermanagement' => true,
 1057             'printermanager' => true,
 1058             'snapinclient' => 'snapin',
 1059             'taskreboot' => true,
 1060             'usercleanup' => true,
 1061             'usertracker' => true,
 1062         );
 1063         // If keys is set, return just the keys.
 1064         if ($keys) {
 1065             $keys = array_keys($services);
 1066             $keys = array_filter($keys);
 1067             $keys = array_unique($keys);
 1068 
 1069             return array_values($keys);
 1070         }
 1071         // Change the keys values
 1072         foreach ($services as $short => &$value) {
 1073             $tmp = $value === true ? $short : $value;
 1074             $value = sprintf('FOG_CLIENT_%s_ENABLED', strtoupper($tmp));
 1075             unset($value);
 1076         }
 1077         // If names is set, send back the short and long names together.
 1078         if ($names) {
 1079             return $services;
 1080         }
 1081         // Now lets get their status'
 1082         $serviceEn = self::getSubObjectIDs(
 1083             'Service',
 1084             array(
 1085                 'name' => array_values($services),
 1086             ),
 1087             'value',
 1088             false,
 1089             'AND',
 1090             'name',
 1091             false,
 1092             false
 1093         );
 1094 
 1095         return array_combine(array_keys($services), $serviceEn);
 1096     }
 1097     /**
 1098      * Sets the date.
 1099      *
 1100      * @param mixed $date The date stamp, defaults to now if not set
 1101      * @param bool  $utc  Whether to use utc timezone or not
 1102      *
 1103      * @return DateTime
 1104      */
 1105     public static function niceDate($date = 'now', $utc = false)
 1106     {
 1107         if ($utc || empty(self::$TimeZone)) {
 1108             $tz = new DateTimeZone('UTC');
 1109         } else {
 1110             $tz = new DateTimeZone(self::$TimeZone);
 1111         }
 1112 
 1113         return new DateTime($date, $tz);
 1114     }
 1115     /**
 1116      * Do formatting things.
 1117      *
 1118      * @param mixed $time   The time to work from
 1119      * @param mixed $format Specified format to return
 1120      * @param bool  $utc    Use UTC Timezone?
 1121      *
 1122      * @return mixed
 1123      */
 1124     public static function formatTime($time, $format = false, $utc = false)
 1125     {
 1126         if (!$time instanceof DateTime) {
 1127             $time = self::niceDate($time, $utc);
 1128         }
 1129         if ($format) {
 1130             if (!self::validDate($time)) {
 1131                 return _('No Data');
 1132             }
 1133 
 1134             return $time->format($format);
 1135         }
 1136         $now = self::niceDate('now', $utc);
 1137         // Get difference of the current to supplied.
 1138         $diff = $now->format('U') - $time->format('U');
 1139         $absolute = abs($diff);
 1140         if (is_nan($diff)) {
 1141             return _('Not a number');
 1142         }
 1143         if (!self::validDate($time)) {
 1144             return _('No Data');
 1145         }
 1146         $date = $time->format('Y/m/d');
 1147         if ($now->format('Y/m/d') == $date) {
 1148             if (0 <= $diff && $absolute < 60) {
 1149                 return 'Moments ago';
 1150             } elseif ($diff < 0 && $absolute < 60) {
 1151                 return 'Seconds from now';
 1152             } elseif ($absolute < 3600) {
 1153                 return self::humanify($diff / 60, 'minute');
 1154             } else {
 1155                 return self::humanify($diff / 3600, 'hour');
 1156             }
 1157         }
 1158         $dayAgo = clone $now;
 1159         $dayAgo->modify('-1 day');
 1160         $dayAhead = clone $now;
 1161         $dayAhead->modify('+1 day');
 1162         if ($dayAgo->format('Y/m/d') == $date) {
 1163             return 'Ran Yesterday at '.$time->format('H:i');
 1164         } elseif ($dayAhead->format('Y/m/d') == $date) {
 1165             return 'Runs today at '.$time->format('H:i');
 1166         } elseif ($absolute / 86400 <= 7) {
 1167             return self::humanify($diff / 86400, 'day');
 1168         } elseif ($absolute / 604800 <= 5) {
 1169             return self::humanify($diff / 604800, 'week');
 1170         } elseif ($absolute / 2628000 < 12) {
 1171             return self::humanify($diff / 2628000, 'month');
 1172         }
 1173 
 1174         return self::humanify($diff / 31536000, 'year');
 1175     }
 1176     /**
 1177      * Checks if the time passed is valid or not.
 1178      *
 1179      * @param mixed $date   the date to use
 1180      * @param mixed $format the format to test
 1181      *
 1182      * @return object
 1183      */
 1184     protected static function validDate($date, $format = '')
 1185     {
 1186         if ($format == 'N') {
 1187             if ($date instanceof DateTime) {
 1188                 return $date->format('N') >= 0;
 1189             } else {
 1190                 return $date >= 0 && $date <= 7;
 1191             }
 1192         }
 1193         if (!$date instanceof DateTime) {
 1194             $date = self::niceDate($date);
 1195         }
 1196         if (!$format) {
 1197             $format = 'm/d/Y';
 1198         }
 1199         if (empty(self::$TimeZone)) {
 1200             $tz = new DateTimeZone('UTC');
 1201         } else {
 1202             $tz = new DateTimeZone(self::$TimeZone);
 1203         }
 1204 
 1205         return DateTime::createFromFormat(
 1206             $format,
 1207             $date->format($format),
 1208             $tz
 1209         );
 1210     }
 1211     /**
 1212      * Simply returns if the item should be with an s or not.
 1213      *
 1214      * @param int    $count The count of the element
 1215      * @param string $text  The string to append to
 1216      * @param bool   $space Use a space or not
 1217      *
 1218      * @throws Exception
 1219      *
 1220      * @return string
 1221      */
 1222     protected static function pluralize($count, $text, $space = false)
 1223     {
 1224         if (!is_bool($space)) {
 1225             throw new Exception(_('Space variable must be boolean'));
 1226         }
 1227 
 1228         return sprintf(
 1229             '%d %s%s%s',
 1230             $count,
 1231             $text,
 1232             $count != 1 ? 's' : '',
 1233             $space === true ? ' ' : ''
 1234         );
 1235     }
 1236     /**
 1237      * Returns the difference given from a start and end time.
 1238      *
 1239      * @param mixed $start the starting date
 1240      * @param mixed $end   the ending date
 1241      * @param bool  $ago   Return immediate highest down
 1242      *
 1243      * @throws Exception
 1244      *
 1245      * @return DateTime
 1246      */
 1247     protected static function diff($start, $end, $ago = false)
 1248     {
 1249         if (!is_bool($ago)) {
 1250             throw new Exception(_('Ago must be boolean'));
 1251         }
 1252         if (!$start instanceof DateTime) {
 1253             $start = self::niceDate($start);
 1254         }
 1255         if (!$end instanceof DateTime) {
 1256             $end = self::niceDate($end);
 1257         }
 1258         $Duration = $start->diff($end);
 1259         $str = '';
 1260         $suffix = '';
 1261         if ($ago === true) {
 1262             $str = '%s %s';
 1263             if ($Duration->invert) {
 1264                 $suffix = 'ago';
 1265             }
 1266             if (($v = $Duration->y) > 0) {
 1267                 return sprintf(
 1268                     $str,
 1269                     self::pluralize($v, 'year'),
 1270                     $suffix
 1271                 );
 1272             }
 1273             if (($v = $Duration->m) > 0) {
 1274                 return sprintf(
 1275                     $str,
 1276                     self::pluralize($v, 'month'),
 1277                     $suffix
 1278                 );
 1279             }
 1280             if (($v = $Duration->d) > 0) {
 1281                 return sprintf(
 1282                     $str,
 1283                     self::pluralize($v, 'day'),
 1284                     $suffix
 1285                 );
 1286             }
 1287             if (($v = $Duration->h) > 0) {
 1288                 return sprintf(
 1289                     $str,
 1290                     self::pluralize($v, 'hour'),
 1291                     $suffix
 1292                 );
 1293             }
 1294             if (($v = $Duration->i) > 0) {
 1295                 return sprintf(
 1296                     $str,
 1297                     self::pluralize($v, 'minute'),
 1298                     $suffix
 1299                 );
 1300             }
 1301             if (($v = $Duration->s) > 0) {
 1302                 return sprintf(
 1303                     $str,
 1304                     self::pluralize($v, 'second'),
 1305                     $suffix
 1306                 );
 1307             }
 1308         }
 1309         if (($v = $Duration->y) > 0) {
 1310             $str .= self::pluralize($v, 'year', true);
 1311         }
 1312         if (($v = $Duration->m) > 0) {
 1313             $str .= self::pluralize($v, 'month', true);
 1314         }
 1315         if (($v = $Duration->d) > 0) {
 1316             $str .= self::pluralize($v, 'day', true);
 1317         }
 1318         if (($v = $Duration->h) > 0) {
 1319             $str .= self::pluralize($v, 'hour', true);
 1320         }
 1321         if (($v = $Duration->i) > 0) {
 1322             $str .= self::pluralize($v, 'minute', true);
 1323         }
 1324         if (($v = $Duration->s) > 0) {
 1325             $str .= self::pluralize($v, 'second');
 1326         }
 1327 
 1328         return $str;
 1329     }
 1330     /**
 1331      * Return more human friendly time.
 1332      *
 1333      * @param int    $diff the difference passed
 1334      * @param string $unit the unit of time (minute, hour, etc...)
 1335      *
 1336      * @throws Exception
 1337      *
 1338      * @return string
 1339      */
 1340     protected static function humanify($diff, $unit)
 1341     {
 1342         if (!is_numeric($diff)) {
 1343             throw new Exception(_('Diff parameter must be numeric'));
 1344         }
 1345         if (!is_string($unit)) {
 1346             throw new Exception(_('Unit of time must be a string'));
 1347         }
 1348         $before = $after = '';
 1349         if ($diff < 0) {
 1350             $before = sprintf('%s ', _('In'));
 1351         }
 1352         if ($diff < 0) {
 1353             $after = sprintf(' %s', _('ago'));
 1354         }
 1355         $diff = floor(abs($diff));
 1356         if ($diff != 1) {
 1357             $unit .= 's';
 1358         }
 1359 
 1360         return sprintf(
 1361             '%s%d %s%s',
 1362             $before,
 1363             $diff,
 1364             $unit,
 1365             $after
 1366         );
 1367     }
 1368     /**
 1369      * Changes the keys around as needed.
 1370      *
 1371      * @param array  $array   the array to change key for
 1372      * @param string $old_key the original key
 1373      * @param string $new_key the key to change to
 1374      *
 1375      * @throws Exception
 1376      * @return void
 1377      */
 1378     protected static function arrayChangeKey(array &$array, $old_key, $new_key)
 1379     {
 1380         if (!is_string($old_key)) {
 1381             throw new Exception(_('Old key must be a string'));
 1382         }
 1383         if (!is_string($new_key)) {
 1384             throw new Exception(_('New key must be a string'));
 1385         }
 1386         $array[$old_key] = (
 1387             is_string($array[$old_key]) ?
 1388             trim($array[$old_key]) :
 1389             $array[$old_key]
 1390         );
 1391         if (!self::$service && is_string($array[$old_key])) {
 1392             $item = mb_convert_encoding(
 1393                 $array[$old_key],
 1394                 'utf-8'
 1395             );
 1396             $array[$new_key] = Initiator::sanitizeItems(
 1397                 $item
 1398             );
 1399         } else {
 1400             $array[$new_key] = $array[$old_key];
 1401         }
 1402         if ($old_key != $new_key) {
 1403             unset($array[$old_key]);
 1404         }
 1405     }
 1406     /**
 1407      * Converts to bits.
 1408      *
 1409      * @param int|float $kilobytes the bytes to convert
 1410      *
 1411      * @return float
 1412      */
 1413     protected static function byteconvert($kilobytes)
 1414     {
 1415         return ($kilobytes / 8) * 1024;
 1416     }
 1417     /**
 1418      * Converts hex to binary equivalent.
 1419      *
 1420      * @param mixed $hex The hex to convert.
 1421      *
 1422      * @return string
 1423      */
 1424     protected static function hex2bin($hex)
 1425     {
 1426         if (function_exists('hex2bin')) {
 1427             return hex2bin($hex);
 1428         }
 1429         $n = strlen($hex);
 1430         $i = 0;
 1431         $sbin = '';
 1432         while ($i < $n) {
 1433             $a = substr($hex, $i, 2);
 1434             $sbin .= pack('H*', $a);
 1435             $i += 2;
 1436         }
 1437 
 1438         return $sbin;
 1439     }
 1440     /**
 1441      * Create security token.
 1442      *
 1443      * @return string
 1444      */
 1445     public static function createSecToken()
 1446     {
 1447         if (function_exists('random_bytes')) {
 1448             $token = bin2hex(
 1449                 random_bytes(64)
 1450             );
 1451         } elseif (function_exists('openssl_random_pseudo_bytes')) {
 1452             $token = bin2hex(
 1453                 openssl_random_pseudo_bytes(
 1454                     64
 1455                 )
 1456             );
 1457         }
 1458         return $token;
 1459     }
 1460     /**
 1461      * AES Encrypt function.
 1462      *
 1463      * @param mixed  $data    the item to encrypt
 1464      * @param string $key     the key to use if false will generate own
 1465      * @param int    $enctype the type of encryption to use
 1466      *
 1467      * @return string
 1468      */
 1469     public static function aesencrypt(
 1470         $data,
 1471         $key = false,
 1472         $enctype = 'aes-256-cbc'
 1473     ) {
 1474         if (!$data) {
 1475             echo json_encode(
 1476                 array(
 1477                     'error' => _('Data is blank')
 1478                 )
 1479             );
 1480             exit;
 1481         }
 1482         $iv_size = openssl_cipher_iv_length($enctype);
 1483         $key = self::hex2bin($key);
 1484         if (mb_strlen($key, '8bit') !== ($iv_size * 2)) {
 1485             echo json_encode(
 1486                 array(
 1487                     'error' => _('Needs a 256-bit key')
 1488                 )
 1489             );
 1490             exit;
 1491         }
 1492         $iv = openssl_random_pseudo_bytes($iv_size, $cstrong);
 1493 
 1494         // Pad the plaintext
 1495         if (strlen($data) % $iv_size) {
 1496             $data = str_pad(
 1497                 $data,
 1498                 ((strlen($data) + $iv_size) - (strlen($data) % $iv_size)),
 1499                 "\0"
 1500             );
 1501         }
 1502 
 1503         $cipher = openssl_encrypt(
 1504             $data,
 1505             $enctype,
 1506             $key,
 1507             OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
 1508             $iv
 1509         );
 1510         if (!$cipher) {
 1511             echo json_encode(
 1512                 array(
 1513                     'error' => openssl_error_string()
 1514                 )
 1515             );
 1516             exit;
 1517         }
 1518         $iv = bin2hex($iv);
 1519         $cipher = bin2hex($cipher);
 1520         return sprintf(
 1521             '%s|%s',
 1522             $iv,
 1523             $cipher
 1524         );
 1525     }
 1526     /**
 1527      * AES Decrypt function.
 1528      *
 1529      * @param mixed  $encdata the item to decrypt
 1530      * @param string $key     the key to use
 1531      * @param int    $enctype the type of encryption to use
 1532      * @param int    $mode    the mode of encryption
 1533      *
 1534      * @return string
 1535      */
 1536     public static function aesdecrypt(
 1537         $encdata,
 1538         $key = false,
 1539         $enctype = 'aes-128-cbc'
 1540     ) {
 1541         $iv_size = openssl_cipher_iv_length($enctype) * 2;
 1542         if (false === strpos($encdata, '|')) {
 1543             return $encdata;
 1544         }
 1545         $data = explode('|', $encdata);
 1546         if (strlen($data[0]) != $iv_size || strlen($data[1]) != $iv_size) {
 1547             return $encdata;
 1548         }
 1549         // add error handler to catch warnings we might get from pack() with non-hex strings
 1550         set_error_handler(
 1551             function ($severity, $message, $file, $line) {
 1552                 throw new ErrorException($message, $severity, $severity, $file, $line);
 1553             }
 1554         );
 1555         try {
 1556             $iv = pack('H*', $data[0]);
 1557             $encoded = pack('H*', $data[1]);
 1558             if (!$key && isset($data[2]) && strlen($data[2]) == $iv_size) {
 1559                 $key = pack('H*', $data[2]);
 1560             }
 1561         } catch (Exception $e) {
 1562             return $encdata;
 1563         }
 1564         restore_error_handler();
 1565         if (empty($key)) {
 1566             return '';
 1567         }
 1568         $decipher = openssl_decrypt(
 1569             $encoded,
 1570             $enctype,
 1571             $key,
 1572             OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
 1573             $iv
 1574         );
 1575         if (!$decipher) {
 1576             echo json_encode(
 1577                 array(
 1578                     'error' => openssl_error_string()
 1579                 )
 1580             );
 1581             exit;
 1582         }
 1583 
 1584         return trim($decipher);
 1585     }
 1586     /**
 1587      * Encrypts the data using the host information.
 1588      * Really just an alias to aesencrypt for now.
 1589      *
 1590      * @param mixed $data the data to encrypt
 1591      *
 1592      * @throws Exception
 1593      *
 1594      * @return string
 1595      */
 1596     protected static function certEncrypt($data)
 1597     {
 1598         if (!self::$Host->isValid()) {
 1599             throw new Exception('#!ih');
 1600         }
 1601         if (!self::$Host->get('pub_key')) {
 1602             throw new Exception('#!ihc');
 1603         }
 1604         return self::aesencrypt($data, self::$Host->get('pub_key'));
 1605     }
 1606     /**
 1607      * Decrypts the information passed.
 1608      *
 1609      * @param mixed $dataArr the data to decrypt
 1610      * @param bool  $padding to use padding or not
 1611      *
 1612      * @throws Exception
 1613      *
 1614      * @return mixed
 1615      */
 1616     protected static function certDecrypt($dataArr, $padding = true)
 1617     {
 1618         if ($padding) {
 1619             $padding = OPENSSL_PKCS1_PADDING;
 1620         } else {
 1621             $padding = OPENSSL_NO_PADDING;
 1622         }
 1623         $tmpssl = array();
 1624         $sslfile = self::getSubObjectIDs('StorageNode', '', 'sslpath');
 1625         foreach ($sslfile as &$path) {
 1626             if (!file_exists($path) || !is_readable($path)) {
 1627                 continue;
 1628             }
 1629             $tmpssl[] = $path;
 1630             unset($path);
 1631         }
 1632         if (count($tmpssl) < 1) {
 1633             throw new Exception(_('Private key path not found'));
 1634         }
 1635         $sslfile = sprintf(
 1636             '%s%s.srvprivate.key',
 1637             str_replace(
 1638                 array('\\', '/'),
 1639                 array(
 1640                     DS,
 1641                     DS
 1642                 ),
 1643                 $tmpssl[0]
 1644             ),
 1645             DS
 1646         );
 1647         unset($tmpssl);
 1648         if (!file_exists($sslfile)) {
 1649             throw new Exception(_('Private key not found'));
 1650         }
 1651         if (!is_readable($sslfile)) {
 1652             throw new Exception(_('Private key not readable'));
 1653         }
 1654         $sslfilecontents = file_get_contents($sslfile);
 1655         $priv_key = openssl_pkey_get_private($sslfilecontents);
 1656         if (!$priv_key) {
 1657             throw new Exception(_('Private key failed'));
 1658         }
 1659         $a_key = openssl_pkey_get_details($priv_key);
 1660         $chunkSize = ceil($a_key['bits'] / 8);
 1661         $output = array();
 1662         foreach ((array) $dataArr as &$data) {
 1663             $dataun = '';
 1664             while ($data) {
 1665                 $data = self::hex2bin($data);
 1666                 $chunk = substr($data, 0, $chunkSize);
 1667                 $data = substr($data, $chunkSize);
 1668                 $decrypt = '';
 1669                 $test = openssl_private_decrypt(
 1670                     $chunk,
 1671                     $decrypt,
 1672                     $priv_key,
 1673                     $padding
 1674                 );
 1675                 if (!$test) {
 1676                     throw new Exception(_('Failed to decrypt data on server'));
 1677                 }
 1678                 $dataun .= $decrypt;
 1679             }
 1680             unset($data);
 1681             $output[] = $dataun;
 1682         }
 1683         openssl_free_key($priv_key);
 1684 
 1685         return (array) $output;
 1686     }
 1687     /**
 1688      * Cycle the macs and return valid.
 1689      *
 1690      * @param string|array $stringlist the macs to parse
 1691      * @param bool         $image      check if image type ignored
 1692      * @param bool         $client     check if client type ignored
 1693      *
 1694      * @return array
 1695      */
 1696     public static function parseMacList(
 1697         $stringlist,
 1698         $image = false,
 1699         $client = false
 1700     ) {
 1701         $MAClist = array();
 1702         $MACs = $stringlist;
 1703         $lowerAndTrim = function ($element) {
 1704             return strtolower(trim($element));
 1705         };
 1706         if (!is_array($stringlist)) {
 1707             $MACs = array_map($lowerAndTrim, explode('|', $stringlist));
 1708         } else {
 1709             $MACs = array_map($lowerAndTrim, $stringlist);
 1710         }
 1711         $MACs = array_filter($MACs);
 1712         $MACs = array_unique($MACs);
 1713         $MACs = array_values($MACs);
 1714         if (count($MACs) < 1) {
 1715             return array();
 1716         }
 1717         $pending_filter = explode(
 1718             ',',
 1719             self::getSetting('FOG_QUICKREG_PENDING_MAC_FILTER')
 1720         );
 1721         $Ignore = array_map($lowerAndTrim, $pending_filter);
 1722         $Ignore = array_filter($Ignore);
 1723         if (count($Ignore) > 0) {
 1724             $pattern = sprintf(
 1725                 '#%s#i',
 1726                 implode('|', (array) $Ignore)
 1727             );
 1728             $found_macs = preg_grep($pattern, $MACs);
 1729             $MACs = array_diff($MACs, $found_macs);
 1730             $MACs = array_filter($MACs);
 1731             $MACs = array_unique($MACs);
 1732             $MACs = array_values($MACs);
 1733         }
 1734         if (count($MACs) < 1) {
 1735             return array();
 1736         }
 1737         $count = self::getClass('MACAddressAssociationManager')->count(
 1738             array(
 1739                 'mac' => $MACs,
 1740                 'pending' => array(0, ''),
 1741             )
 1742         );
 1743         if ($count > 0) {
 1744             $existingMACs = self::getSubObjectIDs(
 1745                 'MACAddressAssociation',
 1746                 array(
 1747                     'mac' => $MACs,
 1748                     'pending' => array(0, ''),
 1749                 ),
 1750                 'mac'
 1751             );
 1752             $existingMACs = array_map($lowerAndTrim, $existingMACs);
 1753             $existingMACs = array_filter($existingMACs);
 1754             $existingMACs = array_unique($existingMACs);
 1755             $existingMACs = array_values($existingMACs);
 1756             $MACs = self::fastmerge((array) $MACs, (array) $existingMACs);
 1757             $MACs = array_unique($MACs);
 1758         }
 1759         if ($client) {
 1760             $clientIgnored = self::getSubObjectIDs(
 1761                 'MACAddressAssociation',
 1762                 array(
 1763                     'mac' => $MACs,
 1764                     'clientIgnore' => 1,
 1765                 ),
 1766                 'mac'
 1767             );
 1768             $clientIgnored = array_map($lowerAndTrim, $clientIgnored);
 1769             $MACs = array_diff((array) $MACs, (array) $clientIgnored);
 1770             unset($clientIgnored);
 1771         }
 1772         if ($image) {
 1773             $imageIgnored = self::getSubObjectIDs(
 1774                 'MACAddressAssociation',
 1775                 array(
 1776                     'mac' => $MACs,
 1777                     'imageIgnore' => 1,
 1778                 ),
 1779                 'mac'
 1780             );
 1781             $imageIgnored = array_map($lowerAndTrim, (array) $imageIgnored);
 1782             $MACs = array_diff((array) $MACs, (array) $imageIgnored);
 1783             unset($imageIgnored);
 1784         }
 1785         $MACs = array_filter($MACs);
 1786         $MACs = array_unique($MACs);
 1787         $MACs = array_values($MACs);
 1788         if (count($MACs) < 1) {
 1789             return array();
 1790         }
 1791         $validMACs = array();
 1792         foreach ($MACs as &$MAC) {
 1793             $MAC = self::getClass('MACAddress', $MAC);
 1794             if (!$MAC->isValid()) {
 1795                 continue;
 1796             }
 1797             $validMACs[] = $MAC;
 1798             unset($MAC);
 1799         }
 1800         $validMACs = array_filter($validMACs);
 1801 
 1802         return $validMACs;
 1803     }
 1804     /**
 1805      * Prints the data encrypted as needed.
 1806      *
 1807      * @param string $datatosend the data to send
 1808      * @param bool   $service    if not a service simpy return
 1809      * @param array  $array      The non-encoded array data.
 1810      *
 1811      * @return string
 1812      */
 1813     protected function sendData(
 1814         $datatosend,
 1815         $service = true,
 1816         $array = array()
 1817     ) {
 1818         global $sub;
 1819         if (false === $service) {
 1820             return;
 1821         }
 1822         try {
 1823             if (!self::$Host->isValid()) {
 1824                 throw new Exception('#!ih');
 1825             }
 1826             $datatosend = trim($datatosend);
 1827             $curdate = self::niceDate();
 1828             $secdate = self::niceDate(self::$Host->get('sec_time'));
 1829             if ($curdate >= $secdate) {
 1830                 self::$Host
 1831                     ->set('pub_key', '')
 1832                     ->save()
 1833                     ->load();
 1834                 if (self::$newService || self::$json) {
 1835                     throw new Exception('#!ihc');
 1836                 }
 1837             }
 1838             if (self::$newService) {
 1839                 printf(
 1840                     '#!enkey=%s',
 1841                     self::certEncrypt($datatosend)
 1842                 );
 1843                 exit;
 1844             } else {
 1845                 echo $datatosend;
 1846                 exit;
 1847             }
 1848         } catch (Exception $e) {
 1849             if (self::$json) {
 1850                 if ($e->getMessage() === '#!ihc') {
 1851                     echo $e->getMessage();
 1852                     exit;
 1853                 }
 1854                 $repData = str_replace('#!', '', $e->getMessage());
 1855                 $array['error'] = $repData;
 1856                 $data = array('error' => $repData);
 1857                 if ($sub === 'requestClientInfo') {
 1858                     echo json_encode($array);
 1859                     exit;
 1860                 } else {
 1861                     return $data;
 1862                 }
 1863             }
 1864             throw new Exception($e->getMessage());
 1865         }
 1866     }
 1867     /**
 1868      * Checks if an array of needles is found in the main array.
 1869      *
 1870      * @param array $haystack the array to search
 1871      * @param array $needles  the items to test for
 1872      * @param bool  $case     whether to be case insensitive
 1873      *
 1874      * @return bool
 1875      */
 1876     protected static function arrayStrpos($haystack, $needles, $case = true)
 1877     {
 1878         $cmd = sprintf('str%spos', ($case ? 'i' : ''));
 1879         $mapinfo = array();
 1880         foreach ((array) $needles as &$needle) {
 1881             $mapinfo[] = $cmd($haystack, $needle);
 1882             unset($needle);
 1883         }
 1884         $mapinfo = array_filter($mapinfo);
 1885 
 1886         return count($mapinfo) > 0;
 1887     }
 1888     /**
 1889      * How to log this file.
 1890      *
 1891      * @param string $txt     The text to log.
 1892      * @param int    $curlog  The logLevel setting.
 1893      * @param int    $logfile The logToFile setting.
 1894      * @param int    $logbrow The logToBrowser setting.
 1895      * @param object $obj     The object.
 1896      * @param int    $level   The basic log level.
 1897      *
 1898      * @return void
 1899      */
 1900     protected static function log(
 1901         $txt,
 1902         $curlog,
 1903         $logfile,
 1904         $logbrow,
 1905         $obj,
 1906         $level = 1
 1907     ) {
 1908         if (!is_string($txt)) {
 1909             throw new Exception(_('Txt must be a string'));
 1910         }
 1911         if (!is_int($level)) {
 1912             throw new Exception(_('Level must be an integer'));
 1913         }
 1914         if (self::$ajax) {
 1915             return;
 1916         }
 1917         $findStr = array("\r", "\n", "\t", ' ,');
 1918         $repStr = array('', ' ', ' ', ',');
 1919         $txt = str_replace($findStr, $repStr, $txt);
 1920         $txt = trim($txt);
 1921         if (empty($txt)) {
 1922             return;
 1923         }
 1924         $txt = sprintf('[%s] %s', self::niceDate()->format('Y-m-d H:i:s'), $txt);
 1925         if ($curlog >= $level) {
 1926             echo $txt;
 1927         }
 1928         self::logHistory($txt);
 1929     }
 1930     /**
 1931      * Log to history table.
 1932      *
 1933      * @param string $string the string to store
 1934      *
 1935      * @return void
 1936      */
 1937     protected static function logHistory($string)
 1938     {
 1939         if (!is_string($string)) {
 1940             throw new Exception(_('String must be a string'));
 1941         }
 1942         $string = sprintf(
 1943             '[%s] %s',
 1944             self::niceDate()->format('Y-m-d H:i:s'),
 1945             $string
 1946         );
 1947         $string = trim($string);
 1948         if (!$string) {
 1949             return;
 1950         }
 1951         $name = (
 1952             self::$FOGUser->isValid() ?
 1953             self::$FOGUser->get('name') :
 1954             'fog'
 1955         );
 1956         if (!self::$FOGUser->isValid()) {
 1957             return;
 1958         }
 1959         if (self::$DB) {
 1960             self::getClass('History')
 1961                 ->set('info', $string)
 1962                 ->set('ip', self::$remoteaddr)
 1963                 ->save();
 1964         }
 1965     }
 1966     /**
 1967      * Sets the order by element of sql.
 1968      *
 1969      * @param string $orderBy the string to order by
 1970      *
 1971      * @return void
 1972      */
 1973     public function orderBy(&$orderBy)
 1974     {
 1975         if (empty($orderBy)) {
 1976             $orderBy = 'name';
 1977             if (!array_key_exists($orderBy, $this->databaseFields)) {
 1978                 $orderBy = 'id';
 1979             }
 1980         } else {
 1981             if (!is_array($orderBy)) {
 1982                 $orderBy = trim($orderBy);
 1983                 if (!array_key_exists($orderBy, $this->databaseFields)) {
 1984                     $orderBy = 'name';
 1985                 }
 1986                 if (!array_key_exists($orderBy, $this->databaseFields)) {
 1987                     $orderBy = 'id';
 1988                 }
 1989             }
 1990         }
 1991     }
 1992     /**
 1993      * Gets the object ids only.
 1994      *
 1995      * @param string $object    The object to use
 1996      * @param array  $findWhere How to find the elements we need
 1997      * @param string $getField  The field value to return
 1998      * @param mixed  $not       DB to search with not or no not
 1999      * @param string $operator  How to join strings (And or Or)
 2000      * @param mixed  $orderBy   Order the return by
 2001      * @param mixed  $groupBy   Group the return by
 2002      * @param string $filter    How to filter the data returning
 2003      *
 2004      * @return array
 2005      */
 2006     public static function getSubObjectIDs(
 2007         $object = 'Host',
 2008         $findWhere = array(),
 2009         $getField = 'id',
 2010         $not = false,
 2011         $operator = 'AND',
 2012         $orderBy = 'name',
 2013         $groupBy = false,
 2014         $filter = 'array_unique'
 2015     ) {
 2016         if (empty($object)) {
 2017             $object = 'Host';
 2018         }
 2019         if (empty($getField)) {
 2020             $getField = 'id';
 2021         }
 2022         if (empty($operator)) {
 2023             $operator = 'AND';
 2024         }
 2025         if (is_array($getField)) {
 2026             foreach ((array)$getField as &$field) {
 2027                 $data[$field] = self::getSubObjectIDs(
 2028                     $object,
 2029                     $findWhere,
 2030                     $field,
 2031                     $not,
 2032                     $operator,
 2033                     $orderBy,
 2034                     $groupBy,
 2035                     $filter
 2036                 );
 2037                 unset($field);
 2038             }
 2039             return $data;
 2040         }
 2041         return self::getClass($object)->getManager()->find(
 2042             $findWhere,
 2043             $operator,
 2044             $orderBy,
 2045             '',
 2046             '',
 2047             $groupBy,
 2048             $not,
 2049             $getField,
 2050             '',
 2051             $filter
 2052         );
 2053     }
 2054     /**
 2055      * Get global setting value by key.
 2056      *
 2057      * @param string $key What to get
 2058      *
 2059      * @throws Exception
 2060      *
 2061      * @return string
 2062      */
 2063     public static function getSetting($key)
 2064     {
 2065         if (!is_string($key)) {
 2066             throw new Exception(_('Key must be a string'));
 2067         }
 2068         $findStr = '\r\n';
 2069         $repStr = "\n";
 2070         $value = self::getClass('Service')
 2071             ->set('name', $key)
 2072             ->load('name')
 2073             ->get('value');
 2074 
 2075         return trim(
 2076             str_replace(
 2077                 $findStr,
 2078                 $repStr,
 2079                 $value
 2080             )
 2081         );
 2082     }
 2083     /**
 2084      * Set global setting value by key.
 2085      *
 2086      * @param string $key   What to set
 2087      * @param string $value Value to set
 2088      *
 2089      * @throws Exception
 2090      *
 2091      * @return this
 2092      */
 2093     public static function setSetting($key, $value)
 2094     {
 2095         self::getClass('ServiceManager')->update(
 2096             array('name' => $key),
 2097             '',
 2098             array('value' => trim($value))
 2099         );
 2100     }
 2101     /**
 2102      * Gets queued state ids.
 2103      *
 2104      * @return array
 2105      */
 2106     public static function getQueuedStates()
 2107     {
 2108         return (array)TaskState::getQueuedStates();
 2109     }
 2110     /**
 2111      * Get queued state main id.
 2112      *
 2113      * @return int
 2114      */
 2115     public static function getQueuedState()
 2116     {
 2117         return TaskState::getQueuedState();
 2118     }
 2119     /**
 2120      * Get checked in state id.
 2121      *
 2122      * @return int
 2123      */
 2124     public static function getCheckedInState()
 2125     {
 2126         return TaskState::getCheckedInState();
 2127     }
 2128     /**
 2129      * Get in progress state id.
 2130      *
 2131      * @return int
 2132      */
 2133     public static function getProgressState()
 2134     {
 2135         return TaskState::getProgressState();
 2136     }
 2137     /**
 2138      * Get complete state id.
 2139      *
 2140      * @return int
 2141      */
 2142     public static function getCompleteState()
 2143     {
 2144         return TaskState::getCompleteState();
 2145     }
 2146     /**
 2147      * Get cancelled state id.
 2148      *
 2149      * @return int
 2150      */
 2151     public static function getCancelledState()
 2152     {
 2153         return TaskState::getCancelledState();
 2154     }
 2155     /**
 2156      * Put string between two strings.
 2157      *
 2158      * @param string $string the string to insert
 2159      * @param string $start  the string to place after
 2160      * @param string $end    the string to place before
 2161      *
 2162      * @return string
 2163      */
 2164     public static function stringBetween($string, $start, $end)
 2165     {
 2166         $string = " $string";
 2167         $ini = strpos($string, $start);
 2168         if ($ini == 0) {
 2169             return '';
 2170         }
 2171         $ini += strlen($start);
 2172         $len = strpos($string, $end, $ini) - $ini;
 2173 
 2174         return substr($string, $ini, $len);
 2175     }
 2176     /**
 2177      * Strips and decodes items.
 2178      *
 2179      * @param mixed $item the item to strip and decode
 2180      *
 2181      * @return mixed
 2182      */
 2183     public static function stripAndDecode(&$item)
 2184     {
 2185         foreach ((array) $item as $key => &$val) {
 2186             $tmp = str_replace(' ', '+', $val);
 2187             $tmp = base64_decode($tmp);
 2188             $tmp = trim($tmp);
 2189             if (mb_detect_encoding($tmp, 'utf-8', true)) {
 2190                 $val = $tmp;
 2191             }
 2192             unset($tmp);
 2193             $item[$key] = trim($val);
 2194             unset($val);
 2195         }
 2196 
 2197         return $item;
 2198     }
 2199     /**
 2200      * Gets the master interface based on the ip found.
 2201      *
 2202      * @param string $ip_find the interface ip's to find
 2203      *
 2204      * @return string
 2205      */
 2206     public static function getMasterInterface($ip_find)
 2207     {
 2208         if (count(self::$interface) > 0) {
 2209             return self::$interface;
 2210         }
 2211         self::getIPAddress();
 2212         exec(
 2213             "/sbin/ip route | grep '$ip_find' | awk -F'[ /]+' '/kernel.*src/ {print $4}'",
 2214             $Interfaces,
 2215             $retVal
 2216         );
 2217         $ip_find = trim($ip_find);
 2218         if (!$ip_find) {
 2219             return;
 2220         }
 2221         self::$interface = array();
 2222         $index = 0;
 2223         foreach ((array) self::$ips as &$ip) {
 2224             $ip = trim($ip);
 2225             if ($ip_find !== $ip) {
 2226                 continue;
 2227             }
 2228             self::$interface[] = $Interfaces[$index++];
 2229             unset($ip);
 2230         }
 2231         if (count(self::$interface) < 1) {
 2232             return false;
 2233         }
 2234 
 2235         return array_shift(self::$interface);
 2236     }
 2237     /**
 2238      * Get IP Addresses of the server.
 2239      *
 2240      * @return array
 2241      */
 2242     protected static function getIPAddress($force = false)
 2243     {
 2244         if (!$force && count(self::$ips) > 0) {
 2245             return self::$ips;
 2246         }
 2247         $output = array();
 2248         exec(
 2249             "/sbin/ip -4 addr | awk -F'[ /]+' '/global/ {print $3}'",
 2250             $IPs,
 2251             $retVal
 2252         );
 2253         if (!count($IPs)) {
 2254             exec(
 2255                 "/sbin/ifconfig -a | awk -F'[ /:]+' '/(cast)/ {print $4}'",
 2256                 $IPs,
 2257                 $retVal
 2258             );
 2259         }
 2260         natcasesort($IPs);
 2261         $retIPs = function (&$IP) {
 2262             $IP = trim($IP);
 2263             if (!filter_var($IP, FILTER_VALIDATE_IP)) {
 2264                 $IP = gethostbyname($IP);
 2265             }
 2266             if (filter_var($IP, FILTER_VALIDATE_IP)) {
 2267                 return $IP;
 2268             }
 2269         };
 2270         $retNames = function (&$IP) {
 2271             $IP = trim($IP);
 2272             if (filter_var($IP, FILTER_VALIDATE_IP)) {
 2273                 return gethostbyaddr($IP);
 2274             }
 2275 
 2276             return $IP;
 2277         };
 2278         $IPs = array_map($retIPs, (array) $IPs);
 2279         $Names = array_map($retNames, (array) $IPs);
 2280         $output = self::fastmerge(
 2281             $IPs,
 2282             $Names,
 2283             array('127.0.0.1', '127.0.1.1')
 2284         );
 2285         unset($IPs, $Names);
 2286         natcasesort($output);
 2287         self::$ips = array_values(array_filter(array_unique((array) $output)));
 2288 
 2289         return self::$ips;
 2290     }
 2291     /**
 2292      * Returns the last error.
 2293      *
 2294      * @return string
 2295      */
 2296     public static function lasterror()
 2297     {
 2298         $error = error_get_last();
 2299 
 2300         return sprintf(
 2301             '%s: %s, %s: %s, %s: %s, %s: %s',
 2302             _('Type'),
 2303             $error['type'],
 2304             _('File'),
 2305             $error['file'],
 2306             _('Line'),
 2307             $error['line'],
 2308             _('Message'),
 2309             $error['message']
 2310         );
 2311     }
 2312     /**
 2313      * Gets the filesize in a non-arch dependent way.
 2314      *
 2315      * @param string $file the file to get size of
 2316      *
 2317      * @return string|int|float
 2318      */
 2319     public static function getFilesize($path)
 2320     {
 2321         $size = 0;
 2322         if (is_dir($path)) {
 2323             foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $file) {
 2324                 if ($file->getFilename() != ".") {
 2325                     $size += filesize($file);
 2326                 }
 2327             }
 2328         } else {
 2329             $size = filesize($path);
 2330         }
 2331         return is_numeric($size) ? $size : 0;
 2332     }
 2333     /**
 2334      * Perform enmass wake on lan.
 2335      *
 2336      * @param array $macs The macs to send
 2337      *
 2338      * @return void
 2339      */
 2340     public static function wakeUp($macs)
 2341     {
 2342         if (!is_array($macs)) {
 2343             $macs = array($macs);
 2344         }
 2345         session_write_close();
 2346         ignore_user_abort(true);
 2347         set_time_limit(0);
 2348         $macs = self::parseMacList($macs);
 2349         if (count($macs) < 1) {
 2350             return;
 2351         }
 2352         $macStr = implode(
 2353             '|',
 2354             $macs
 2355         );
 2356         $macStr = trim($macStr);
 2357         if (empty($macStr)) {
 2358             return;
 2359         }
 2360         $url = '%s://%s/fog/management/index.php?';
 2361         $url .= 'node=client&sub=wakeEmUp';
 2362         $nodeURLs = array();
 2363         $macCount = count($macs);
 2364         if ($macCount < 1) {
 2365             return;
 2366         }
 2367         foreach ((array)self::getClass('StorageNodeManager')
 2368             ->find(
 2369                 array('isEnabled' => 1)
 2370             ) as &$Node
 2371         ) {
 2372             $ip = $Node->get('ip');
 2373             $nodeURLs[] = sprintf(
 2374                 $url,
 2375                 self::$httpproto,
 2376                 $ip
 2377             );
 2378             unset($Node);
 2379         }
 2380         list(
 2381             $gHost
 2382         ) = self::getSubObjectIDs(
 2383             'Service',
 2384             array(
 2385                 'name' => array(
 2386                     'FOG_WEB_HOST'
 2387                 ),
 2388             ),
 2389             'value',
 2390             false,
 2391             'AND',
 2392             'name',
 2393             false,
 2394             ''
 2395         );
 2396         $ip = $gHost;
 2397         $nodeURLs[] = $ip;
 2398         $ret = self::$FOGURLRequests->process(
 2399             $nodeURLs,
 2400             'POST',
 2401             array('mac' => $macStr),
 2402             false,
 2403             false,
 2404             false,
 2405             false
 2406         );
 2407     }
 2408     /**
 2409      * Faster array merge operation.
 2410      *
 2411      * @param array $array1 The array to merge with.
 2412      *
 2413      * @return array
 2414      */
 2415     public static function fastmerge($array1)
 2416     {
 2417         $others = func_get_args();
 2418         array_shift($others);
 2419         foreach ((array)$others as &$other) {
 2420             foreach ((array)$other as $key => &$oth) {
 2421                 if (is_numeric($key)) {
 2422                     $array1[] = $oth;
 2423                     continue;
 2424                 } elseif (isset($array1[$key])) {
 2425                     $array1[$key] = $oth;
 2426                     continue;
 2427                 }
 2428                 unset($oth);
 2429             }
 2430             $array1 += $other;
 2431             unset($other);
 2432         }
 2433 
 2434         return $array1;
 2435     }
 2436     /**
 2437      * Returns hash of passed file.
 2438      *
 2439      * @param string $file The file to get hash of.
 2440      *
 2441      * @return string
 2442      */
 2443     public static function getHash($file)
 2444     {
 2445         $filesize = self::getFilesize($file);
 2446         $fp = fopen($file, 'r');
 2447         if ($fp) {
 2448             $data = fread($fp, 10485760);
 2449             if ($filesize >= 20971520) {
 2450                 fseek($fp, -10485760, SEEK_END);
 2451                 $data .= fread($fp, 10485760);
 2452             }
 2453             fclose($fp);
 2454         }
 2455         return isset($data) ? hash('sha256', $data) : '';
 2456     }
 2457     /**
 2458      * Attempts to login
 2459      *
 2460      * @param string $username the username to attempt
 2461      * @param string $password the password to attempt
 2462      *
 2463      * @return object
 2464      */
 2465     public static function attemptLogin($username, $password)
 2466     {
 2467         return self::getClass('User')
 2468             ->validatePw($username, $password);
 2469     }
 2470     /**
 2471      * Clears the mac lookup table
 2472      *
 2473      * @return bool
 2474      */
 2475     public static function clearMACLookupTable()
 2476     {
 2477         $OUITable = self::getClass('OUI', '', true);
 2478         $OUITable = $OUITable['databaseTable'];
 2479         return self::$DB->query("TRUNCATE TABLE `$OUITable`");
 2480     }
 2481     /**
 2482      * Returns the count of mac lookups
 2483      *
 2484      * @return int
 2485      */
 2486     public static function getMACLookupCount()
 2487     {
 2488         return self::getClass('OUIManager')->count();
 2489     }
 2490     /**
 2491      * Resolves a hostname to its IP address
 2492      *
 2493      * @param string $host the item to test
 2494      *
 2495      * @return string
 2496      */
 2497     public static function resolveHostname($host)
 2498     {
 2499         $host = trim($host);
 2500         if (filter_var($host, FILTER_VALIDATE_IP)) {
 2501             return $host;
 2502         }
 2503         $host = gethostbyname($host);
 2504         $host = trim($host);
 2505         return $host;
 2506     }
 2507     /**
 2508      * Gets the broadcast address of the server
 2509      *
 2510      * @return array
 2511      */
 2512     public static function getBroadcast()
 2513     {
 2514         $output = array();
 2515         $cmd = sprintf(
 2516             '%s | %s | %s',
 2517             '/sbin/ip -4 addr',
 2518             "awk -F'[ /]+' '/global/ {print $6}'",
 2519             "grep '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'"
 2520         );
 2521         exec($cmd, $IPs, $retVal);
 2522         if (!count($IPs)) {
 2523             $cmd = sprintf(
 2524                 '%s | %s | %s | %s',
 2525                 '/sbin/ifconfig -a',
 2526                 "awk '/(cast)/ {print $3}'",
 2527                 "cut -d':' -f2",
 2528                 "grep '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'"
 2529             );
 2530             exec($cmd, $IPs, $retVal);
 2531         }
 2532         $IPs = array_map('trim', (array)$IPs);
 2533         $IPs = array_filter($IPs);
 2534         $IPs = array_values($IPs);
 2535         return $IPs;
 2536     }
 2537     /**
 2538      * Wait a random interval between 1/2 second to 2 seconds.
 2539      *
 2540      * @return void
 2541      */
 2542     public static function randWait()
 2543     {
 2544         usleep(
 2545             rand(
 2546                 5000,
 2547                 2000000
 2548             )
 2549         );
 2550     }
 2551 }