"Fossies" - the Fresh Open Source Software Archive

Member "fogproject-1.5.9/packages/web/lib/fog/fogurlrequests.class.php" (13 Sep 2020, 17722 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 "fogurlrequests.class.php": 1.5.8_vs_1.5.9.

    1 <?php
    2 /**
    3  * Processes URL requests for our needs.
    4  *
    5  * PHP version 5
    6  *
    7  * @category FOGURLRequests
    8  * @package  FOGProject
    9  * @author   Tom Elliott <tommygunsster@gmail.com>
   10  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   11  * @link     https://fogproject.org
   12  */
   13 /**
   14  * Processes URL requests for our needs.
   15  *
   16  * @category FOGURLRequests
   17  * @package  FOGProject
   18  * @author   Tom Elliott <tommygunsster@gmail.com>
   19  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   20  * @link     https://fogproject.org
   21  */
   22 class FOGURLRequests extends FOGBase
   23 {
   24     /**
   25      * The maximum urls to process at one time.
   26      *
   27      * @var int
   28      */
   29     private $_windowSize = 20;
   30     /**
   31      * The available connection timeout.
   32      *
   33      * Default to 2000 milliseconds.
   34      *
   35      * @var int
   36      */
   37     private $_aconntimeout = 2000;
   38     /**
   39      * The base connection timeout.
   40      *
   41      * Defaults to 15 seconds.
   42      *
   43      * @var int
   44      */
   45     private $_conntimeout = 15;
   46     /**
   47      * The timeout value to process each url.
   48      *
   49      * Defaults to 86400 seconds or 1 day.
   50      *
   51      * @var int
   52      */
   53     private $_timeout = 86400;
   54     /**
   55      * Defines a specific call back request.
   56      *
   57      * TODO: Fixup more appropriately to get data
   58      * from a callback rather than from an execution
   59      * instance.
   60      *
   61      * @var string
   62      */
   63     private $_callback = '';
   64     /**
   65      * Contains the response of our url requests.
   66      *
   67      * @var array
   68      */
   69     private $_response = array();
   70     /**
   71      * Curl options to all url requests.
   72      *
   73      * @var array
   74      */
   75     public $options = array(
   76         CURLOPT_SSL_VERIFYPEER => false,
   77         CURLOPT_SSL_VERIFYHOST => false,
   78         CURLOPT_RETURNTRANSFER => true,
   79     );
   80     /**
   81      * Curl headers to send/request.
   82      *
   83      * @var array
   84      */
   85     private $_headers = array();
   86     /**
   87      * The requests themselves.
   88      *
   89      * @var array
   90      */
   91     private $_requests = array();
   92     /**
   93      * The mapping of requests so we can receive
   94      * information in the proper order as requested.
   95      *
   96      * @var array
   97      */
   98     private $_requestMap = array();
   99     /**
  100      * Initializes our url requests object.
  101      *
  102      * @param string $callback Optional callback
  103      */
  104     public function __construct($callback = null)
  105     {
  106         parent::__construct();
  107         list(
  108             $aconntimeout,
  109             $conntimeout,
  110             $timeout
  111         ) = self::getSubObjectIDs(
  112             'Service',
  113             array(
  114                 'name' => array(
  115                     'FOG_URL_AVAILABLE_TIMEOUT',
  116                     'FOG_URL_BASE_CONNECT_TIMEOUT',
  117                     'FOG_URL_BASE_TIMEOUT'
  118                 )
  119             ),
  120             'value',
  121             false,
  122             'AND',
  123             'name',
  124             false,
  125             ''
  126         );
  127         if ($aconntimeout
  128             && is_numeric($aconntimeout)
  129             && $aconntimeout > 0
  130             && $aconntimeout > $this->_aconntimeout
  131         ) {
  132             $this->_aconntimeout = (int)$aconntimeout;
  133         }
  134         if ($conntimeout
  135             && is_numeric($conntimeout)
  136             && $conntimeout > 0
  137         ) {
  138             $this->_conntimeout = (int)$conntimeout;
  139         }
  140         if ($timeout
  141             && is_numeric($timeout)
  142             && $timeout > 0
  143         ) {
  144             $this->_timeout = (int)$timeout;
  145         }
  146         $this->options[CURLOPT_CONNECTTIMEOUT] = $this->_conntimeout;
  147         $this->options[CURLOPT_TIMEOUT] = $this->_timeout;
  148         $this->_callback = $callback;
  149     }
  150     /**
  151      * Cleans up when no longer needed.
  152      */
  153     public function __destruct()
  154     {
  155         $this->_windowSize = 20;
  156         $this->_callback = '';
  157         $this->options = array(
  158             CURLOPT_SSL_VERIFYPEER => false,
  159             CURLOPT_SSL_VERIFYHOST => false,
  160             CURLOPT_RETURNTRANSFER => true,
  161         );
  162         $this->_response = array();
  163         $this->_requests = array();
  164         $this->_requestMap = array();
  165     }
  166     /**
  167      * Magic caller to get specialized methods
  168      * in a common method.
  169      *
  170      * @param string $name The method to get
  171      *
  172      * @return mixed
  173      */
  174     public function __get($name)
  175     {
  176         if (in_array($name, array('headers'))) {
  177             $name = sprintf(
  178                 '_%s',
  179                 $name
  180             );
  181         }
  182         return (isset($this->{$name})) ? $this->{$name} : null;
  183     }
  184     /**
  185      * Magic caller to set specialized methods
  186      * in a common method.
  187      *
  188      * @param string $name  The method to set
  189      * @param mixed  $value The value to set
  190      *
  191      * @return object
  192      */
  193     public function __set($name, $value)
  194     {
  195         $addMethods = array(
  196             'options',
  197             'headers',
  198         );
  199         if (in_array($name, array('headers'))) {
  200             $name = sprintf(
  201                 '_%s',
  202                 $name
  203             );
  204         }
  205         if (in_array($name, $addMethods)) {
  206             $this->{$name} = $value + $this->{$name};
  207         } else {
  208             $this->{$name} = $value;
  209         }
  210 
  211         return $this;
  212     }
  213     /**
  214      * Add a request to the requests variable.
  215      *
  216      * @param FOGRollingURL $request the request to add
  217      *
  218      * @return object
  219      */
  220     public function add($request)
  221     {
  222         $this->_requests[] = $request;
  223 
  224         return $this;
  225     }
  226     /**
  227      * Generates the request and stores to our requests variable.
  228      *
  229      * @param string $url      The url to request
  230      * @param string $method   The method to call
  231      * @param mixed  $postData The data to pass
  232      * @param mixed  $headers  Any additional request headers to send
  233      * @param mixed  $options  Any additional request options to use
  234      *
  235      * @return object
  236      */
  237     public function request(
  238         $url,
  239         $method = 'GET',
  240         $postData = array(),
  241         $headers = array(),
  242         $options = array()
  243     ) {
  244         $this->_requests[] = new FOGRollingURL(
  245             $url,
  246             $method,
  247             $postData,
  248             $headers,
  249             $options
  250         );
  251 
  252         return $this;
  253     }
  254     /**
  255      * Get method url request definition.
  256      *
  257      * @param string $url     The url to request to
  258      * @param mixed  $headers The custom headers to send with this
  259      * @param mixed  $options The custom options to send with this
  260      *
  261      * @return object
  262      */
  263     public function get(
  264         $url,
  265         $headers = null,
  266         $options = null
  267     ) {
  268         return $this->request(
  269             $url,
  270             'GET',
  271             null,
  272             $headers,
  273             $options
  274         );
  275     }
  276     /**
  277      * Post method url request definition.
  278      *
  279      * @param string $url       The url to request to
  280      * @param mixed  $post_data The post data to send
  281      * @param mixed  $headers   The custom headers to send with this
  282      * @param mixed  $options   The custom options to send with this
  283      *
  284      * @return object
  285      */
  286     public function post(
  287         $url,
  288         $post_data = null,
  289         $headers = null,
  290         $options = null
  291     ) {
  292         return $this->request(
  293             $url,
  294             'POST',
  295             $post_data,
  296             $headers,
  297             $options
  298         );
  299     }
  300     /**
  301      * Actually executes the requests.
  302      * If only one request, perform a _singleCurl.
  303      * If multiple perform _rollingCurl.
  304      *
  305      * @param mixed $window_size The window size to allow at run time
  306      *
  307      * @return object
  308      */
  309     public function execute($window_size = null)
  310     {
  311         $window_count = count($this->_requests);
  312         if (empty($window_size)
  313             || !is_numeric($window_size)
  314             || $window_size > $window_count
  315         ) {
  316             $window_size = $window_count;
  317         }
  318         if ($window_count < 1) {
  319             return (array) false;
  320         }
  321         if ($window_count === 1) {
  322             return $this->_singleCurl();
  323         }
  324 
  325         return $this->_rollingCurl($window_size);
  326     }
  327     /**
  328      * Run a single url request.
  329      *
  330      * @return mixed
  331      */
  332     private function _singleCurl()
  333     {
  334         $ch = curl_init();
  335         $request = array_shift($this->_requests);
  336         $options = $this->_getOptions($request);
  337         curl_setopt_array($ch, $options);
  338         $output = curl_exec($ch);
  339         $info = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  340         curl_close($ch);
  341         if ($this->_callback && is_callable($this->_callback)) {
  342             $this->_callback($output, $info, $request);
  343         }
  344 
  345         return (array)$output;
  346     }
  347     /**
  348      * Perform multiple url requests.
  349      *
  350      * @param mixed $window_size The customized window size to use
  351      *
  352      * @return mixed
  353      */
  354     private function _rollingCurl($window_size = null)
  355     {
  356         if ($window_size) {
  357             $this->_windowSize = $window_size;
  358         }
  359         if (sizeof($this->_requests) < $this->_windowSize) {
  360             $this->_windowSize = sizeof($this->_requests);
  361         }
  362         if ($this->_windowSize < 2) {
  363             throw new Exception(_('Window size must be greater than 1'));
  364         }
  365         $timeout = $this->_timeout;
  366         $master = curl_multi_init();
  367         for ($i = 0; $i < $this->_windowSize; ++$i) {
  368             $ch = curl_init();
  369             $options = $this->_getOptions($this->_requests[$i]);
  370             curl_setopt_array($ch, $options);
  371             curl_multi_add_handle($master, $ch);
  372             $key = (string) $ch;
  373             $this->_requestMap[$key] = $i;
  374         }
  375         do {
  376             while ((
  377                 $execrun = curl_multi_exec(
  378                     $master,
  379                     $running
  380                 )
  381             ) == CURLM_CALL_MULTI_PERFORM) {
  382             }
  383             if ($execrun != CURLM_OK) {
  384                 break;
  385             }
  386             while ($done = curl_multi_info_read($master)) {
  387                 $info = curl_getinfo($done['handle'], CURLINFO_HTTP_CODE);
  388                 $key = (string)$done['handle'];
  389                 $output = curl_multi_getcontent($done['handle']);
  390                 $this->_response[$this->_requestMap[$key]] = $output;
  391                 if ($this->_callback && is_callable($this->_callback)) {
  392                     $request = $this->_requests[$this->_requestMap[$key]];
  393                     $this->_callback($output, $info, $request);
  394                 }
  395                 $sizeof = sizeof($this->_requests);
  396                 if ($i < $sizeof
  397                     && isset($this->_requests[$i])
  398                 ) {
  399                     $ch = curl_init();
  400                     $options = $this->_getOptions($this->_requests[$i]);
  401                     curl_setopt_array($ch, $options);
  402                     curl_multi_add_handle($master, $ch);
  403                     $key = (string) $ch;
  404                     $this->_requestMap[$key] = $i;
  405                     ++$i;
  406                 } else {
  407                     unset(
  408                         $this->_requests[$this->_requestMap[$key]],
  409                         $this->_requestMap[$key]
  410                     );
  411                 }
  412                 curl_multi_remove_handle($master, $done['handle']);
  413             }
  414             if ($running) {
  415                 curl_multi_select($master, $timeout);
  416             }
  417         } while ($running);
  418         ksort($this->_response);
  419         curl_multi_close($master);
  420 
  421         return $this->_response;
  422     }
  423     /**
  424      * Get options of the request and whole.
  425      *
  426      * @param FOGRollingURL $request the request to get options from
  427      *
  428      * @return array
  429      */
  430     private function _getOptions($request)
  431     {
  432         $options = $this->__get('options');
  433         if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {
  434             $options[CURLOPT_FOLLOWLOCATION] = 1;
  435             $options[CURLOPT_MAXREDIRS] = 5;
  436         }
  437         $url = $this->_validUrl($request->url);
  438         $headers = $this->__get('headers');
  439         if ($request->options) {
  440             $options = $request->options + $options;
  441         }
  442         $options[CURLOPT_URL] = $url;
  443         if ($request->postData) {
  444             $options[CURLOPT_POST] = 1;
  445             $options[CURLOPT_POSTFIELDS] = $request->postData;
  446         }
  447         if ($headers) {
  448             $options[CURLOPT_HEADER] = 0;
  449             $options[CURLOPT_HTTPHEADER] = (array)$headers;
  450         }
  451         list($ip, $password, $port, $username) = self::getSubObjectIDs(
  452             'Service',
  453             array(
  454                 'name' => array(
  455                     'FOG_PROXY_IP',
  456                     'FOG_PROXY_PASSWORD',
  457                     'FOG_PROXY_PORT',
  458                     'FOG_PROXY_USERNAME',
  459                 ),
  460             ),
  461             'value',
  462             false,
  463             'AND',
  464             'name',
  465             false,
  466             false
  467         );
  468         $IPs = self::getSubObjectIDs('StorageNode', array('isEnabled' => 1));
  469         $pat = sprintf(
  470             '#%s#i',
  471             implode('|', $IPs)
  472         );
  473         if (!preg_match($pat, $url)) {
  474             if ($ip) {
  475                 $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
  476                 $options[CURLOPT_PROXYPORT] = $port;
  477                 $options[CURLOPT_PROXY] = $ip;
  478                 if ($username) {
  479                     $options[CURLOPT_PROXYUSERPWD] = sprintf(
  480                         '%s:%s',
  481                         $username,
  482                         $password
  483                     );
  484                 }
  485             }
  486         }
  487 
  488         return $options;
  489     }
  490     /**
  491      * Function simply ensures the url is valid.
  492      *
  493      * @param string $url The url test check
  494      *
  495      * @return string
  496      */
  497     private function _validUrl(&$url)
  498     {
  499         $url = filter_var($url, FILTER_SANITIZE_URL);
  500         if (false === filter_var($url, FILTER_VALIDATE_URL)) {
  501             unset($url);
  502         }
  503 
  504         return $url;
  505     }
  506     /**
  507      * Processes the requests as needed.
  508      *
  509      * @param mixed  $urls       the urls to process
  510      * @param string $method     the method to use for all urls
  511      * @param mixed  $data       post/get data possibly
  512      * @param bool   $sendAsJSON Send data as json if needed
  513      * @param mixed  $auth       Any authorization data needed
  514      * @param string $callback   A callback to use if needed
  515      * @param string $file       A filename to use to download a file
  516      * @param mixed  $timeout    allow updating timeout values
  517      *
  518      * @return array
  519      */
  520     public function process(
  521         $urls,
  522         $method = 'GET',
  523         $data = null,
  524         $sendAsJSON = false,
  525         $auth = false,
  526         $callback = false,
  527         $file = false,
  528         $timeout = false
  529     ) {
  530         $this->__destruct();
  531         if (false !== $timeout) {
  532             $this->_timeout = (int)$timeout;
  533             $this->options[CURLOPT_TIMEOUT] = (int)$timeout;
  534         }
  535         if ($callback && is_callable($callback)) {
  536             $this->_callback = $callback;
  537         }
  538         if ($auth) {
  539             $this->options[CURLOPT_USERPWD] = $auth;
  540         }
  541         if ($sendAsJSON) {
  542             $data2 = json_encode($data);
  543             $datalen = strlen($data2);
  544             $this->options[CURLOPT_HEADER] = true;
  545             $this->options[CURLOPT_HTTPHEADER] = array(
  546                 'Content-Type: application/json',
  547                 "Content-Length: $datalen",
  548                 'Expect:',
  549             );
  550         }
  551         if ($file) {
  552             $this->options[CURLOPT_FILE] = $file;
  553         }
  554         $this->options[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0';
  555         foreach ((array) $urls as &$url) {
  556             if ($method === 'GET') {
  557                 $this->get($url);
  558             } else {
  559                 $this->post($url, $data);
  560             }
  561             unset($url);
  562         }
  563 
  564         return $this->execute();
  565     }
  566     /**
  567      * Quick test if url is available.
  568      *
  569      * @param string $urls    the url to check.
  570      * @param int    $timeout the timeout value.
  571      * @param int    $port    the port to test on.
  572      *
  573      * @return void
  574      */
  575     public function isAvailable($urls, $timeout = 30, $port = -1)
  576     {
  577         $this->__destruct();
  578         $output = array();
  579         if (empty($timeout) || !$timeout || $timeout < 1) {
  580             $timeout = 30;
  581         }
  582         foreach ((array) $urls as &$url) {
  583             $url = parse_url($url);
  584             if (!isset($url['host']) && isset($url['path'])) {
  585                 $url['host'] = $url['path'];
  586             }
  587             if ($port == -1 || empty($port) || !$port) {
  588                 if (!isset($url['port']) && isset($url['scheme'])) {
  589                     switch ($url['scheme']) {
  590                         case "http":
  591                             $port = 80;
  592                             break;
  593                         case "https":
  594                             $port = 443;
  595                             break;
  596                         case "ftp":
  597                             $port = 21;
  598                             break;
  599                         default:
  600                             $port = self::$FOGFTP->get('port');
  601                     }
  602                 } else {
  603                     $port = self::$FOGFTP->get('port');
  604                 }
  605             }
  606             $socket = @fsockopen(
  607                 $url['host'],
  608                 $port,
  609                 $errno,
  610                 $errstr,
  611                 $timeout
  612             );
  613             if (!$socket) {
  614                 $output[] = false;
  615                 continue;
  616             }
  617             $output[] = true;
  618             fclose($socket);
  619             unset($url);
  620         }
  621 
  622         return $output;
  623     }
  624 }