/components/com_easyblog/helpers/connectors.php

https://bitbucket.org/pastor399/newcastleunifc · PHP · 279 lines · 211 code · 49 blank · 19 comment · 33 complexity · cb15b380eb359a1ab4b766e74b1def34 MD5 · raw file

  1. <?php
  2. /*
  3. * @package EasyBlog
  4. * @copyright Copyright (C) 2010 Stack Ideas Private Limited. All rights reserved.
  5. * @license GNU/GPL, see LICENSE.php
  6. * EasyBlog is free software. This version may have been modified pursuant
  7. * to the GNU General Public License, and as distributed it includes or
  8. * is derivative of works licensed under the GNU General Public License or
  9. * other free or open source software licenses.
  10. * See COPYRIGHT.php for copyright notices and details.
  11. */
  12. defined( 'JPATH_BASE' ) or die( 'Unauthorized Access' );
  13. class EasyBlogConnectorsHelper
  14. {
  15. public $defaultOptions = array(
  16. CURLOPT_CONNECTTIMEOUT => 15,
  17. CURLOPT_RETURNTRANSFER => true,
  18. CURLOPT_TIMEOUT => 60,
  19. CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0.1) Gecko/20100101 Firefox/5.0.1',
  20. CURLOPT_HEADER => true
  21. );
  22. var $options = array();
  23. var $handles = array();
  24. var $handle = null;
  25. var $result = array();
  26. var $header = array();
  27. var $redirects = array( 300 , 301 , 302 , 303 , 304 , 305 , 306 , 307 );
  28. var $args = array();
  29. var $current = '';
  30. public function __construct()
  31. {
  32. $this->handle = curl_multi_init();
  33. }
  34. public function addUrl( $url )
  35. {
  36. $this->handles[ $url ] = curl_init( $url );
  37. $this->current = $url;
  38. $this->options[ $url ] = $this->defaultOptions;
  39. return curl_multi_add_handle( $this->handle , $this->handles[ $url ] ) === 0;
  40. }
  41. public function addQuery( $key , $value )
  42. {
  43. $this->args[ $this->current ][ $key ] = $value;
  44. }
  45. public function addLength( $length )
  46. {
  47. $this->options[ CURLOPT_RANGE ] = $length;
  48. $this->options[ CURLOPT_HEADER ] = false;
  49. }
  50. public function useHeadersOnly()
  51. {
  52. $this->options[ CURLOPT_HEADER ] = true;
  53. $this->options[ CURLOPT_NOBODY ] = true;
  54. return true;
  55. }
  56. public function execute()
  57. {
  58. $running = null;
  59. /**
  60. * Get all handles and set the options for all respective handles
  61. */
  62. foreach( $this->handles as $handle )
  63. {
  64. $info = curl_getinfo( $handle );
  65. $url = $info[ 'url' ];
  66. // If this is a post request, then we should add the necessary post data
  67. if( isset( $this->options[ $url ][ CURLOPT_POST ] ) && $this->options[ $url ][ CURLOPT_POST ] === true )
  68. {
  69. $this->options[ $url ][ CURLOPT_POSTFIELDS ] = http_build_query( $this->args[ $url ] );
  70. }
  71. // Set options for specific urls.
  72. curl_setopt_array( $handle , $this->options[ $url ] );
  73. }
  74. do
  75. {
  76. curl_multi_exec( $this->handle , $running );
  77. }
  78. while( $running > 0 );
  79. foreach( $this->handles as $key => $handle )
  80. {
  81. $code = curl_getinfo( $handle , CURLINFO_HTTP_CODE );
  82. if( in_array( $code , $this->redirects ) )
  83. {
  84. // @TODO: Send logging to exceptional to log this curl error
  85. $error = curl_error( $handle );
  86. $content = curl_multi_getcontent( $handle );
  87. $headers = explode( "\r\n\r\n" , $content );
  88. $this->executeRedirects( $handle , $key , $code , $headers[0] );
  89. }
  90. else
  91. {
  92. $content = curl_multi_getcontent( $handle );
  93. $content = explode( "\r\n\r\n" , $content );
  94. // we 'throw' the 1st index which we know its a header
  95. $htmlheader = array_shift($content);
  96. $htmlcontent = implode("\r\n\r\n", $content);
  97. $this->result[ $key ] = $htmlcontent;
  98. $this->header[ $key ] = $htmlheader;
  99. }
  100. curl_multi_remove_handle( $this->handle , $handle );
  101. }
  102. curl_multi_close( $this->handle );
  103. return true;
  104. }
  105. function executeRedirects( $handle , $key , $code = '' , $headers = '' )
  106. {
  107. static $curl_loops = 0;
  108. static $curl_max_loops = 20;
  109. if( $curl_loops++ >= $curl_max_loops )
  110. {
  111. $curl_loops = 0;
  112. return false;
  113. }
  114. if( $curl_loops > 1 )
  115. {
  116. $data = curl_exec( $handle );
  117. $res = explode( "\n\n" , $data , 2 );
  118. $headers = isset( $res[ 0 ] ) ? $res[ 0 ] : '';
  119. $newdata = isset( $res[ 1 ] ) ? $res[ 1 ] : '';
  120. if( $curl_loops == 5 )
  121. {
  122. echo '5';
  123. exit;
  124. }
  125. $code = curl_getinfo( $handle , CURLINFO_HTTP_CODE );
  126. }
  127. if( $code == 301 || $code == 302)
  128. {
  129. $matches = array();
  130. preg_match('/Location:(.*?)\n/', $headers, $matches);
  131. $url = @parse_url(trim(array_pop($matches)));
  132. $new_url = '';
  133. if( isset( $url['host'] ) )
  134. {
  135. if( $url['scheme'] == 'http' || $url['scheme'] == 'https' )
  136. {
  137. //$new_url = $url['scheme' ] . '://' . $url['host'] . $url['path'];
  138. $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ( isset( $url['query'] ) ?'?'.$url['query']:'');
  139. }
  140. }
  141. if( empty( $new_url ) )
  142. {
  143. if (!$url)
  144. {
  145. $curl_loops = 0;
  146. return $newdata;
  147. }
  148. $last_url = parse_url( curl_getinfo( $handle , CURLINFO_EFFECTIVE_URL) );
  149. if ( ( isset( $url[ 'scheme'] ) && !$url['scheme'] ) || ( ! isset($url[ 'scheme']) ) )
  150. {
  151. $url['scheme'] = $last_url['scheme'];
  152. }
  153. if( ( isset( $url[ 'host'] ) && !$url['host'] ) || ( ! isset($url[ 'host']) ) )
  154. {
  155. $url['host'] = $last_url['host'];
  156. }
  157. if( ( isset( $url[ 'path' ] ) && !$url['path'] ) || ( ! isset($url[ 'path']) ) )
  158. {
  159. $url['path'] = $last_url['path'];
  160. }
  161. $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ( isset( $url['query'] ) ?'?'.$url['query']:'');
  162. }
  163. // @rule: Refresh with a new curl resource to avoid multi init issues.
  164. curl_setopt( $handle , CURLOPT_URL , $new_url );
  165. curl_setopt( $handle , CURLOPT_RETURNTRANSFER , true );
  166. curl_setopt( $handle , CURLOPT_HEADER , true );
  167. $data = curl_exec( $handle );
  168. $content = curl_multi_getcontent( $handle );
  169. $headers = explode( "\r\n\r\n" , $content );
  170. $code = curl_getinfo( $handle , CURLINFO_HTTP_CODE );
  171. if( $code == 301 || $code == 302)
  172. {
  173. return self::executeRedirects( $handle , $key , $code , $headers );
  174. }
  175. $curl_loops = 0;
  176. $this->result[ $key ] = $data;
  177. }
  178. else
  179. {
  180. $curl_loops = 0;
  181. $this->result[ $key ] = $data;
  182. }
  183. }
  184. public function getResult( $url )
  185. {
  186. if( !isset( $this->result[ $url ] ) )
  187. {
  188. return false;
  189. }
  190. return $this->result[ $url ];
  191. }
  192. public function getResultHeader( $url )
  193. {
  194. if( !isset( $this->header[ $url ] ) )
  195. {
  196. return false;
  197. }
  198. return $this->header[ $url ];
  199. }
  200. public function getResults()
  201. {
  202. return $this->result;
  203. }
  204. public function addOption( $key , $value )
  205. {
  206. $this->options[$this->current][ $key ] = $value;
  207. }
  208. public function addFile( $resource , $size )
  209. {
  210. $this->addOption( CURLOPT_INFILE , $resource );
  211. $this->addOption( CURLOPT_INFILESIZE , $size );
  212. return true;
  213. }
  214. public function setMethod( $method = 'GET' )
  215. {
  216. switch( $method )
  217. {
  218. case 'GET':
  219. $this->addOption( CURLOPT_HTTPGET , true );
  220. break;
  221. case 'POST':
  222. $this->addOption( CURLOPT_POST , true );
  223. break;
  224. case 'PUT':
  225. $this->addOption( CURLOPT_PUT , true );
  226. break;
  227. }
  228. return true;
  229. }
  230. }