Curl Response Refactoring

- extended Curl to parse Curl Response
- refactored Network::curl()
- replaced every Network::curl() execution with the new Curl container
This commit is contained in:
Philipp Holzer 2018-10-10 21:08:43 +02:00
parent 904fee3bed
commit 2dec8895a9
No known key found for this signature in database
GPG key ID: 517BE60E2CE5C8A5
20 changed files with 466 additions and 382 deletions

View file

@ -2567,6 +2567,5 @@ function admin_page_features(App $a)
function admin_page_server_vital() function admin_page_server_vital()
{ {
// Fetch the host-meta to check if this really is a vital server // Fetch the host-meta to check if this really is a vital server
$serverret = Network::curl(System::baseUrl() . '/.well-known/host-meta'); return Network::curl(System::baseUrl() . '/.well-known/host-meta')->isSuccess();
return $serverret["success"];
} }

View file

@ -32,8 +32,7 @@ function feedtest_content(App $a)
$contact = DBA::selectFirst('contact', [], ['id' => $contact_id]); $contact = DBA::selectFirst('contact', [], ['id' => $contact_id]);
$ret = Network::curl($contact['poll']); $xml = Network::fetchUrl($contact['poll']);
$xml = $ret['body'];
$dummy = null; $dummy = null;
$import_result = Feed::import($xml, $importer, $contact, $dummy, true); $import_result = Feed::import($xml, $importer, $contact, $dummy, true);

View file

@ -44,14 +44,14 @@ function ostatus_subscribe_content(App $a) {
$api = $contact["baseurl"]."/api/"; $api = $contact["baseurl"]."/api/";
// Fetching friends // Fetching friends
$data = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]); $curlResult = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]);
if (!$data["success"]) { if (!$curlResult->isSuccess()) {
PConfig::delete($uid, "ostatus", "legacy_contact"); PConfig::delete($uid, "ostatus", "legacy_contact");
return $o.L10n::t("Couldn't fetch friends for contact."); return $o.L10n::t("Couldn't fetch friends for contact.");
} }
PConfig::set($uid, "ostatus", "legacy_friends", $data["body"]); PConfig::set($uid, "ostatus", "legacy_friends", $curlResult->getBody());
} }
$friends = json_decode(PConfig::get($uid, "ostatus", "legacy_friends")); $friends = json_decode(PConfig::get($uid, "ostatus", "legacy_friends"));
@ -72,8 +72,8 @@ function ostatus_subscribe_content(App $a) {
$o .= "<p>".$counter."/".$total.": ".$url; $o .= "<p>".$counter."/".$total.": ".$url;
$data = Probe::uri($url); $curlResult = Probe::uri($url);
if ($data["network"] == Protocol::OSTATUS) { if ($curlResult["network"] == Protocol::OSTATUS) {
$result = Contact::createFromProbe($uid, $url, true, Protocol::OSTATUS); $result = Contact::createFromProbe($uid, $url, true, Protocol::OSTATUS);
if ($result["success"]) { if ($result["success"]) {
$o .= " - ".L10n::t("success"); $o .= " - ".L10n::t("success");

View file

@ -60,12 +60,12 @@ function parse_url_content(App $a)
// the URL with the corresponding BBCode media tag // the URL with the corresponding BBCode media tag
$redirects = 0; $redirects = 0;
// Fetch the header of the URL // Fetch the header of the URL
$result = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]); $curlResponse = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]);
if ($result['success']) { if ($curlResponse->isSuccess()) {
// Convert the header fields into an array // Convert the header fields into an array
$hdrs = []; $hdrs = [];
$h = explode("\n", $result['header']); $h = explode("\n", $curlResponse->getHeader());
foreach ($h as $l) { foreach ($h as $l) {
$header = array_map('trim', explode(':', trim($l), 2)); $header = array_map('trim', explode(':', trim($l), 2));
if (count($header) == 2) { if (count($header) == 2) {

View file

@ -344,9 +344,9 @@ class ACL extends BaseObject
$a = self::getApp(); $a = self::getApp();
$p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : ''; $p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : '';
$response = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); $curlResult = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
if ($response['success']) { if ($curlResult->isSuccess()) {
$lsearch = json_decode($response['body'], true); $lsearch = json_decode($curlResult->getBody(), true);
if (!empty($lsearch['results'])) { if (!empty($lsearch['results'])) {
$return = $lsearch['results']; $return = $lsearch['results'];
} }

View file

@ -33,12 +33,12 @@ class APContact extends BaseObject
$webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr); $webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr);
$ret = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']); $curlResult = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']);
if (!$ret['success'] || empty($ret['body'])) { if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
return false; return false;
} }
$data = json_decode($ret['body'], true); $data = json_decode($curlResult->getBody(), true);
if (empty($data['links'])) { if (empty($data['links'])) {
return false; return false;

View file

@ -957,12 +957,12 @@ class GContact
$url = $server."/main/statistics"; $url = $server."/main/statistics";
$result = Network::curl($url); $curlResult = Network::curl($url);
if (!$result["success"]) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
$statistics = json_decode($result["body"]); $statistics = json_decode($curlResult->getBody());
if (!empty($statistics->config)) { if (!empty($statistics->config)) {
if ($statistics->config->instance_with_ssl) { if ($statistics->config->instance_with_ssl) {

View file

@ -1056,7 +1056,7 @@ class Profile
if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) { if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) {
$magic_path = $basepath . '/magic' . '?f=&owa=1&dest=' . $dest; $magic_path = $basepath . '/magic' . '?f=&owa=1&dest=' . $dest;
$serverret = Network::curl($magic_path); $serverret = Network::curl($magic_path);
if (!empty($serverret['success'])) { if ($serverret->isSuccess()) {
goaway($magic_path); goaway($magic_path);
} }
} }

View file

@ -82,10 +82,10 @@ class Magic extends BaseModule
); );
// Try to get an authentication token from the other instance. // Try to get an authentication token from the other instance.
$x = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]); $curlResult = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]);
if ($x['success']) { if ($curlResult->isSuccess()) {
$j = json_decode($x['body'], true); $j = json_decode($curlResult->getBody(), true);
if ($j['success']) { if ($j['success']) {
$token = ''; $token = '';

View file

@ -3,15 +3,17 @@
namespace Friendica\Network; namespace Friendica\Network;
use Friendica\Network\HTTPException\InternalServerErrorException;
/** /**
* A content class for Curl call results * A content class for Curl call results
*/ */
class Curl class Curl
{ {
/** /**
* @var string the Code of the Curl call * @var int HTTP return code or 0 if timeout or failure
*/ */
private $code; private $returnCode;
/** /**
* @var string the content type of the Curl call * @var string the content type of the Curl call
@ -19,25 +21,179 @@ class Curl
private $contentType; private $contentType;
/** /**
* @var string the headers of the Curl call * @var string the HTTP headers of the Curl call
*/ */
private $headers; private $header;
public function __construct($code = '', $contentType = '', $headers = '') /**
* @var boolean true (if HTTP 2xx result) or false
*/
private $isSuccess;
/**
* @var string the URL which was called
*/
private $url;
/**
* @var string in case of redirect, content was finally retrieved from this URL
*/
private $redirectUrl;
/**
* @var string fetched content
*/
private $body;
/**
* @var array some informations about the fetched data
*/
private $info;
/**
* @var boolean true if the URL has a redirect
*/
private $isRedirectUrl;
/**
* @var boolean true if the curl request timed out
*/
private $isTimeout;
/**
* @var int optional error numer
*/
private $errorNumber;
/**
* @var string optional error message
*/
private $error;
/**
* Creates an errored CURL response
*
* @param string $url optional URL
*
* @return Curl a CURL with error response
*/
public static function createErrorCurl($url = '')
{ {
$this->code = $code; return new Curl(
$this->contentType = $contentType; $url,
$this->headers = $headers; '',
['http_code' => 0]
);
} }
/** /**
* Sets the Curl Code * Curl constructor.
* @param string $url the URL which was called
* @param string $result the result of the curl execution
* @param array $info an additional info array
* @param int $errorNumber the error number or 0 (zero) if no error
* @param string $error the error message or '' (the empty string) if no
* *
* @param string $code The Curl Code * @throws InternalServerErrorException when HTTP code of the CURL response is missing
*/ */
public function setCode($code) public function __construct($url, $result, $info, $errorNumber = 0, $error = '')
{ {
$this->code = $code; if (empty($info['http_code'])) {
throw new InternalServerErrorException('CURL response doesn\'t contains a response HTTP code');
}
$this->returnCode = $info['http_code'];
$this->url = $url;
$this->info = $info;
$this->errorNumber = $errorNumber;
$this->error = $error;
logger($url . ': ' . $this->returnCode . " " . $result, LOGGER_DATA);
$this->parseBodyHeader($result);
$this->checkSuccess();
$this->checkRedirect();
$this->checkInfo();
}
private function parseBodyHeader($result)
{
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
$header = '';
$base = $result;
while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
$chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
$header .= $chunk;
$base = substr($base, strlen($chunk));
}
$this->body = substr($result, strlen($header));
$this->header = $header;
}
private function checkSuccess()
{
$this->isSuccess = ((($this->returnCode >= 200 && $this->returnCode <= 299) || !empty($this->errorNumber)) ? true : false);
if (!$this->isSuccess) {
logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_DEBUG);
logger('debug: ' . print_r($this->info, true), LOGGER_DATA);
}
if (!$this->isSuccess && $this->errorNumber == CURLE_OPERATION_TIMEDOUT) {
$this->isTimeout = true;
} else {
$this->isTimeout = false;
}
}
private function checkRedirect()
{
if (empty($this->info['url'])) {
$this->redirectUrl = '';
} else {
$this->redirectUrl = $this->info['url'];
}
if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) {
$new_location_info = (empty($this->info['redirect_url']) ? '' : @parse_url($this->info['redirect_url']));
$old_location_info = (empty($this->info['url'] ? '' : @parse_url($this->info['url']));
$this->redirectUrl = $new_location_info;
if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
$this->redirectUrl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
}
$matches = [];
if (preg_match('/(Location:|URI:)(.*?)\n/i', $this->header, $matches)) {
$this->redirectUrl = trim(array_pop($matches));
}
if (strpos($this->redirectUrl, '/') === 0) {
$this->redirectUrl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $this->redirectUrl;
}
$old_location_query = @parse_url($this->url, PHP_URL_QUERY);
if ($old_location_query != '') {
$this->redirectUrl .= '?' . $old_location_query;
}
$this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL);
} else {
$this->isRedirectUrl = false;
}
}
private function checkInfo()
{
if (isset($this->info['content_type'])) {
$this->contentType = $this->info['content_type'];
} else {
$this->contentType = '';
}
} }
/** /**
@ -45,19 +201,9 @@ class Curl
* *
* @return string The Curl Code * @return string The Curl Code
*/ */
public function getCode() public function getReturnCode()
{ {
return $this->code; return $this->returnCode;
}
/**
* Sets the Curl Content Type
*
* @param string $content_type The Curl Content Type
*/
public function setContentType($content_type)
{
$this->contentType = $content_type;
} }
/** /**
@ -70,23 +216,85 @@ class Curl
return $this->contentType; return $this->contentType;
} }
/**
* Sets the Curl headers
*
* @param string $headers the Curl headers
*/
public function setHeaders($headers)
{
$this->headers = $headers;
}
/** /**
* Returns the Curl headers * Returns the Curl headers
* *
* @return string the Curl headers * @return string the Curl headers
*/ */
public function getHeaders() public function getHeader()
{ {
return $this->headers; return $this->header;
}
/**
* @return bool
*/
public function isSuccess()
{
return $this->isSuccess;
}
/**
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* @return string
*/
public function getRedirectUrl()
{
return $this->redirectUrl;
}
/**
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* @return array
*/
public function getInfo()
{
return $this->info;
}
/**
* @return bool
*/
public function isRedirectUrl()
{
return $this->isRedirectUrl;
}
/**
* @return int
*/
public function getErrorNumber()
{
return $this->errorNumber;
}
/**
* @return string
*/
public function getError()
{
return $this->error;
}
/**
* @return bool
*/
public function isTimeout()
{
return $this->isTimeout;
} }
} }

View file

@ -112,20 +112,20 @@ class Probe
logger("Probing for ".$host, LOGGER_DEBUG); logger("Probing for ".$host, LOGGER_DEBUG);
$xrd = null; $xrd = null;
$ret = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); $curlResult = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
if ($ret['success']) { if ($curlResult->isSuccess()) {
$xml = $ret['body']; $xml = $curlResult->getBody();
$xrd = XML::parseString($xml, false); $xrd = XML::parseString($xml, false);
$host_url = 'https://'.$host; $host_url = 'https://'.$host;
} }
if (!is_object($xrd)) { if (!is_object($xrd)) {
$ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); $curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
logger("Probing timeout for ".$url, LOGGER_DEBUG); logger("Probing timeout for " . $url, LOGGER_DEBUG);
return false; return false;
} }
$xml = $ret['body']; $xml = $curlResult->getBody();
$xrd = XML::parseString($xml, false); $xrd = XML::parseString($xml, false);
$host_url = 'http://'.$host; $host_url = 'http://'.$host;
} }
@ -742,11 +742,11 @@ class Probe
$xrd_timeout = Config::get('system', 'xrd_timeout', 20); $xrd_timeout = Config::get('system', 'xrd_timeout', 20);
$redirects = 0; $redirects = 0;
$ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]); $curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
return false; return false;
} }
$data = $ret['body']; $data = $curlResult->getBody();
$webfinger = json_decode($data, true); $webfinger = json_decode($data, true);
if (is_array($webfinger)) { if (is_array($webfinger)) {
@ -809,11 +809,11 @@ class Probe
*/ */
private static function pollNoscrape($noscrape_url, $data) private static function pollNoscrape($noscrape_url, $data)
{ {
$ret = Network::curl($noscrape_url); $curlResult = Network::curl($noscrape_url);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
return false; return false;
} }
$content = $ret['body']; $content = $curlResult->getBody();
if (!$content) { if (!$content) {
logger("Empty body for ".$noscrape_url, LOGGER_DEBUG); logger("Empty body for ".$noscrape_url, LOGGER_DEBUG);
return false; return false;
@ -1054,11 +1054,11 @@ class Probe
*/ */
private static function pollHcard($hcard_url, $data, $dfrn = false) private static function pollHcard($hcard_url, $data, $dfrn = false)
{ {
$ret = Network::curl($hcard_url); $curlResult = Network::curl($hcard_url);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
return false; return false;
} }
$content = $ret['body']; $content = $curlResult->getBody();
if (!$content) { if (!$content) {
return false; return false;
} }
@ -1301,11 +1301,11 @@ class Probe
$pubkey = substr($pubkey, 5); $pubkey = substr($pubkey, 5);
} }
} elseif (normalise_link($pubkey) == 'http://') { } elseif (normalise_link($pubkey) == 'http://') {
$ret = Network::curl($pubkey); $curlResult = Network::curl($pubkey);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
return false; return false;
} }
$pubkey = $ret['body']; $pubkey = $curlResult['body'];
} }
$key = explode(".", $pubkey); $key = explode(".", $pubkey);
@ -1333,11 +1333,11 @@ class Probe
} }
// Fetch all additional data from the feed // Fetch all additional data from the feed
$ret = Network::curl($data["poll"]); $curlResult = Network::curl($data["poll"]);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if (!empty($curlResult["errno"]) && ($curlResult['errno'] == CURLE_OPERATION_TIMEDOUT)) {
return false; return false;
} }
$feed = $ret['body']; $feed = $curlResult['body'];
$dummy1 = null; $dummy1 = null;
$dummy2 = null; $dummy2 = null;
$dummy2 = null; $dummy2 = null;
@ -1543,11 +1543,11 @@ class Probe
*/ */
private static function feed($url, $probe = true) private static function feed($url, $probe = true)
{ {
$ret = Network::curl($url); $curlResult = Network::curl($url);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
return false; return false;
} }
$feed = $ret['body']; $feed = $curlResult->getBody();
$dummy1 = $dummy2 = $dummy3 = null; $dummy1 = $dummy2 = $dummy3 = null;
$feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true); $feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true);

View file

@ -58,12 +58,12 @@ class ActivityPub
*/ */
public static function fetchContent($url) public static function fetchContent($url)
{ {
$ret = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']); $curlResult = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']);
if (!$ret['success'] || empty($ret['body'])) { if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
return false; return false;
} }
return json_decode($ret['body'], true); return json_decode($curlResult->getBody(), true);
} }
/** /**

View file

@ -1170,10 +1170,10 @@ class DFRN
// At first try the Diaspora transport layer // At first try the Diaspora transport layer
if (!$dissolve && !$legacy_transport) { if (!$dissolve && !$legacy_transport) {
$ret = self::transmit($owner, $contact, $atom); $curlResult = self::transmit($owner, $contact, $atom);
if ($ret >= 200) { if ($curlResult >= 200) {
logger('Delivery via Diaspora transport layer was successful with status ' . $ret); logger('Delivery via Diaspora transport layer was successful with status ' . $curlResult);
return $ret; return $curlResult;
} }
} }
@ -1211,16 +1211,16 @@ class DFRN
logger('dfrn_deliver: ' . $url); logger('dfrn_deliver: ' . $url);
$ret = Network::curl($url); $curlResult = Network::curl($url);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
Contact::markForArchival($contact); Contact::markForArchival($contact);
return -2; // timed out return -2; // timed out
} }
$xml = $ret['body']; $xml = $curlResult->getBody();
$curl_stat = Network::getCurl()->getCode(); $curl_stat = $curlResult->getReturnCode();
if (empty($curl_stat)) { if (empty($curl_stat)) {
Contact::markForArchival($contact); Contact::markForArchival($contact);
return -3; // timed out return -3; // timed out
@ -1368,17 +1368,19 @@ class DFRN
logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars, true), LOGGER_DATA); logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars, true), LOGGER_DATA);
$xml = Network::post($contact['notify'], $postvars); $postResult = Network::post($contact['notify'], $postvars);
$xml = $postResult->getBody();
logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA);
$curl_stat = Network::getCurl()->getCode(); $curl_stat = $postResult->getReturnCode();
if (empty($curl_stat) || empty($xml)) { if (empty($curl_stat) || empty($xml)) {
Contact::markForArchival($contact); Contact::markForArchival($contact);
return -9; // timed out return -9; // timed out
} }
if (($curl_stat == 503) && stristr(Network::getCurl()->getHeaders(), 'retry-after')) { if (($curl_stat == 503) && stristr($postResult->getHeader(), 'retry-after')) {
Contact::markForArchival($contact); Contact::markForArchival($contact);
return -10; return -10;
} }

View file

@ -736,21 +736,21 @@ class OStatus
self::$conv_list[$conversation] = true; self::$conv_list[$conversation] = true;
$conversation_data = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); $curlResult = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
if (!$conversation_data['success']) { if (!$curlResult->isSuccess()) {
return; return;
} }
$xml = ''; $xml = '';
if (stristr($conversation_data['header'], 'Content-Type: application/atom+xml')) { if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) {
$xml = $conversation_data['body']; $xml = $curlResult->getBody();
} }
if ($xml == '') { if ($xml == '') {
$doc = new DOMDocument(); $doc = new DOMDocument();
if (!@$doc->loadHTML($conversation_data['body'])) { if (!@$doc->loadHTML($curlResult->getBody())) {
return; return;
} }
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
@ -767,8 +767,8 @@ class OStatus
if ($file != '') { if ($file != '') {
$conversation_atom = Network::curl($attribute['href']); $conversation_atom = Network::curl($attribute['href']);
if ($conversation_atom['success']) { if ($conversation_atom->isSuccess()) {
$xml = $conversation_atom['body']; $xml = $conversation_atom->getBody();
} }
} }
} }
@ -880,15 +880,15 @@ class OStatus
return; return;
} }
$self_data = Network::curl($self); $curlResult = Network::curl($self);
if (!$self_data['success']) { if (!$curlResult->isSuccess()) {
return; return;
} }
// We reformat the XML to make it better readable // We reformat the XML to make it better readable
$doc = new DOMDocument(); $doc = new DOMDocument();
$doc->loadXML($self_data['body']); $doc->loadXML($curlResult->getBody());
$doc->preserveWhiteSpace = false; $doc->preserveWhiteSpace = false;
$doc->formatOutput = true; $doc->formatOutput = true;
$xml = $doc->saveXML(); $xml = $doc->saveXML();
@ -925,22 +925,22 @@ class OStatus
} }
$stored = false; $stored = false;
$related_data = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); $curlResult = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
if (!$related_data['success']) { if (!$curlResult->isSuccess()) {
return; return;
} }
$xml = ''; $xml = '';
if (stristr($related_data['header'], 'Content-Type: application/atom+xml')) { if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) {
logger('Directly fetched XML for URI '.$related_uri, LOGGER_DEBUG); logger('Directly fetched XML for URI ' . $related_uri, LOGGER_DEBUG);
$xml = $related_data['body']; $xml = $curlResult->getBody();
} }
if ($xml == '') { if ($xml == '') {
$doc = new DOMDocument(); $doc = new DOMDocument();
if (!@$doc->loadHTML($related_data['body'])) { if (!@$doc->loadHTML($curlResult->getBody())) {
return; return;
} }
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
@ -956,11 +956,11 @@ class OStatus
} }
} }
if ($atom_file != '') { if ($atom_file != '') {
$related_atom = Network::curl($atom_file); $curlResult = Network::curl($atom_file);
if ($related_atom['success']) { if ($curlResult->isSuccess()) {
logger('Fetched XML for URI '.$related_uri, LOGGER_DEBUG); logger('Fetched XML for URI ' . $related_uri, LOGGER_DEBUG);
$xml = $related_atom['body']; $xml = $curlResult->getBody();
} }
} }
} }
@ -968,22 +968,22 @@ class OStatus
// Workaround for older GNU Social servers // Workaround for older GNU Social servers
if (($xml == '') && strstr($related, '/notice/')) { if (($xml == '') && strstr($related, '/notice/')) {
$related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom'); $curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom');
if ($related_atom['success']) { if ($curlResult->isSuccess()) {
logger('GNU Social workaround to fetch XML for URI '.$related_uri, LOGGER_DEBUG); logger('GNU Social workaround to fetch XML for URI ' . $related_uri, LOGGER_DEBUG);
$xml = $related_atom['body']; $xml = $curlResult->getBody();
} }
} }
// Even more worse workaround for GNU Social ;-) // Even more worse workaround for GNU Social ;-)
if ($xml == '') { if ($xml == '') {
$related_guess = OStatus::convertHref($related_uri); $related_guess = OStatus::convertHref($related_uri);
$related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom'); $curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom');
if ($related_atom['success']) { if ($curlResult->isSuccess()) {
logger('GNU Social workaround 2 to fetch XML for URI '.$related_uri, LOGGER_DEBUG); logger('GNU Social workaround 2 to fetch XML for URI ' . $related_uri, LOGGER_DEBUG);
$xml = $related_atom['body']; $xml = $curlResult->getBody();
} }
} }

View file

@ -290,8 +290,8 @@ class PortableContact
} }
// Fetch the host-meta to check if this really is a server // Fetch the host-meta to check if this really is a server
$serverret = Network::curl($server_url."/.well-known/host-meta"); $curlResult = Network::curl($server_url."/.well-known/host-meta");
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return ""; return "";
} }
@ -370,10 +370,10 @@ class PortableContact
$server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", DBA::escape(normalise_link($server_url))); $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", DBA::escape(normalise_link($server_url)));
if ($server) { if ($server) {
$noscraperet = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); $curlResult = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
if ($noscraperet["success"] && ($noscraperet["body"] != "")) { if ($curlResult->isSuccess() && ($curlResult->getBody() != "")) {
$noscrape = json_decode($noscraperet["body"], true); $noscrape = json_decode($curlResult->getBody(), true);
if (is_array($noscrape)) { if (is_array($noscrape)) {
$contact["network"] = $server[0]["network"]; $contact["network"] = $server[0]["network"];
@ -484,9 +484,9 @@ class PortableContact
GContact::update($contact); GContact::update($contact);
$feedret = Network::curl($data["poll"]); $curlResult = Network::curl($data["poll"]);
if (!$feedret["success"]) { if (!$curlResult->isSuccess()) {
$fields = ['last_failure' => DateTimeFormat::utcNow()]; $fields = ['last_failure' => DateTimeFormat::utcNow()];
DBA::update('gcontact', $fields, ['nurl' => normalise_link($profile)]); DBA::update('gcontact', $fields, ['nurl' => normalise_link($profile)]);
@ -496,7 +496,7 @@ class PortableContact
$doc = new DOMDocument(); $doc = new DOMDocument();
/// @TODO Avoid error supression here /// @TODO Avoid error supression here
@$doc->loadXML($feedret["body"]); @$doc->loadXML($curlResult->getBody());
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom"); $xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
@ -645,12 +645,12 @@ class PortableContact
*/ */
private static function fetchNodeinfo($server_url) private static function fetchNodeinfo($server_url)
{ {
$serverret = Network::curl($server_url."/.well-known/nodeinfo"); $curlResult = Network::curl($server_url."/.well-known/nodeinfo");
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
$nodeinfo = json_decode($serverret['body'], true); $nodeinfo = json_decode($curlResult->getBody(), true);
if (!is_array($nodeinfo) || !isset($nodeinfo['links'])) { if (!is_array($nodeinfo) || !isset($nodeinfo['links'])) {
return false; return false;
@ -698,13 +698,13 @@ class PortableContact
*/ */
private static function parseNodeinfo1($nodeinfo_url) private static function parseNodeinfo1($nodeinfo_url)
{ {
$serverret = Network::curl($nodeinfo_url); $curlResult = Network::curl($nodeinfo_url);
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
$nodeinfo = json_decode($serverret['body'], true); $nodeinfo = json_decode($curlResult->getBody(), true);
if (!is_array($nodeinfo)) { if (!is_array($nodeinfo)) {
return false; return false;
@ -782,12 +782,12 @@ class PortableContact
*/ */
private static function parseNodeinfo2($nodeinfo_url) private static function parseNodeinfo2($nodeinfo_url)
{ {
$serverret = Network::curl($nodeinfo_url); $curlResult = Network::curl($nodeinfo_url);
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
$nodeinfo = json_decode($serverret['body'], true); $nodeinfo = json_decode($curlResult->getBody(), true);
if (!is_array($nodeinfo)) { if (!is_array($nodeinfo)) {
return false; return false;
@ -997,38 +997,38 @@ class PortableContact
$server_url = str_replace("http://", "https://", $server_url); $server_url = str_replace("http://", "https://", $server_url);
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
$serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); $curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
// Quit if there is a timeout. // Quit if there is a timeout.
// But we want to make sure to only quit if we are mostly sure that this server url fits. // But we want to make sure to only quit if we are mostly sure that this server url fits.
if (DBA::isResult($gserver) && ($orig_server_url == $server_url) && if (DBA::isResult($gserver) && ($orig_server_url == $server_url) &&
(!empty($serverret["errno"]) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT))) { ($curlResult->isTimeout())) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]); DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]);
return false; return false;
} }
// Maybe the page is unencrypted only? // Maybe the page is unencrypted only?
$xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); $xmlobj = @simplexml_load_string($curlResult->getBody(), 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
if (!$serverret["success"] || ($serverret["body"] == "") || empty($xmlobj) || !is_object($xmlobj)) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == "") || empty($xmlobj) || !is_object($xmlobj)) {
$server_url = str_replace("https://", "http://", $server_url); $server_url = str_replace("https://", "http://", $server_url);
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
$serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); $curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
// Quit if there is a timeout // Quit if there is a timeout
if (!empty($serverret["errno"]) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if ($curlResult->isTimeout()) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); logger("Connection to server " . $server_url . " timed out.", LOGGER_DEBUG);
DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]); DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]);
return false; return false;
} }
$xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); $xmlobj = @simplexml_load_string($curlResult->getBody(), 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
} }
if (!$serverret["success"] || ($serverret["body"] == "") || empty($xmlobj) || !is_object($xmlobj)) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == "") || empty($xmlobj) || !is_object($xmlobj)) {
// Workaround for bad configured servers (known nginx problem) // Workaround for bad configured servers (known nginx problem)
if (!empty($serverret["debug"]) && !in_array($serverret["debug"]["http_code"], ["403", "404"])) { if (!empty($curlResult->getInfo()) && !in_array($curlResult->getInfo()["http_code"], ["403", "404"])) {
$failure = true; $failure = true;
} }
@ -1051,10 +1051,10 @@ class PortableContact
// Look for poco // Look for poco
if (!$failure) { if (!$failure) {
$serverret = Network::curl($server_url."/poco"); $curlResult = Network::curl($server_url."/poco");
if ($serverret["success"]) { if ($curlResult->isSuccess()) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['totalResults'])) { if (isset($data['totalResults'])) {
$registered_users = $data['totalResults']; $registered_users = $data['totalResults'];
@ -1083,12 +1083,12 @@ class PortableContact
if (!$failure) { if (!$failure) {
// Test for Diaspora, Hubzilla, Mastodon or older Friendica servers // Test for Diaspora, Hubzilla, Mastodon or older Friendica servers
$serverret = Network::curl($server_url); $curlResult = Network::curl($server_url);
if (!$serverret["success"] || ($serverret["body"] == "")) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == "")) {
$failure = true; $failure = true;
} else { } else {
$server = self::detectServerType($serverret["body"]); $server = self::detectServerType($curlResult->getBody());
if (!empty($server)) { if (!empty($server)) {
$platform = $server['platform']; $platform = $server['platform'];
@ -1097,7 +1097,7 @@ class PortableContact
$site_name = $server['site_name']; $site_name = $server['site_name'];
} }
$lines = explode("\n", $serverret["header"]); $lines = explode("\n", $curlResult->getHeader());
if (count($lines)) { if (count($lines)) {
foreach ($lines as $line) { foreach ($lines as $line) {
@ -1125,35 +1125,35 @@ class PortableContact
// Test for Statusnet // Test for Statusnet
// Will also return data for Friendica and GNU Social - but it will be overwritten later // Will also return data for Friendica and GNU Social - but it will be overwritten later
// The "not implemented" is a special treatment for really, really old Friendica versions // The "not implemented" is a special treatment for really, really old Friendica versions
$serverret = Network::curl($server_url."/api/statusnet/version.json"); $curlResult = Network::curl($server_url."/api/statusnet/version.json");
if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
$platform = "StatusNet"; $platform = "StatusNet";
// Remove junk that some GNU Social servers return // Remove junk that some GNU Social servers return
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]); $version = str_replace(chr(239).chr(187).chr(191), "", $curlResult->getBody());
$version = trim($version, '"'); $version = trim($version, '"');
$network = Protocol::OSTATUS; $network = Protocol::OSTATUS;
} }
// Test for GNU Social // Test for GNU Social
$serverret = Network::curl($server_url."/api/gnusocial/version.json"); $curlResult = Network::curl($server_url."/api/gnusocial/version.json");
if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
$platform = "GNU Social"; $platform = "GNU Social";
// Remove junk that some GNU Social servers return // Remove junk that some GNU Social servers return
$version = str_replace(chr(239) . chr(187) . chr(191), "", $serverret["body"]); $version = str_replace(chr(239) . chr(187) . chr(191), "", $curlResult->getBody());
$version = trim($version, '"'); $version = trim($version, '"');
$network = Protocol::OSTATUS; $network = Protocol::OSTATUS;
} }
// Test for Mastodon // Test for Mastodon
$orig_version = $version; $orig_version = $version;
$serverret = Network::curl($server_url . "/api/v1/instance"); $curlResult = Network::curl($server_url . "/api/v1/instance");
if ($serverret["success"] && ($serverret["body"] != '')) { if ($curlResult->isSuccess() && ($curlResult->getBody() != '')) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['version'])) { if (isset($data['version'])) {
$platform = "Mastodon"; $platform = "Mastodon";
@ -1176,10 +1176,10 @@ class PortableContact
if (!$failure) { if (!$failure) {
// Test for Hubzilla and Red // Test for Hubzilla and Red
$serverret = Network::curl($server_url . "/siteinfo.json"); $curlResult = Network::curl($server_url . "/siteinfo.json");
if ($serverret["success"]) { if ($curlResult->isSuccess()) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['url'])) { if (isset($data['url'])) {
$platform = $data['platform']; $platform = $data['platform'];
@ -1213,10 +1213,10 @@ class PortableContact
} }
} else { } else {
// Test for Hubzilla, Redmatrix or Friendica // Test for Hubzilla, Redmatrix or Friendica
$serverret = Network::curl($server_url."/api/statusnet/config.json"); $curlResult = Network::curl($server_url."/api/statusnet/config.json");
if ($serverret["success"]) { if ($curlResult->isSuccess()) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['site']['server'])) { if (isset($data['site']['server'])) {
if (isset($data['site']['platform'])) { if (isset($data['site']['platform'])) {
@ -1286,10 +1286,10 @@ class PortableContact
// Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
if (!$failure) { if (!$failure) {
$serverret = Network::curl($server_url . "/statistics.json"); $curlResult = Network::curl($server_url . "/statistics.json");
if ($serverret["success"]) { if ($curlResult->isSuccess()) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['version'])) { if (isset($data['version'])) {
$version = $data['version']; $version = $data['version'];
@ -1350,14 +1350,14 @@ class PortableContact
// Check for noscrape // Check for noscrape
// Friendica servers could be detected as OStatus servers // Friendica servers could be detected as OStatus servers
if (!$failure && in_array($network, [Protocol::DFRN, Protocol::OSTATUS])) { if (!$failure && in_array($network, [Protocol::DFRN, Protocol::OSTATUS])) {
$serverret = Network::curl($server_url . "/friendica/json"); $curlResult = Network::curl($server_url . "/friendica/json");
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
$serverret = Network::curl($server_url . "/friendika/json"); $curlResult = Network::curl($server_url . "/friendika/json");
} }
if ($serverret["success"]) { if ($curlResult->isSuccess()) {
$data = json_decode($serverret["body"], true); $data = json_decode($curlResult->getBody(), true);
if (isset($data['version'])) { if (isset($data['version'])) {
$network = Protocol::DFRN; $network = Protocol::DFRN;
@ -1442,13 +1442,13 @@ class PortableContact
{ {
logger("Discover relay data for server " . $server_url, LOGGER_DEBUG); logger("Discover relay data for server " . $server_url, LOGGER_DEBUG);
$serverret = Network::curl($server_url . "/.well-known/x-social-relay"); $curlResult = Network::curl($server_url . "/.well-known/x-social-relay");
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return; return;
} }
$data = json_decode($serverret['body'], true); $data = json_decode($curlResult->getBody(), true);
if (!is_array($data)) { if (!is_array($data)) {
return; return;
@ -1538,13 +1538,13 @@ class PortableContact
*/ */
private static function fetchServerlist($poco) private static function fetchServerlist($poco)
{ {
$serverret = Network::curl($poco . "/@server"); $curlResult = Network::curl($poco . "/@server");
if (!$serverret["success"]) { if (!$curlResult->isSuccess()) {
return; return;
} }
$serverlist = json_decode($serverret['body'], true); $serverlist = json_decode($curlResult->getBody(), true);
if (!is_array($serverlist)) { if (!is_array($serverlist)) {
return; return;
@ -1575,10 +1575,10 @@ class PortableContact
} }
// Discover Friendica, Hubzilla and Diaspora servers // Discover Friendica, Hubzilla and Diaspora servers
$serverdata = Network::fetchUrl("http://the-federation.info/pods.json"); $curlResult = Network::fetchUrl("http://the-federation.info/pods.json");
if (!empty($serverdata)) { if (!empty($curlResult)) {
$servers = json_decode($serverdata, true); $servers = json_decode($curlResult, true);
if (!empty($servers['pods'])) { if (!empty($servers['pods'])) {
foreach ($servers['pods'] as $server) { foreach ($servers['pods'] as $server) {
@ -1594,10 +1594,10 @@ class PortableContact
if (!empty($accesstoken)) { if (!empty($accesstoken)) {
$api = 'https://instances.social/api/1.0/instances/list?count=0'; $api = 'https://instances.social/api/1.0/instances/list?count=0';
$header = ['Authorization: Bearer '.$accesstoken]; $header = ['Authorization: Bearer '.$accesstoken];
$serverdata = Network::curl($api, false, $redirects, ['headers' => $header]); $curlResult = Network::curl($api, false, $redirects, ['headers' => $header]);
if ($serverdata['success']) { if ($curlResult->isSuccess()) {
$servers = json_decode($serverdata['body'], true); $servers = json_decode($curlResult->getBody(), true);
foreach ($servers['instances'] as $server) { foreach ($servers['instances'] as $server) {
$url = (is_null($server['https_score']) ? 'http' : 'https') . '://' . $server['name']; $url = (is_null($server['https_score']) ? 'http' : 'https') . '://' . $server['name'];
@ -1613,9 +1613,9 @@ class PortableContact
//if (!Config::get('system','ostatus_disabled')) { //if (!Config::get('system','ostatus_disabled')) {
// $serverdata = "http://gstools.org/api/get_open_instances/"; // $serverdata = "http://gstools.org/api/get_open_instances/";
// $result = Network::curl($serverdata); // $curlResult = Network::curl($serverdata);
// if ($result["success"]) { // if ($curlResult->isSuccess()) {
// $servers = json_decode($result["body"], true); // $servers = json_decode($result->getBody(), true);
// foreach($servers['data'] as $server) // foreach($servers['data'] as $server)
// self::checkServer($server['instance_address']); // self::checkServer($server['instance_address']);
@ -1643,10 +1643,10 @@ class PortableContact
logger("Fetch all users from the server " . $server["url"], LOGGER_DEBUG); logger("Fetch all users from the server " . $server["url"], LOGGER_DEBUG);
$retdata = Network::curl($url); $curlResult = Network::curl($url);
if ($retdata["success"] && !empty($retdata["body"])) { if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
$data = json_decode($retdata["body"], true); $data = json_decode($curlResult->getBody(), true);
if (!empty($data)) { if (!empty($data)) {
self::discoverServer($data, 2); self::discoverServer($data, 2);
@ -1666,11 +1666,11 @@ class PortableContact
$success = false; $success = false;
$retdata = Network::curl($url); $curlResult = Network::curl($url);
if ($retdata["success"] && !empty($retdata["body"])) { if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
logger("Fetch all global contacts from the server " . $server["nurl"], LOGGER_DEBUG); logger("Fetch all global contacts from the server " . $server["nurl"], LOGGER_DEBUG);
$data = json_decode($retdata["body"], true); $data = json_decode($curlResult->getBody(), true);
if (!empty($data)) { if (!empty($data)) {
$success = self::discoverServer($data); $success = self::discoverServer($data);
@ -1766,10 +1766,10 @@ class PortableContact
// Fetch all contacts from a given user from the other server // Fetch all contacts from a given user from the other server
$url = $server['poco'] . '/' . $username . '/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation'; $url = $server['poco'] . '/' . $username . '/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation';
$retdata = Network::curl($url); $curlResult = Network::curl($url);
if (!empty($retdata['success'])) { if ($curlResult->isSuccess()) {
$data = json_decode($retdata["body"], true); $data = json_decode($curlResult["body"], true);
if (!empty($data)) { if (!empty($data)) {
self::discoverServer($data, 3); self::discoverServer($data, 3);

View file

@ -179,17 +179,17 @@ class ExAuth
$url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user; $url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user;
$data = Network::curl($url); $curlResult = Network::curl($url);
if (!is_array($data)) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
if ($data['return_code'] != '200') { if ($curlResult->getReturnCode() != 200) {
return false; return false;
} }
$json = @json_decode($data['body']); $json = @json_decode($curlResult->getBody());
if (!is_object($json)) { if (!is_object($json)) {
return false; return false;
} }

View file

@ -13,25 +13,6 @@ use DomXPath;
class Network class Network
{ {
/**
* @var Curl The latest Curl output
*/
private static $curl;
/**
* Returns the latest Curl output
*
* @return Curl The latest Curl output
*/
public static function getCurl()
{
if (empty(self::$curl)) {
self::$curl = new Curl();
}
return self::$curl;
}
/** /**
* Curl wrapper * Curl wrapper
* *
@ -54,7 +35,7 @@ class Network
{ {
$ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar); $ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar);
return $ret['body']; return $ret->getBody();
} }
/** /**
@ -72,7 +53,7 @@ class Network
* @param string $accept_content supply Accept: header with 'accept_content' as the value * @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file * @param string $cookiejar Path to cookie jar file
* *
* @return array With all relevant information, 'body' contains the actual fetched content. * @return Curl With all relevant information, 'body' contains the actual fetched content.
*/ */
public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '') public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
{ {
@ -102,12 +83,7 @@ class Network
* 'nobody' => only return the header * 'nobody' => only return the header
* 'cookiejar' => path to cookie jar file * 'cookiejar' => path to cookie jar file
* *
* @return array an assoziative array with: * @return Curl
* int 'return_code' => HTTP return code or 0 if timeout or failure
* boolean 'success' => boolean true (if HTTP 2xx result) or false
* string 'redirect_url' => in case of redirect, content was finally retrieved from this URL
* string 'header' => HTTP headers
* string 'body' => fetched content
*/ */
public static function curl($url, $binary = false, &$redirects = 0, $opts = []) public static function curl($url, $binary = false, &$redirects = 0, $opts = [])
{ {
@ -120,24 +96,24 @@ class Network
$parts = parse_url($url); $parts = parse_url($url);
$path_parts = explode('/', defaults($parts, 'path', '')); $path_parts = explode('/', defaults($parts, 'path', ''));
foreach ($path_parts as $part) { foreach ($path_parts as $part) {
if (strlen($part) <> mb_strlen($part)) { if (strlen($part) <> mb_strlen($part)) {
$parts2[] = rawurlencode($part); $parts2[] = rawurlencode($part);
} else { } else {
$parts2[] = $part; $parts2[] = $part;
} }
} }
$parts['path'] = implode('/', $parts2); $parts['path'] = implode('/', $parts2);
$url = self::unparseURL($parts); $url = self::unparseURL($parts);
if (self::isUrlBlocked($url)) { if (self::isUrlBlocked($url)) {
logger('domain of ' . $url . ' is blocked', LOGGER_DATA); logger('domain of ' . $url . ' is blocked', LOGGER_DATA);
return $ret; return Curl::createErrorCurl($url);
} }
$ch = @curl_init($url); $ch = @curl_init($url);
if (($redirects > 8) || (!$ch)) { if (($redirects > 8) || (!$ch)) {
return $ret; return Curl::createErrorCurl($url);
} }
@curl_setopt($ch, CURLOPT_HEADER, true); @curl_setopt($ch, CURLOPT_HEADER, true);
@ -236,87 +212,20 @@ class Network
logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO); logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO);
} }
$ret['errno'] = curl_errno($ch); $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
$base = $s; if ($curlResponse->isRedirectUrl()) {
$ret['info'] = $curl_info; $redirects++;
logger('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
$http_code = $curl_info['http_code']; @curl_close($ch);
return self::curl($curlResponse->getRedirectUrl(), $binary, $redirects, $opts);
logger($url . ': ' . $http_code . " " . $s, LOGGER_DATA);
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
$chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
$header .= $chunk;
$base = substr($base, strlen($chunk));
}
self::$curl = new Curl($http_code, (isset($curl_info['content_type']) ? $curl_info['content_type'] : ''), $header);
if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
$new_location_info = @parse_url($curl_info['redirect_url']);
$old_location_info = @parse_url($curl_info['url']);
$newurl = $curl_info['redirect_url'];
if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
$newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
}
$matches = [];
if (preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches)) {
$newurl = trim(array_pop($matches));
}
if (strpos($newurl, '/') === 0) {
$newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl;
}
$old_location_query = @parse_url($url, PHP_URL_QUERY);
if ($old_location_query != '') {
$newurl .= '?' . $old_location_query;
}
if (filter_var($newurl, FILTER_VALIDATE_URL)) {
$redirects++;
@curl_close($ch);
return self::curl($newurl, $binary, $redirects, $opts);
}
}
self::$curl->setCode($http_code);
if (isset($curl_info['content_type'])) {
self::$curl->setContentType($curl_info['content_type']);
}
$rc = intval($http_code);
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
$ret['redirect_url'] = $url;
if (!$ret['success']) {
$ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
logger('error: '.$url.': '.$ret['return_code'].' - '.$ret['error'], LOGGER_DEBUG);
logger('debug: '.print_r($curl_info, true), LOGGER_DATA);
}
$ret['body'] = substr($s, strlen($header));
$ret['header'] = $header;
if (x($opts, 'debug')) {
$ret['debug'] = $curl_info;
} }
@curl_close($ch); @curl_close($ch);
$a->saveTimestamp($stamp1, 'network'); $a->saveTimestamp($stamp1, 'network');
return($ret); return $curlResponse;
} }
/** /**
@ -328,7 +237,7 @@ class Network
* @param integer $redirects Recursion counter for internal use - default = 0 * @param integer $redirects Recursion counter for internal use - default = 0
* @param integer $timeout The timeout in seconds, default system config value or 60 seconds * @param integer $timeout The timeout in seconds, default system config value or 60 seconds
* *
* @return string The content * @return Curl The content
*/ */
public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0) public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
{ {
@ -336,14 +245,14 @@ class Network
if (self::isUrlBlocked($url)) { if (self::isUrlBlocked($url)) {
logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA); logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA);
return false; return Curl::createErrorCurl($url);
} }
$a = get_app(); $a = get_app();
$ch = curl_init($url); $ch = curl_init($url);
if (($redirects > 8) || (!$ch)) { if (($redirects > 8) || (!$ch)) {
return false; return Curl::createErrorCurl($url);
} }
logger('post_url: start ' . $url, LOGGER_DATA); logger('post_url: start ' . $url, LOGGER_DATA);
@ -397,8 +306,6 @@ class Network
} }
} }
self::getCurl()->setCode(0);
// don't let curl abort the entire application // don't let curl abort the entire application
// if it throws any errors. // if it throws any errors.
@ -406,53 +313,23 @@ class Network
$base = $s; $base = $s;
$curl_info = curl_getinfo($ch); $curl_info = curl_getinfo($ch);
$http_code = $curl_info['http_code'];
logger('post_url: result ' . $http_code . ' - ' . $url, LOGGER_DATA); $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
$header = ''; if ($curlResponse->isRedirectUrl()) {
$redirects++;
// Pull out multiple headers, e.g. proxy and continuation headers logger('post_url: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
// allow for HTTP/2.x without fixing code curl_close($ch);
return self::post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
$chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
$header .= $chunk;
$base = substr($base, strlen($chunk));
} }
if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
$matches = [];
$new_location_info = @parse_url($curl_info['redirect_url']);
$old_location_info = @parse_url($curl_info['url']);
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$newurl = trim(array_pop($matches));
if (strpos($newurl, '/') === 0) {
$newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl;
}
if (filter_var($newurl, FILTER_VALIDATE_URL)) {
$redirects++;
logger('post_url: redirect ' . $url . ' to ' . $newurl);
return self::post($newurl, $params, $headers, $redirects, $timeout);
}
}
self::getCurl()->setCode($http_code);
$body = substr($s, strlen($header));
self::getCurl()->setHeaders($header);
curl_close($ch); curl_close($ch);
$a->saveTimestamp($stamp1, 'network'); $a->saveTimestamp($stamp1, 'network');
logger('post_url: end ' . $url, LOGGER_DATA); logger('post_url: end ' . $url, LOGGER_DATA);
return $body; return $curlResponse;
} }
/** /**

View file

@ -135,23 +135,23 @@ class ParseUrl
$siteinfo['url'] = $url; $siteinfo['url'] = $url;
$siteinfo['type'] = 'link'; $siteinfo['type'] = 'link';
$data = Network::curl($url); $curlResult = Network::curl($url);
if (!$data['success']) { if (!$curlResult->isSuccess()) {
return $siteinfo; return $siteinfo;
} }
// If the file is too large then exit // If the file is too large then exit
if ($data['info']['download_content_length'] > 1000000) { if ($curlResult->getInfo()['download_content_length'] > 1000000) {
return $siteinfo; return $siteinfo;
} }
// If it isn't a HTML file then exit // If it isn't a HTML file then exit
if (($data['info']['content_type'] != '') && !strstr(strtolower($data['info']['content_type']), 'html')) { if (($curlResult->getContentType() != '') && !strstr(strtolower($curlResult->getContentType()), 'html')) {
return $siteinfo; return $siteinfo;
} }
$header = $data['header']; $header = $curlResult->getHeader();
$body = $data['body']; $body = $curlResult->getBody();
if ($do_oembed) { if ($do_oembed) {
$oembed_data = OEmbed::fetchURL($url); $oembed_data = OEmbed::fetchURL($url);

View file

@ -274,12 +274,12 @@ class DiscoverPoCo
$url = "http://gstools.org/api/users_search/".urlencode($search); $url = "http://gstools.org/api/users_search/".urlencode($search);
$result = Network::curl($url); $curlResult = Network::curl($url);
if (!$result["success"]) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
$contacts = json_decode($result["body"]); $contacts = json_decode($curlResult->getBody());
if ($contacts->status == 'ERROR') { if ($contacts->status == 'ERROR') {
return false; return false;

View file

@ -185,18 +185,17 @@ class OnePoll
. '&type=data&last_update=' . $last_update . '&type=data&last_update=' . $last_update
. '&perm=' . $perm ; . '&perm=' . $perm ;
$ret = Network::curl($url); $curlResult = Network::curl($url);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if (!$curlResult->isSuccess() && ($curlResult->getErrorNumber() == CURLE_OPERATION_TIMEDOUT)) {
// set the last-update so we don't keep polling // set the last-update so we don't keep polling
DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]); DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]);
Contact::markForArchival($contact); Contact::markForArchival($contact);
return; return;
} }
$handshake_xml = $ret['body']; $handshake_xml = $curlResult->getBody();
$html_code = $curlResult->getReturnCode();
$html_code = Network::getCurl()->getCode();
logger('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); logger('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA);
@ -319,17 +318,17 @@ class OnePoll
} }
$cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-'); $cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-');
$ret = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]); $curlResult = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]);
unlink($cookiejar); unlink($cookiejar);
if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) { if (!$curlResult->isTimeout()) {
// set the last-update so we don't keep polling // set the last-update so we don't keep polling
DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]); DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]);
Contact::markForArchival($contact); Contact::markForArchival($contact);
return; return;
} }
$xml = $ret['body']; $xml = $curlResult->getBody();
} elseif ($contact['network'] === Protocol::MAIL) { } elseif ($contact['network'] === Protocol::MAIL) {
logger("Mail: Fetching for ".$contact['addr'], LOGGER_DEBUG); logger("Mail: Fetching for ".$contact['addr'], LOGGER_DEBUG);