/** * @internal * * @param array $request * * @return array */ public function _invokeAsArray(array $request) { $factory = $this->factory; // Ensure headers are by reference. They're updated elsewhere. $result = $factory($request, curl_init()); $h = $result[0]; $hd =& $result[1]; $body = $result[2]; Core::doSleep($request); try { // override the default body stream with the request response $safecurl = new SafeCurl($h); $body = $safecurl->execute(Core::url($request)); } catch (Exception $e) { // URL wasn't safe, return empty content $body = ''; $safeCurlError = $e->getMessage(); } $response = ['transfer_stats' => curl_getinfo($h)]; $response['curl']['error'] = curl_error($h); $response['curl']['errno'] = curl_errno($h); $response['transfer_stats'] = array_merge($response['transfer_stats'], $response['curl']); curl_close($h); // override default error message in case of SafeCurl error if (isset($safeCurlError)) { $response['err_message'] = $safeCurlError; } return CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, Stream::factory($body)); }
<?php /* * redirects.php * * Using SafeCurl and following redirects with a limit */ require '../vendor/autoload.php'; use fin1te\SafeCurl\SafeCurl; use fin1te\SafeCurl\Options; try { $curlHandle = curl_init(); $options = new Options(); //Follow redirects, but limit to 10 $options->enableFollowLocation()->setFollowLocationLimit(10); $result = SafeCurl::execute('http://fin1te.net', $curlHandle); } catch (Exception $e) { //Handle exception }
/** * Exectutes a cURL request, whilst checking that the * URL abides by our whitelists/blacklists * * @param $url string * @param $curlHandle resource optional - Incase called on an object rather than statically * @param $options SafeCurl\Options optional * * @return bool */ public static function execute($url, $curlHandle = null, Options $options = null) { //Check if we've been called staticly or not if (isset($this) && get_class($this) == __CLASS__) { $safeCurl = $this; //Get the cURL handle, if it wasn't passed in if (!is_resource($curlHandle) || get_resource_type($curlHandle) != 'curl') { $curlHandle = $this->getCurlHandle(); } } else { $safeCurl = new SafeCurl($curlHandle, $options); } //Backup the existing URL $originalUrl = $url; //Execute, catch redirects and validate the URL $redirected = false; $redirectCount = 0; $redirectLimit = $safeCurl->getOptions()->getFollowLocationLimit(); $followLocation = $safeCurl->getOptions()->getFollowLocation(); do { //Validate the URL $url = Url::validateUrl($url, $safeCurl->getOptions()); //Are there credentials, but we don't want to send them? if (!$safeCurl->getOptions()->getSendCredentials() && (array_key_exists('user', $url) || array_key_exists('pass', $url))) { throw new InvalidURLException("Credentials passed in but 'sendCredentials' is set to false"); } if ($safeCurl->getOptions()->getPinDns()) { //Send a Host header curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array('Host: ' . $url['parts']['host'])); //The "fake" URL curl_setopt($curlHandle, CURLOPT_URL, $url['cleanUrl']); //We also have to disable SSL cert verfication, which is not great //Might be possible to manually check the certificate ourselves? curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false); } else { curl_setopt($curlHandle, CURLOPT_URL, $url['cleanUrl']); } //Execute the cURL request $response = curl_exec($curlHandle); //Check for any errors if (curl_errno($curlHandle)) { throw new Exception("cURL Error: " . curl_error($curlHandle)); } //Check for an HTTP redirect if ($followLocation) { $statusCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE); switch ($statusCode) { case 301: case 302: case 303: case 307: case 308: if ($redirectLimit == 0 || ++$redirectCount < $redirectLimit) { //Redirect received, so rinse and repeat $url = curl_getinfo($curlHandle, CURLINFO_REDIRECT_URL); $redirected = true; } else { throw new Exception("Redirect limit '{$redirectLimit}' hit"); } break; default: $redirected = false; } } } while ($redirected); return $response; }
<?php /* * options.php * * Using SafeCurl with custom options */ require '../vendor/autoload.php'; use fin1te\SafeCurl\SafeCurl; use fin1te\SafeCurl\Options; try { $curlHandle = curl_init(); $options = new Options(); //Completely clear the whitelist $options->setList('whitelist', []); //Completely clear the blacklist $options->setList('blacklist', []); //Set the domain whitelist only $options->setList('whitelist', ['google.com', 'youtube.com'], 'domain'); $result = SafeCurl::execute('http://www.youtube.com', $curlHandle); } catch (Exception $e) { //Handle exception }