miksco

cPanel LiveAPI PHP Class

Dec 20th, 2021
6,033
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 28.34 KB | None | 0 0
  1. <?php
  2. /**
  3.  * cpanel - /usr/local/cpanel/php/cpanel.php      Copyright(c) 2020 cPanel, L.L.C.
  4.  *                                                          All rights reserved.
  5.  * [email protected]                                        http://cpanel.net
  6.  */
  7. if (version_compare(PHP_VERSION, '5.2.0', '<')) {
  8.     trigger_error(
  9.         "cPanel's Live PHP class must be executed with PHP >= 5.2",
  10.         E_USER_ERROR
  11.     );
  12.     exit;
  13. }
  14. /** cPanel LiveAPI PHP Class
  15.  *
  16.  * This class allows for cPanel frontend pages to be developed in PHP using an
  17.  * object for accessing the APIs.
  18.  * For the full documentation, see https://go.cpanel.net/livephp.
  19.  *
  20.  * You are free to include this module in your program as long as it is for use
  21.  * with cPanel. This module is only licensed for use with the version of cPanel
  22.  * it is distributed with.
  23.  *
  24.  * The backend APIs are subject to change.  If you ignore this message you will
  25.  * find that this module will not work in future versions.  This class will be
  26.  * updated if the backend APIs change.  We will make all efforts to provide
  27.  * backwards compatibility, but if you do use this class with any version
  28.  * of cPanel other than the one it is distributed with the results could be
  29.  * disasterous.
  30.  *
  31.  * FOR THE AVOIDANCE OF DOUBT: MAKE SURE YOU ONLY USE THIS MODULE WITH THE
  32.  * VERSION OF CPANEL THAT IT CAME WITH
  33.  *
  34.  * For debugging purposes you can set the following two constants to enable
  35.  * debug mode:
  36.  *   - LIVEPHP_DEBUG_LEVEL - 0 or 1 - enable or disable debugging
  37.  *   - LIVEPHP_DEBUG_LOG - path - The absolute path and filename for logging.
  38.  *
  39.  * This class also provides a set_debug() method for enabling/disabling debug
  40.  * mode.
  41.  *
  42.  * Changes:
  43.  *  Version 2.1
  44.  *   - Corrected various documentation
  45.  *   - Altered code and documentation for better adherence to PEAR PHP coding
  46.  *     standards without breaking BC
  47.  *   - Fixed bug (constructor should explicitly return "$this")
  48.  *   - Altered methods cpanelif() and cpanelfeature() to enforce a boolean
  49.  *     return.
  50.  *   - Implemented the use pre-defined SPL Exception classes instead of generic
  51.  *     Exception base class
  52.  *   - Use Exceptions wherever possible instead of simple log via error_log()
  53.  *   - Use trigger_error() instead of error_log()
  54.  *   - Use error_log() only when logging cPanel related information (i.e., what
  55.  *     normally might be E_NOTICE or E_DEPRECATED, but specific only to cPanel
  56.  *     technicians and developers)
  57.  *   - Added 'deprecated' PHP DocBlock to cpanellangprint(). (future versions
  58.  *     will likely throw E_USER_DEPRECATED; instead use
  59.  *     API1's Locale::maketext() (## no extract maketext)
  60.  *
  61.  *  Version 2.0
  62.  *   - Changed the backend serialization format to JSON
  63.  *   - Added debug logger
  64.  *   - Added Exceptions
  65.  *
  66.  * @category  Cpanel
  67.  * @package   CPANEL
  68.  * @author    cPanel, Inc. <[email protected]>
  69.  * @copyright 1997-2020 cPanel, L.L.C.
  70.  * @license   http://cpanel.net
  71.  * @version   Release: 2.1
  72.  * @link      https://go.cpanel.net/livephp
  73.  */
  74. class CPANEL
  75. {
  76.     /**
  77.      * Socket resource for communicating with cPanel LiveAPI parser
  78.      * @var resource Local socket
  79.      */
  80.     private $_cpanelfh;
  81.     /**
  82.      * State tracker for socket resource
  83.      * @var boolean State of private resource
  84.      */
  85.     public $connected = 0;
  86.     /**
  87.      * Absolute path and filename of debug log
  88.      *
  89.      * NOTE: If LIVEPHP_DEBUG_LOG environment variable is not set, this variable
  90.      * will be populated with a random log file (if debugging is enabled):
  91.      * ~/.cpanel/livephp.log.$randomstring.
  92.      *
  93.      * @var string Log file
  94.      */
  95.     private $_debug_log;
  96.     /**
  97.      * File handle for debug log
  98.      * @var resource File handle for debug log
  99.      */
  100.     private $_debug_fh;
  101.     /**
  102.      * Debug logging level
  103.      *
  104.      * Value values are:
  105.      *  0 - Debugging disabled
  106.      *  1 - Log all socket communication to debug log file
  107.      *
  108.      * @var integer Debug logging level
  109.      */
  110.     private $_debug_level = 0;
  111.     /**
  112.      * Storage location for last server response
  113.      * @var array Array data structure of the last server response
  114.      */
  115.     private $_result;
  116.  
  117.     /**
  118.     * Storage location for a stringified DOM as used by the header() and footer() methods
  119.     * note: modern themes only
  120.      */
  121.     private $_dom = 0;
  122.     /**
  123.      * Instantiate the LiveAPI PHP Object
  124.      *
  125.      * This will create the "CPANEL" object; open the communication socket.
  126.      *
  127.      * @return CPANEL A LiveAPI object
  128.      * @throws RuntimeException if CPANEL_PHPCONNECT_SOCKET environment variable
  129.      * is not set
  130.      * @throws RuntimeException if file socket cannot be established
  131.      * @throws RuntimeException if stream blocking cannot be set for file socket
  132.      */
  133.     public function __construct()
  134.     {
  135.         $this->connected = 1;
  136.         // Attempt to set debugging based on defined PHP constants
  137.         if (defined('LIVEPHP_DEBUG_LOG')) {
  138.             $this->_debug_log = LIVEPHP_DEBUG_LOG;
  139.         }
  140.         if (defined('LIVEPHP_DEBUG_LEVEL')) {
  141.             $this->set_debug(LIVEPHP_DEBUG_LEVEL);
  142.         }
  143.         // prepare socket to communicate with cPanel API parser
  144.         $socketfile = getenv('CPANEL_PHPCONNECT_SOCKET');
  145.         if (!$socketfile) {
  146.             throw new RuntimeException(
  147.                 'There was a problem fetching the env variable'
  148.                 . 'containing the path to the socket'
  149.             );
  150.         }
  151.         $this->_cpanelfh = fsockopen("unix://" . $socketfile);
  152.         if (!$this->_cpanelfh) {
  153.             $this->connected = 0;
  154.             throw new RuntimeException(
  155.                 'There was a problem connecting back to the cPanel engine.'
  156.                 .' Make sure your script ends with .live.php or .livephp'
  157.             );
  158.         }
  159.         stream_set_blocking($this->_cpanelfh, 1) || $this->connected = 0;
  160.         if (!$this->connected) {
  161.             throw new RuntimeException(
  162.                 'There was a problem connecting back to the cPanel engine.'
  163.                 .' Make sure your script ends with .live.php or .livephp'
  164.             );
  165.         }
  166.         // enable enbedded json in the protocol
  167.         $this->exec('<cpaneljson enable="1">');
  168.         return $this;
  169.     }
  170.     /**
  171.      * Enable debugging mode
  172.      *
  173.      * Passing this a non-zero value will enable socket logging.
  174.      *
  175.      * NOTE: This should only be used when attempting to debug the transactions
  176.      * that happen over the socket. ALL data will be log!
  177.      *
  178.      * The valid logging level are as follows:
  179.      *   0 - Disable logging (default)
  180.      *   1 - Write socket transactions to the log.
  181.      *
  182.      * @param int $debug_level The debug level
  183.      *
  184.      * @return void
  185.      * @throws UnexpectedValueException if $debug_level is not numeric
  186.      */
  187.     public function set_debug($debug_level)
  188.     {
  189.         if (is_numeric($debug_level)) {
  190.             // Open the debug log if it isn't already
  191.             if ($debug_level > 0 && !is_resource($this->_debug_fh)) {
  192.                 // Set the debug log
  193.                 if (!isset($this->_debug_log)) {
  194.                     $user_pwnam = posix_getpwuid(posix_getuid());
  195.                     $this->_debug_log = $user_pwnam['dir']
  196.                     . '/.cpanel/livephp.log.' . mt_rand(10000000, 99999999);
  197.                 }
  198.                 $this->_debug_fh = fopen($this->_debug_log, 'a');
  199.             } elseif (is_resource($this->_debug_fh) && $debug_level == 0) {
  200.                 // Close debug_log if debug logging is being disabled
  201.                 fclose($this->_debug_fh);
  202.             }
  203.             $this->_debug_level = $debug_level;
  204.         } else {
  205.             $this->set_debug(0);
  206.             throw new UnexpectedValueException(
  207.                 'CPANEL::set_debug given non-integer value.'
  208.             );
  209.         }
  210.     }
  211.     /**
  212.      * Write to the debug log
  213.      *
  214.      * Write a message to the debug log
  215.      *
  216.      * @param int    $level   The desired logging level for $log_msg to appear.
  217.      * @param string $log_msg The message you wish to have logged
  218.      *
  219.      * @return void
  220.      * @throws RuntimeException if log filehandle does not exist
  221.      */
  222.     private function debug_log($level, $log_msg)
  223.     {
  224.         if ($level > 0 && $level <= $this->_debug_level) {
  225.             if (is_resource($this->_debug_fh)) {
  226.                 fwrite($this->_debug_fh, date("[d-M-Y H:i:s] ") . $log_msg . "\n");
  227.             } else {
  228.                 throw new RuntimeException(
  229.                     'Attempted to execute debugging statement on closed filehandle'
  230.                 );
  231.             }
  232.         }
  233.     }
  234.  
  235.     /**
  236.      * Parse and log a JSON formatted string.
  237.      *
  238.      * @param string $str JSON formatted string to decode and log
  239.      *
  240.      * @return void
  241.      */
  242.     private function debug_log_json($str)
  243.     {
  244.         $parsed = json_decode($str, true);
  245.         if ($parsed !== null) {
  246.             ob_start();
  247.             var_dump($parsed);
  248.             $log_msg = ob_get_clean();
  249.         } elseif (function_exists('json_last_error') && json_last_error()) {
  250.             // json_last_error is only PHP>=5.3
  251.             switch (json_last_error()) {
  252.             case JSON_ERROR_DEPTH:
  253.                 $log_msg = 'Maximum stack depth exceeded';
  254.                 break;
  255.             case JSON_ERROR_CTRL_CHAR:
  256.                 $log_msg = 'Unexpected control character found';
  257.                 break;
  258.             case JSON_ERROR_SYNTAX:
  259.                 $log_msg = 'Syntax error, malformed JSON';
  260.                 break;
  261.             case JSON_ERROR_NONE:
  262.                 //do nothing;
  263.                 break;
  264.             }
  265.         } else {
  266.             $log_msg = "Error decoding JSON string";
  267.         }
  268.         $this->debug_log(1, 'JSON_decode: ' . $log_msg);
  269.     }
  270.     /**
  271.      * Get the filename of the debug log currently in use.
  272.      *
  273.      * @return string Current log file
  274.      */
  275.     public function get_debug_log()
  276.     {
  277.         return $this->_debug_log;
  278.     }
  279.     /**
  280.      * Return the currently set debug level.
  281.      *
  282.      * @return int Current debug level
  283.      */
  284.     public function get_debug_level()
  285.     {
  286.         return $this->_debug_level;
  287.     }
  288.     /**
  289.      * Return the value of a cPvar
  290.      *
  291.      * @param string $var The cPvar to fetch (e.g. $CPDATA{'DNS'} )
  292.      *
  293.      * @return array Response containing cPvar value
  294.      */
  295.     public function fetch($var)
  296.     {
  297.         if (!$this->connected) {
  298.             return;
  299.         }
  300.         return $this->exec('<cpanel print="' . $var . '">');
  301.     }
  302.     /**
  303.      * Execute an API1 call
  304.      *
  305.      * @param string $module An API1 module name.
  306.      * @param string $func   An API1 function.
  307.      * @param array  $args   An ordinal array containing arguments for the API1 function
  308.      *
  309.      * @return array Returned response from the API1 function
  310.      * @throws RuntimeException if LiveAPI socket is not available
  311.      */
  312.     public function api1($module, $func, $args = array())
  313.     {
  314.         if (!$this->connected) {
  315.             throw new RuntimeException(
  316.                 'The LiveAPI PHP socket has closed, unable to continue.'
  317.             );
  318.         }
  319.         return $this->api('exec', "1", $module, $func, $args);
  320.     }
  321.     /**
  322.      * Execute an API2 call
  323.      *
  324.      * @param string $module An API2 module name.
  325.      * @param string $func   An API2 function.
  326.      * @param array  $args   An associative array containing arguments for the API2 function
  327.      *
  328.      * @return array Returned response from the API2 function
  329.      * @throws RuntimeException if LiveAPI socket is not available
  330.      */
  331.     public function api2($module, $func, $args = array())
  332.     {
  333.         if (!$this->connected) {
  334.             throw new RuntimeException(
  335.                 'The LiveAPI PHP socket has closed, unable to continue.'
  336.             );
  337.         }
  338.         return $this->api('exec', "2", $module, $func, $args);
  339.     }
  340.      /**
  341.      * Execute an API3 call, an alias for a UAPI call
  342.      *
  343.      * @param string $module A UAPI module name.
  344.      * @param string $func   A UAPI function.
  345.      * @param array  $args   An associative array containing arguments for the UAPIfunction
  346.      *
  347.      * @return array Returned response from the UAPI function
  348.      * @throws RuntimeException if LiveAPI socket is not available
  349.      */
  350.     public function api3($module, $func, $args = array())
  351.     {
  352.         if (!$this->connected) {
  353.             throw new RuntimeException(
  354.                 'The LiveAPI PHP socket has closed, unable to continue.'
  355.             );
  356.         }
  357.         return $this->api('exec', "3", $module, $func, $args);
  358.     }
  359.     /**
  360.      * Execute an UAPI call
  361.      *
  362.      * @param string $module A UAPI module name.
  363.      * @param string $func   A UAPI function.
  364.      * @param array  $args   An associative array containing arguments for the UAPIfunction
  365.      *
  366.      * @return array Returned response from the UAPI function
  367.      * @throws RuntimeException if LiveAPI socket is not available
  368.      */
  369.     public function uapi($module, $func, $args = array())
  370.     {
  371.         if (!$this->connected) {
  372.             throw new RuntimeException(
  373.                 'The LiveAPI PHP socket has closed, unable to continue.'
  374.             );
  375.         }
  376.         return $this->api('exec', "uapi", $module, $func, $args);
  377.     }
  378.     /**
  379.      * Evaluate a cpanelif statement
  380.      *
  381.      * This method will return a boolean value based on the evaluation of the
  382.      * code expression
  383.      *
  384.      * @param string $code A cPvar or logical test condition
  385.      *
  386.      * @link https://go.cpanel.net/PluginVars ExpVar Reference Chart
  387.      * @return boolean Whether the $code expression evaluates as true or false
  388.      * @throws RuntimeException if LiveAPI socket is not available
  389.      */
  390.     public function cpanelif($code)
  391.     {
  392.         if (!$this->connected) {
  393.             throw new RuntimeException(
  394.                 'The LiveAPI PHP socket has closed, unable to continue.'
  395.             );
  396.         }
  397.         $value = (simple_result($this->api('if', '1', 'if', 'if', $code)))? 1 : 0;
  398.         return $value;
  399.     }
  400.     /**
  401.      * Determine if the current cPanel account has access to a specific feature
  402.      *
  403.      * @param string $feature A feature name
  404.      *
  405.      * @return boolean Whether the current cPanel account has access to queried
  406.      * feature.
  407.      * @throws RuntimeException if LiveAPI socket is not available
  408.      */
  409.     public function cpanelfeature($feature)
  410.     {
  411.         if (!$this->connected) {
  412.             throw new RuntimeException(
  413.                 'The LiveAPI PHP socket has closed, unable to continue.'
  414.             );
  415.         }
  416.         $value = (simple_result($this->api('feature', '1', 'feature', 'feature', $feature)))? 1 : 0;
  417.         return $value;
  418.     }
  419.     /**
  420.      * Return the value of a cPvar
  421.      *
  422.      * This method will return the value of a cPvar. This differs from fetch()
  423.      * which returns the complete response as an array.  The method will only
  424.      * return the cPvar value as a string.
  425.      *
  426.      * @param string $var The cPvar to retrieve (e.g. $CPDATA{'DNS'} )
  427.      *
  428.      * @return string The value of the queried cPvar
  429.      * @throws RuntimeException if LiveAPI socket is not available
  430.      */
  431.     public function cpanelprint($var)
  432.     {
  433.         if (!$this->connected) {
  434.             throw new RuntimeException(
  435.                 'The LiveAPI PHP socket has closed, unable to continue.'
  436.             );
  437.         }
  438.         return simple_result($this->api1('print', '', $var));
  439.     }
  440.     /**
  441.      * Process a language key for the cPanel account's current language
  442.      *
  443.      * @param string $key A language key
  444.      *
  445.      * @deprecated The cpanellongprint tag is no longer supported. Use API1
  446.      * Locale::maketext ## no extract maketext
  447.      * @see https://go.cpanel.net/maketext ## no extract maketext
  448.      *
  449.      * @return string Translated version of the requested language key
  450.      * @throws RuntimeException if LiveAPI socket is not available
  451.      */
  452.     public function cpanellangprint($key)
  453.     {
  454.         if (!$this->connected) {
  455.             throw new RuntimeException(
  456.                 'The LiveAPI PHP socket has closed, unable to continue.'
  457.             );
  458.         }
  459.         return simple_result($this->api1('langprint', '', $key));
  460.     }
  461.     /**
  462.      * Execute a cpanel tag
  463.      *
  464.      * In most cases there is no need to call this method directly.  Instead one
  465.      * should use the api1(), api2() or cpanel*() methods (which all call this
  466.      * method internally).
  467.      *
  468.      * @param string  $code        A cPanel tag to execute.
  469.      * @param boolean $skip_return (optional) If set to true, this function will
  470.      * not return anything.
  471.      *
  472.      * @return array Returned response in an array data structure
  473.      * @throws RuntimeException if LiveAPI socket is not available
  474.      */
  475.     public function exec($code, $skip_return = 0)
  476.     {
  477.         if (!$this->connected) {
  478.             throw new RuntimeException(
  479.                 'The LiveAPI PHP socket has closed, unable to continue.'
  480.             );
  481.         }
  482.         // SEND CODE
  483.         $buffer = '';
  484.         $result = '';
  485.         if ($this->_debug_level) {
  486.             $this->debug_log(1, '(exec) SEND:' . $code);
  487.         }
  488.         fwrite($this->_cpanelfh, strlen($code) . "\n" . $code);
  489.         //RECV CODE
  490.         while ($buffer = fgets($this->_cpanelfh)) {
  491.             $result = $result . $buffer;
  492.             if (strstr($buffer, '</cpanelresult>') !== false) {
  493.                 break;
  494.             }
  495.         }
  496.         if ($this->_debug_level) {
  497.             $this->debug_log(1, '(exec) RECV:' . $result);
  498.         }
  499.         if ($skip_return) {
  500.             $this->_result = null;
  501.             return;
  502.         }
  503.         // Parse out return code, build livePHP result
  504.         $json_start_pos = strpos($result, "<cpanelresult>{");
  505.         if ($json_start_pos !== false) {
  506.             $json_start_pos+= 14;
  507.             if ($this->_debug_level) {
  508.                 $this->debug_log_json(
  509.                     substr(
  510.                         trim($result),
  511.                         $json_start_pos,
  512.                         strpos(
  513.                             $result,
  514.                             "</cpanelresult>"
  515.                         ) - $json_start_pos
  516.                     )
  517.                 );
  518.             }
  519.             $parsed = json_decode(
  520.                 substr(
  521.                     trim($result),
  522.                     $json_start_pos,
  523.                     strpos(
  524.                         $result,
  525.                         "</cpanelresult>"
  526.                     ) - $json_start_pos
  527.                 ),
  528.                 true
  529.             );
  530.             if (strpos($result, '<cpanelresult>{"cpanelresult"') === false
  531.                 && $parsed !== null
  532.             ) {
  533.                 /**
  534.                  * needed for compat: API2 tags will end up with both due to
  535.                  * the internals
  536.                  */
  537.                 $this->_result = array('cpanelresult' => $parsed);
  538.             } else {
  539.                 $this->_result = $parsed;
  540.             }
  541.         } elseif (strpos($result, "<cpanelresult></cpanelresult>") !== false) {
  542.             /* This is a hybird api1/api2/api3 response to ensure that
  543.                 the developer using api gets the error field in the position
  544.                 they are looking for */
  545.             $this->_result = array('cpanelresult' => array('error' => 'Error cannot be propagated to liveapi, please check the cPanel error_log.', 'result' => array('errors' => array('Error cannot be propagated to liveapi, please check the cPanel error_log.'))));
  546.         } elseif (strpos($result, "<cpanelresult>") !== false) {
  547.             /**
  548.              * This logic flow is provide for BC in the unlikely event that the
  549.              * cPanel engine doesn't not handle JSON.
  550.              * - log this directly to the PHP error log in hopes that it gets
  551.              *   reported
  552.              */
  553.  
  554.             if ($this->_debug_level) {
  555.                 $this->debug_log(1, 'XML_unserialize:' . $result);
  556.             }
  557.             error_log(
  558.                 'cPanel LiveAPI parser returned XML, which is deprecated. '
  559.                 .'Please file a bug report at https://tickets.cpanel.net/submit/'
  560.             );
  561.             include_once '/usr/local/cpanel/php/xml.php';
  562.             # XML_unserialize takes a reference, and PHP doesn't like it if we
  563.            # pass a non-variable by reference.
  564.            $temp = trim($result);
  565.             $this->_result = XML_unserialize($temp);
  566.         }
  567.         return $this->_result;
  568.     }
  569.     /**
  570.      * Execute an API call
  571.      *
  572.      * In most cases there is no need to call this method directly.  Instead one
  573.      * should use the api1(), api2() or cpanel*() methods (which all call this
  574.      * method, or exec(), internally).
  575.      *
  576.      * @param string $reqtype The type of request used by the cPanel API parser;
  577.      *  valid values are 'exec', 'feature' or 'if'
  578.      * @param int    $version The version of the API; valid values are either
  579.      *  '1' or '2'
  580.      * @param string $module  An API module name
  581.      * @param string $func    An API function name
  582.      * @param mixed  $args    Associate array for API2, ordered array for API1,
  583.      *  string for non exec $reqtypes
  584.      *
  585.      * @see api1()
  586.      * @see api2()
  587.      * @return array Returned response in an array data structure
  588.      * @throws RuntimeException if LiveAPI socket is not available
  589.      */
  590.     public function api($reqtype, $version, $module, $func, $args = array())
  591.     {
  592.         if (!$this->connected) {
  593.             throw new RuntimeException(
  594.                 'The LiveAPI PHP socket has closed, unable to continue.'
  595.             );
  596.         }
  597.         $input = array(
  598.                 "module" => $module,
  599.                 "reqtype" => $reqtype,
  600.                 "func" => $func,
  601.                 "apiversion" => $version
  602.                 );
  603.  
  604.         // Args may actually be a string instead of an array.
  605.         // yay for php 4.x-isms which would automagically turn 'string' into array('string') when accessed as array
  606.         // As such, just check that it isn't empty instead of doing count()
  607.         if (!empty($args)) {
  608.             $input['args'] = $args;
  609.         }
  610.         /**
  611.          *  cPanel engine can process the JSON much much faster than XML
  612.          */
  613.         if (function_exists('json_encode')) {
  614.             $code = "<cpanelaction>\n" . json_encode($input) . "\n</cpanelaction>";
  615.         } else {
  616.             /**
  617.             * This logic flow is provide for BC in the unlikely event that the
  618.             * cPanel engine doesn't not handle JSON.
  619.             * - log this directly to the PHP error log in hopes that it gets
  620.             *   reported
  621.             */
  622.             error_log(
  623.                 'cPanel LiveAPI parser returned XML, which is deprecated. '
  624.                 .'Please file a bug report at https://tickets.cpanel.net/submit/'
  625.             );
  626.             include_once '/usr/local/cpanel/php/xml.php';
  627.             $temp = array("cpanelaction" => array($input));
  628.             $code = XML_serialize($temp);
  629.         }
  630.         return $this->exec($code);
  631.     }
  632.     /**
  633.     * Get the data result node of the last call
  634.     *
  635.     * This method will return the ['cpanelresult']['data']['result'] node from
  636.     * the last call that was made.
  637.     *
  638.     * @return mixed A string if the last call was API1, an array or array of
  639.     * associative arrays if the last call was API2
  640.     * @throws UnexpectedValueException if no data is available from a previous
  641.     * call
  642.     * @throws OutOfBoundsException if previous data response does not contain
  643.     * proper hierarchy
  644.     *
  645.     */
  646.     public function get_result()
  647.     {
  648.         if ( !$this->_result ) {
  649.             throw new UnexpectedValueException('No previous result exists');
  650.         }
  651.         if (!is_array($this->_result)
  652.             || !is_array($this->_result['cpanelresult'])
  653.             || !is_array($this->_result['cpanelresult']['data'])
  654.         ) {
  655.             throw new OutOfBoundsException(
  656.                 'cpanelresult->data associative array key does not exist or '
  657.                 .'previous call did not return array'
  658.             );
  659.         }
  660.         if (array_key_exists('result', $this->_result['cpanelresult']['data'])) {
  661.             return $this->_result['cpanelresult']['data']['result'];
  662.         } else {
  663.             return $this->_result['cpanelresult']['data'];
  664.         }
  665.     }
  666.  
  667.     /**
  668.     * Get the string containing all of the output up until the header
  669.     *
  670.     * This method will return everything up until just past the body-content div
  671.     * this intended as a method of writing a liveAPI application that matches cpanel's
  672.     * presentation.
  673.     *
  674.     * @return string A string containing all output before the body-content div
  675.     * @throws UnexpectedValueException if no header value is detected
  676.     */
  677.     public function header( $title = '', $app_key = '' ) {
  678.         if ( !$this->_dom ) {
  679.             $result = $this->uapi( 'Chrome', 'get_dom', array( 'page_title' => $title, 'app_key' => $app_key ) );
  680.             $this->_dom = $result['cpanelresult']['result']['data'];
  681.         }
  682.         if ( !array_key_exists( 'header', $this->_dom ) ) {
  683.             throw new UnexpectedValueException('No header in DOM response!');
  684.         }
  685.         return $this->_dom['header'];
  686.     }
  687.  
  688.     /**
  689.     * Get the string containing all of the output after the body
  690.     *
  691.     * This method will return everything past the body-content div
  692.     * this intended as a method of writing a liveAPI application that matches cpanel's
  693.     * presentation.
  694.     *
  695.     * @return string A string containing all output after the body-content div
  696.     * @throws UnexpectedValueException if no footer value is detected
  697.     */
  698.     public function footer( $title = '' ) {
  699.         if ( !$this->_dom ) {
  700.             $result = $this->uapi( 'Chrome', 'get_dom', array( 'title' => $title ) );
  701.             $this->_dom = $result['cpanelresult']['result']['data'];
  702.         }
  703.         if ( !array_key_exists( 'footer', $this->_dom ) ) {
  704.             throw new UnexpectedValueException('No footer in DOM response!');
  705.         }
  706.         return $this->_dom['footer'];
  707.     }
  708.  
  709.  
  710.  
  711.     /**
  712.      * Close the connection and destroy the object
  713.      *
  714.      * Calling this method should not be required since all logic actually
  715.      * resides in the class deconstructor. This is provided for BC.
  716.      *
  717.      * @return void
  718.      * @throws RuntimeException if LiveAPI socket is not available
  719.      */
  720.     public function end()
  721.     {
  722.         if (!$this->connected) {
  723.             throw new RuntimeException(
  724.                 'The LiveAPI PHP socket has closed, unable to continue.'
  725.             );
  726.         }
  727.         $this->__destruct();
  728.     }
  729.     /**
  730.      * Deconstructor is responsible for closing communication with the cPanel
  731.      * engine
  732.      *
  733.      * @return void
  734.      * @throws RuntimeException if LiveAPI socket is not available
  735.      */
  736.     public function __destruct()
  737.     {
  738.         if (!$this->connected) {
  739.             throw new RuntimeException(
  740.                 'The LiveAPI PHP socket has closed, unable to continue.'
  741.             );
  742.         }
  743.         if (is_resource($this->_cpanelfh)) {
  744.             $this->exec('<cpanelxml shutdown="1" />', 1);
  745.             while (!feof($this->_cpanelfh)) {
  746.                 fgets($this->_cpanelfh);
  747.             }
  748.             fclose($this->_cpanelfh);
  749.             if ($this->_debug_level) {
  750.                 $this->debug_log(1, 'MAX_MEM: ' . memory_get_peak_usage());
  751.                 if (is_resource($this->_debug_fh)) {
  752.                     fclose($this->_debug_fh);
  753.                 }
  754.             }
  755.         }
  756.     }
  757. }
  758. /**
  759.  * Retrieve the contents of the 'result' node within a return response data
  760.  * structure
  761.  *
  762.  * This function is only valid for responses which have only a single response
  763.  * in their data structure, i.e., special cpanel tags.  In most cases, one
  764.  * should consider using CPANEL::get_result() immediately following an API or
  765.  * cPanel tag query.  This function may be deprecated in future versions of the
  766.  * LiveAPI PHP client code.
  767.  *
  768.  * @param array $result_data Returned response in array format
  769.  *
  770.  * @return string Contents of the "result" node in the provided data structure
  771.  */
  772. function simple_result($result_data)
  773. {
  774.     return $result_data['cpanelresult']['data']['result'];
  775. }
  776. ?>
Advertisement
Add Comment
Please, Sign In to add comment