Merge pull request #8911 from MrPetovan/task/curl_DI

Introduce "HTTPRequest" class
This commit is contained in:
Michael Vogel 2020-07-25 09:50:20 +02:00 committed by GitHub
commit 398e65d66b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 765 additions and 647 deletions

View file

@ -45,7 +45,6 @@ use Friendica\Model\User;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -224,7 +223,7 @@ function dfrn_confirm_post(App $a, $handsfree = null)
* *
*/ */
$res = Network::post($dfrn_confirm, $params, [], 120)->getBody(); $res = DI::httpRequest()->post($dfrn_confirm, $params, [], 120)->getBody();
Logger::log(' Confirm: received data: ' . $res, Logger::DATA); Logger::log(' Confirm: received data: ' . $res, Logger::DATA);

View file

@ -21,13 +21,12 @@
use Friendica\App; use Friendica\App;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Protocol\DFRN; use Friendica\Protocol\DFRN;
use Friendica\Protocol\OStatus; use Friendica\Protocol\OStatus;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -115,7 +114,7 @@ function dfrn_poll_init(App $a)
); );
if (DBA::isResult($r)) { if (DBA::isResult($r)) {
$s = Network::fetchUrl($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check'); $s = DI::httpRequest()->fetch($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check');
Logger::log("dfrn_poll: old profile returns " . $s, Logger::DATA); Logger::log("dfrn_poll: old profile returns " . $s, Logger::DATA);
@ -499,7 +498,7 @@ function dfrn_poll_content(App $a)
// URL reply // URL reply
if ($dfrn_version < 2.2) { if ($dfrn_version < 2.2) {
$s = Network::fetchUrl($r[0]['poll'] $s = DI::httpRequest()->fetch($r[0]['poll']
. '?dfrn_id=' . $encrypted_id . '?dfrn_id=' . $encrypted_id
. '&type=profile-check' . '&type=profile-check'
. '&dfrn_version=' . DFRN_PROTOCOL_VERSION . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
@ -507,7 +506,7 @@ function dfrn_poll_content(App $a)
. '&sec=' . $sec . '&sec=' . $sec
); );
} else { } else {
$s = Network::post($r[0]['poll'], [ $s = DI::httpRequest()->post($r[0]['poll'], [
'dfrn_id' => $encrypted_id, 'dfrn_id' => $encrypted_id,
'type' => 'profile-check', 'type' => 'profile-check',
'dfrn_version' => DFRN_PROTOCOL_VERSION, 'dfrn_version' => DFRN_PROTOCOL_VERSION,

View file

@ -29,8 +29,8 @@ use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Search; use Friendica\Core\Search;
use Friendica\Core\System;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
@ -203,7 +203,7 @@ function dfrn_request_post(App $a)
} }
if (!empty($dfrn_request) && strlen($confirm_key)) { if (!empty($dfrn_request) && strlen($confirm_key)) {
Network::fetchUrl($dfrn_request . '?confirm_key=' . $confirm_key); DI::httpRequest()->fetch($dfrn_request . '?confirm_key=' . $confirm_key);
} }
// (ignore reply, nothing we can do it failed) // (ignore reply, nothing we can do it failed)

View file

@ -27,7 +27,6 @@ use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Profile; use Friendica\Model\Profile;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Proxy as ProxyUtils;
/** /**
@ -76,7 +75,7 @@ function match_content(App $a)
$host = DI::baseUrl(); $host = DI::baseUrl();
} }
$msearch_json = Network::post($host . '/msearch', $params)->getBody(); $msearch_json = DI::httpRequest()->post($host . '/msearch', $params)->getBody();
$msearch = json_decode($msearch_json); $msearch = json_decode($msearch_json);

View file

@ -23,7 +23,6 @@ use Friendica\App;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Security\Login; use Friendica\Module\Security\Login;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
function oexchange_init(App $a) { function oexchange_init(App $a) {
@ -57,7 +56,7 @@ function oexchange_content(App $a) {
$tags = ((!empty($_REQUEST['tags'])) $tags = ((!empty($_REQUEST['tags']))
? '&tags=' . urlencode(Strings::escapeTags(trim($_REQUEST['tags']))) : ''); ? '&tags=' . urlencode(Strings::escapeTags(trim($_REQUEST['tags']))) : '');
$s = Network::fetchUrl(DI::baseUrl() . '/parse_url?url=' . $url . $title . $description . $tags); $s = DI::httpRequest()->fetch(DI::baseUrl() . '/parse_url?url=' . $url . $title . $description . $tags);
if (!strlen($s)) { if (!strlen($s)) {
return; return;

View file

@ -23,7 +23,6 @@ use Friendica\App;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Util\Network;
function ostatus_subscribe_content(App $a) function ostatus_subscribe_content(App $a)
{ {
@ -55,7 +54,7 @@ function ostatus_subscribe_content(App $a)
$api = $contact['baseurl'] . '/api/'; $api = $contact['baseurl'] . '/api/';
// Fetching friends // Fetching friends
$curlResult = Network::curl($api . 'statuses/friends.json?screen_name=' . $contact['nick']); $curlResult = DI::httpRequest()->get($api . 'statuses/friends.json?screen_name=' . $contact['nick']);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
DI::pConfig()->delete($uid, 'ostatus', 'legacy_contact'); DI::pConfig()->delete($uid, 'ostatus', 'legacy_contact');

View file

@ -28,7 +28,7 @@ use Friendica\Content\PageInfo;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Util\Network; use Friendica\DI;
use Friendica\Util\ParseUrl; use Friendica\Util\ParseUrl;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -85,7 +85,7 @@ function parse_url_content(App $a)
// Check if the URL is an image, video or audio file. If so format // Check if the URL is an image, video or audio file. If so format
// the URL with the corresponding BBCode media tag // the URL with the corresponding BBCode media tag
// Fetch the header of the URL // Fetch the header of the URL
$curlResponse = Network::curl($url, false, ['novalidate' => true, 'nobody' => true]); $curlResponse = DI::httpRequest()->get($url, false, ['novalidate' => true, 'nobody' => true]);
if ($curlResponse->isSuccess()) { if ($curlResponse->isSuccess()) {
// Convert the header fields into an array // Convert the header fields into an array

View file

@ -24,7 +24,6 @@ use Friendica\Core\Logger;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\PushSubscriber; use Friendica\Model\PushSubscriber;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
function post_var($name) { function post_var($name) {
@ -126,7 +125,7 @@ function pubsubhubbub_init(App $a) {
$hub_callback = rtrim($hub_callback, ' ?&#'); $hub_callback = rtrim($hub_callback, ' ?&#');
$separator = parse_url($hub_callback, PHP_URL_QUERY) === null ? '?' : '&'; $separator = parse_url($hub_callback, PHP_URL_QUERY) === null ? '?' : '&';
$fetchResult = Network::fetchUrlFull($hub_callback . $separator . $params); $fetchResult = DI::httpRequest()->fetchFull($hub_callback . $separator . $params);
$body = $fetchResult->getBody(); $body = $fetchResult->getBody();
$ret = $fetchResult->getReturnCode(); $ret = $fetchResult->getReturnCode();

View file

@ -27,7 +27,6 @@ use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Profile; use Friendica\Model\Profile;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
function redir_init(App $a) { function redir_init(App $a) {
@ -171,7 +170,7 @@ function redir_magic($a, $cid, $url)
} }
// Test for magic auth on the target system // Test for magic auth on the target system
$serverret = Network::curl($basepath . '/magic'); $serverret = DI::httpRequest()->get($basepath . '/magic');
if ($serverret->isSuccess()) { if ($serverret->isSuccess()) {
$separator = strpos($target_url, '?') ? '&' : '?'; $separator = strpos($target_url, '?') ? '&' : '?';
$target_url .= $separator . 'zrl=' . urlencode($visitor) . '&addr=' . urlencode($contact_url); $target_url .= $separator . 'zrl=' . urlencode($visitor) . '&addr=' . urlencode($contact_url);

View file

@ -240,22 +240,6 @@ class App
} }
} }
/**
* Returns the current UserAgent as a String
*
* @return string the UserAgent as a String
* @throws HTTPException\InternalServerErrorException
*/
public function getUserAgent()
{
return
FRIENDICA_PLATFORM . " '" .
FRIENDICA_CODENAME . "' " .
FRIENDICA_VERSION . '-' .
DB_UPDATE_VERSION . '; ' .
$this->baseURL->get();
}
/** /**
* Returns the current theme name. May be overriden by the mobile theme name. * Returns the current theme name. May be overriden by the mobile theme name.
* *

View file

@ -95,7 +95,7 @@ class OEmbed
if (!in_array($ext, $noexts)) { if (!in_array($ext, $noexts)) {
// try oembed autodiscovery // try oembed autodiscovery
$html_text = Network::fetchUrl($embedurl, false, 15, 'text/*'); $html_text = DI::httpRequest()->fetch($embedurl, false, 15, 'text/*');
if ($html_text) { if ($html_text) {
$dom = @DOMDocument::loadHTML($html_text); $dom = @DOMDocument::loadHTML($html_text);
if ($dom) { if ($dom) {
@ -103,14 +103,14 @@ class OEmbed
$entries = $xpath->query("//link[@type='application/json+oembed']"); $entries = $xpath->query("//link[@type='application/json+oembed']");
foreach ($entries as $e) { foreach ($entries as $e) {
$href = $e->getAttributeNode('href')->nodeValue; $href = $e->getAttributeNode('href')->nodeValue;
$json_string = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); $json_string = DI::httpRequest()->fetch($href . '&maxwidth=' . $a->videowidth);
break; break;
} }
$entries = $xpath->query("//link[@type='text/json+oembed']"); $entries = $xpath->query("//link[@type='text/json+oembed']");
foreach ($entries as $e) { foreach ($entries as $e) {
$href = $e->getAttributeNode('href')->nodeValue; $href = $e->getAttributeNode('href')->nodeValue;
$json_string = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); $json_string = DI::httpRequest()->fetch($href . '&maxwidth=' . $a->videowidth);
break; break;
} }
} }

View file

@ -38,12 +38,10 @@ use Friendica\Model\Contact;
use Friendica\Model\Event; use Friendica\Model\Event;
use Friendica\Model\Photo; use Friendica\Model\Photo;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Network\Probe;
use Friendica\Object\Image; use Friendica\Object\Image;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
use Friendica\Util\Images; use Friendica\Util\Images;
use Friendica\Util\Map; use Friendica\Util\Map;
use Friendica\Util\Network;
use Friendica\Util\ParseUrl; use Friendica\Util\ParseUrl;
use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -487,7 +485,7 @@ class BBCode
continue; continue;
} }
$curlResult = Network::curl($mtch[1], true); $curlResult = DI::httpRequest()->get($mtch[1], true);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
continue; continue;
} }
@ -1096,7 +1094,7 @@ class BBCode
$ch = @curl_init($match[1]); $ch = @curl_init($match[1]);
@curl_setopt($ch, CURLOPT_NOBODY, true); @curl_setopt($ch, CURLOPT_NOBODY, true);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent()); @curl_setopt($ch, CURLOPT_USERAGENT, DI::httpRequest()->getUserAgent());
@curl_exec($ch); @curl_exec($ch);
$curl_info = @curl_getinfo($ch); $curl_info = @curl_getinfo($ch);
@ -1108,7 +1106,7 @@ class BBCode
$text = "[url=" . $match[2] . ']' . $match[2] . "[/url]"; $text = "[url=" . $match[2] . ']' . $match[2] . "[/url]";
// if its not a picture then look if its a page that contains a picture link // if its not a picture then look if its a page that contains a picture link
$body = Network::fetchUrl($match[1]); $body = DI::httpRequest()->fetch($match[1]);
$doc = new DOMDocument(); $doc = new DOMDocument();
@$doc->loadHTML($body); @$doc->loadHTML($body);
@ -1170,7 +1168,7 @@ class BBCode
$ch = @curl_init($match[1]); $ch = @curl_init($match[1]);
@curl_setopt($ch, CURLOPT_NOBODY, true); @curl_setopt($ch, CURLOPT_NOBODY, true);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent()); @curl_setopt($ch, CURLOPT_USERAGENT, DI::httpRequest()->getUserAgent());
@curl_exec($ch); @curl_exec($ch);
$curl_info = @curl_getinfo($ch); $curl_info = @curl_getinfo($ch);
@ -1187,7 +1185,7 @@ class BBCode
} }
// if its not a picture then look if its a page that contains a picture link // if its not a picture then look if its a page that contains a picture link
$body = Network::fetchUrl($match[1]); $body = DI::httpRequest()->fetch($match[1]);
$doc = new DOMDocument(); $doc = new DOMDocument();
@$doc->loadHTML($body); @$doc->loadHTML($body);

View file

@ -28,7 +28,6 @@ use Friendica\Database\Database;
use Friendica\Database\DBStructure; use Friendica\Database\DBStructure;
use Friendica\DI; use Friendica\DI;
use Friendica\Util\Images; use Friendica\Util\Images;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
/** /**
@ -548,11 +547,11 @@ class Installer
$help = ""; $help = "";
$error_msg = ""; $error_msg = "";
if (function_exists('curl_init')) { if (function_exists('curl_init')) {
$fetchResult = Network::fetchUrlFull($baseurl . "/install/testrewrite"); $fetchResult = DI::httpRequest()->fetchFull($baseurl . "/install/testrewrite");
$url = Strings::normaliseLink($baseurl . "/install/testrewrite"); $url = Strings::normaliseLink($baseurl . "/install/testrewrite");
if ($fetchResult->getReturnCode() != 204) { if ($fetchResult->getReturnCode() != 204) {
$fetchResult = Network::fetchUrlFull($url); $fetchResult = DI::httpRequest()->fetchFull($url);
} }
if ($fetchResult->getReturnCode() != 204) { if ($fetchResult->getReturnCode() != 204) {

View file

@ -21,7 +21,7 @@
namespace Friendica\Core; namespace Friendica\Core;
use Friendica\Util\Network; use Friendica\DI;
/** /**
* Manage compatibility with federated networks * Manage compatibility with federated networks
@ -91,7 +91,6 @@ class Protocol
* @param string $profile_url * @param string $profile_url
* @param array $matches preg_match return array: [0] => Full match [1] => hostname [2] => username * @param array $matches preg_match return array: [0] => Full match [1] => hostname [2] => username
* @return string * @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function matchByProfileUrl($profile_url, &$matches = []) public static function matchByProfileUrl($profile_url, &$matches = [])
{ {
@ -123,7 +122,7 @@ class Protocol
if (preg_match('=https?://(.*)/user/(.*)=ism', $profile_url, $matches)) { if (preg_match('=https?://(.*)/user/(.*)=ism', $profile_url, $matches)) {
$statusnet_host = $matches[1]; $statusnet_host = $matches[1];
$statusnet_user = $matches[2]; $statusnet_user = $matches[2];
$UserData = Network::fetchUrl('http://' . $statusnet_host . '/api/users/show.json?user_id=' . $statusnet_user); $UserData = DI::httpRequest()->fetch('http://' . $statusnet_host . '/api/users/show.json?user_id=' . $statusnet_user);
$user = json_decode($UserData); $user = json_decode($UserData);
if ($user) { if ($user) {
$matches[2] = $user->screen_name; $matches[2] = $user->screen_name;

View file

@ -123,7 +123,7 @@ class Search
$searchUrl .= '&page=' . $page; $searchUrl .= '&page=' . $page;
} }
$resultJson = Network::fetchUrl($searchUrl, false, 0, 'application/json'); $resultJson = DI::httpRequest()->fetch($searchUrl, false, 0, 'application/json');
$results = json_decode($resultJson, true); $results = json_decode($resultJson, true);
@ -284,7 +284,7 @@ class Search
$return = GContact::searchByName($search, $mode); $return = GContact::searchByName($search, $mode);
} else { } else {
$p = $page > 1 ? 'p=' . $page : ''; $p = $page > 1 ? 'p=' . $page : '';
$curlResult = Network::curl(self::getGlobalDirectory() . '/search/people?' . $p . '&q=' . urlencode($search), false, ['accept_content' => 'application/json']); $curlResult = DI::httpRequest()->get(self::getGlobalDirectory() . '/search/people?' . $p . '&q=' . urlencode($search), false, ['accept_content' => 'application/json']);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$searchResult = json_decode($curlResult->getBody(), true); $searchResult = json_decode($curlResult->getBody(), true);
if (!empty($searchResult['profiles'])) { if (!empty($searchResult['profiles'])) {

View file

@ -26,7 +26,6 @@ use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Process; use Friendica\Model\Process;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
/** /**
* Contains the class for the worker background job processing * Contains the class for the worker background job processing
@ -997,7 +996,7 @@ class Worker
} }
$url = DI::baseUrl() . '/worker'; $url = DI::baseUrl() . '/worker';
Network::fetchUrl($url, false, 1); DI::httpRequest()->fetch($url, false, 1);
} }
/** /**

View file

@ -323,6 +323,18 @@ abstract class DI
return self::$dice->create(Model\Storage\IStorage::class); return self::$dice->create(Model\Storage\IStorage::class);
} }
//
// "Network" namespace
//
/**
* @return Network\IHTTPRequest
*/
public static function httpRequest()
{
return self::$dice->create(Network\IHTTPRequest::class);
}
// //
// "Repository" namespace // "Repository" namespace
// //

View file

@ -24,15 +24,13 @@ namespace Friendica\Model;
use Friendica\Content\Text\HTML; use Friendica\Content\Text\HTML;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Network\Probe; use Friendica\Network\Probe;
use Friendica\Protocol\ActivityNamespace; use Friendica\Protocol\ActivityNamespace;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
use Friendica\Util\Network;
use Friendica\Util\JsonLD;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings; use Friendica\Util\JsonLD;
use Friendica\Util\Network;
class APContact class APContact
{ {

View file

@ -26,8 +26,8 @@ use DOMXPath;
use Exception; use Exception;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Core\Search; use Friendica\Core\Search;
use Friendica\Core\System;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
@ -537,7 +537,7 @@ class GContact
$done[] = DI::baseUrl() . '/poco'; $done[] = DI::baseUrl() . '/poco';
if (strlen(DI::config()->get('system', 'directory'))) { if (strlen(DI::config()->get('system', 'directory'))) {
$x = Network::fetchUrl(Search::getGlobalDirectory() . '/pubsites'); $x = DI::httpRequest()->fetch(Search::getGlobalDirectory() . '/pubsites');
if (!empty($x)) { if (!empty($x)) {
$j = json_decode($x); $j = json_decode($x);
if (!empty($j->entries)) { if (!empty($j->entries)) {
@ -845,7 +845,7 @@ class GContact
return false; return false;
} }
$curlResult = Network::curl($gserver['noscrape'] . '/' . $data['nick']); $curlResult = DI::httpRequest()->get($gserver['noscrape'] . '/' . $data['nick']);
if ($curlResult->isSuccess() && !empty($curlResult->getBody())) { if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
$noscrape = json_decode($curlResult->getBody(), true); $noscrape = json_decode($curlResult->getBody(), true);
@ -927,7 +927,7 @@ class GContact
private static function updateFromFeed(array $data) private static function updateFromFeed(array $data)
{ {
// Search for the newest entry in the feed // Search for the newest entry in the feed
$curlResult = Network::curl($data['poll']); $curlResult = DI::httpRequest()->get($data['poll']);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
$fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()]; $fields = ['failed' => true, 'last_failure' => DateTimeFormat::utcNow()];
DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]); DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($data['url'])]);
@ -1205,7 +1205,7 @@ class GContact
$url = $server . '/main/statistics'; $url = $server . '/main/statistics';
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
@ -1378,7 +1378,7 @@ class GContact
return; return;
} }
$curlResult = Network::curl($data['poco']); $curlResult = DI::httpRequest()->get($data['poco']);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
} }

View file

@ -23,20 +23,20 @@ namespace Friendica\Model;
use DOMDocument; use DOMDocument;
use DOMXPath; use DOMXPath;
use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Register; use Friendica\Module\Register;
use Friendica\Network\CurlResult; use Friendica\Network\CurlResult;
use Friendica\Util\Network; use Friendica\Protocol\Diaspora;
use Friendica\Protocol\PortableContact;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Protocol\PortableContact;
use Friendica\Protocol\Diaspora;
/** /**
* This class handles GServer related functions * This class handles GServer related functions
@ -309,7 +309,7 @@ class GServer
// When a nodeinfo is present, we don't need to dig further // When a nodeinfo is present, we don't need to dig further
$xrd_timeout = DI::config()->get('system', 'xrd_timeout'); $xrd_timeout = DI::config()->get('system', 'xrd_timeout');
$curlResult = Network::curl($url . '/.well-known/nodeinfo', false, ['timeout' => $xrd_timeout]); $curlResult = DI::httpRequest()->get($url . '/.well-known/nodeinfo', false, ['timeout' => $xrd_timeout]);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::setFailure($url); self::setFailure($url);
return false; return false;
@ -342,7 +342,7 @@ class GServer
$basedata = ['detection-method' => self::DETECT_MANUAL]; $basedata = ['detection-method' => self::DETECT_MANUAL];
} }
$curlResult = Network::curl($baseurl, false, ['timeout' => $xrd_timeout]); $curlResult = DI::httpRequest()->get($baseurl, false, ['timeout' => $xrd_timeout]);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$basedata = self::analyseRootHeader($curlResult, $basedata); $basedata = self::analyseRootHeader($curlResult, $basedata);
$basedata = self::analyseRootBody($curlResult, $basedata, $baseurl); $basedata = self::analyseRootBody($curlResult, $basedata, $baseurl);
@ -359,7 +359,7 @@ class GServer
// When the base path doesn't seem to contain a social network we try the complete path. // When the base path doesn't seem to contain a social network we try the complete path.
// Most detectable system have to be installed in the root directory. // Most detectable system have to be installed in the root directory.
// We checked the base to avoid false positives. // We checked the base to avoid false positives.
$curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout]); $curlResult = DI::httpRequest()->get($url, false, ['timeout' => $xrd_timeout]);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$urldata = self::analyseRootHeader($curlResult, $serverdata); $urldata = self::analyseRootHeader($curlResult, $serverdata);
$urldata = self::analyseRootBody($curlResult, $urldata, $url); $urldata = self::analyseRootBody($curlResult, $urldata, $url);
@ -498,7 +498,7 @@ class GServer
{ {
Logger::info('Discover relay data', ['server' => $server_url]); Logger::info('Discover relay data', ['server' => $server_url]);
$curlResult = Network::curl($server_url . '/.well-known/x-social-relay'); $curlResult = DI::httpRequest()->get($server_url . '/.well-known/x-social-relay');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
} }
@ -579,7 +579,7 @@ class GServer
*/ */
private static function fetchStatistics(string $url) private static function fetchStatistics(string $url)
{ {
$curlResult = Network::curl($url . '/statistics.json'); $curlResult = DI::httpRequest()->get($url . '/statistics.json');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return []; return [];
} }
@ -689,7 +689,8 @@ class GServer
*/ */
private static function parseNodeinfo1(string $nodeinfo_url) private static function parseNodeinfo1(string $nodeinfo_url)
{ {
$curlResult = Network::curl($nodeinfo_url); $curlResult = DI::httpRequest()->get($nodeinfo_url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return []; return [];
} }
@ -765,7 +766,7 @@ class GServer
*/ */
private static function parseNodeinfo2(string $nodeinfo_url) private static function parseNodeinfo2(string $nodeinfo_url)
{ {
$curlResult = Network::curl($nodeinfo_url); $curlResult = DI::httpRequest()->get($nodeinfo_url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return []; return [];
} }
@ -842,7 +843,7 @@ class GServer
*/ */
private static function fetchSiteinfo(string $url, array $serverdata) private static function fetchSiteinfo(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/siteinfo.json'); $curlResult = DI::httpRequest()->get($url . '/siteinfo.json');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return $serverdata; return $serverdata;
} }
@ -911,7 +912,7 @@ class GServer
private static function validHostMeta(string $url) private static function validHostMeta(string $url)
{ {
$xrd_timeout = DI::config()->get('system', 'xrd_timeout'); $xrd_timeout = DI::config()->get('system', 'xrd_timeout');
$curlResult = Network::curl($url . '/.well-known/host-meta', false, ['timeout' => $xrd_timeout]); $curlResult = DI::httpRequest()->get($url . '/.well-known/host-meta', false, ['timeout' => $xrd_timeout]);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
@ -1007,7 +1008,7 @@ class GServer
{ {
$serverdata['poco'] = ''; $serverdata['poco'] = '';
$curlResult = Network::curl($url. '/poco'); $curlResult = DI::httpRequest()->get($url . '/poco');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return $serverdata; return $serverdata;
} }
@ -1037,7 +1038,7 @@ class GServer
*/ */
public static function checkMastodonDirectory(string $url, array $serverdata) public static function checkMastodonDirectory(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/api/v1/directory?limit=1'); $curlResult = DI::httpRequest()->get($url . '/api/v1/directory?limit=1');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return $serverdata; return $serverdata;
} }
@ -1064,7 +1065,8 @@ class GServer
*/ */
private static function detectNextcloud(string $url, array $serverdata) private static function detectNextcloud(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/status.php'); $curlResult = DI::httpRequest()->get($url . '/status.php');
if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
return $serverdata; return $serverdata;
} }
@ -1097,7 +1099,8 @@ class GServer
*/ */
private static function detectMastodonAlikes(string $url, array $serverdata) private static function detectMastodonAlikes(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/api/v1/instance'); $curlResult = DI::httpRequest()->get($url . '/api/v1/instance');
if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
return $serverdata; return $serverdata;
} }
@ -1162,7 +1165,7 @@ class GServer
*/ */
private static function detectHubzilla(string $url, array $serverdata) private static function detectHubzilla(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/api/statusnet/config.json'); $curlResult = DI::httpRequest()->get($url . '/api/statusnet/config.json');
if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
return $serverdata; return $serverdata;
} }
@ -1260,7 +1263,7 @@ class GServer
private static function detectGNUSocial(string $url, array $serverdata) private static function detectGNUSocial(string $url, array $serverdata)
{ {
// Test for GNU Social // Test for GNU Social
$curlResult = Network::curl($url . '/api/gnusocial/version.json'); $curlResult = DI::httpRequest()->get($url . '/api/gnusocial/version.json');
if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') && if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) { ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
$serverdata['platform'] = 'gnusocial'; $serverdata['platform'] = 'gnusocial';
@ -1278,7 +1281,7 @@ class GServer
} }
// Test for Statusnet // Test for Statusnet
$curlResult = Network::curl($url . '/api/statusnet/version.json'); $curlResult = DI::httpRequest()->get($url . '/api/statusnet/version.json');
if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') && if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) { ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
@ -1314,9 +1317,9 @@ class GServer
*/ */
private static function detectFriendica(string $url, array $serverdata) private static function detectFriendica(string $url, array $serverdata)
{ {
$curlResult = Network::curl($url . '/friendica/json'); $curlResult = DI::httpRequest()->get($url . '/friendica/json');
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
$curlResult = Network::curl($url . '/friendika/json'); $curlResult = DI::httpRequest()->get($url . '/friendika/json');
$friendika = true; $friendika = true;
$platform = 'Friendika'; $platform = 'Friendika';
} else { } else {
@ -1631,7 +1634,7 @@ class GServer
$protocols = ['activitypub', 'diaspora', 'dfrn', 'ostatus']; $protocols = ['activitypub', 'diaspora', 'dfrn', 'ostatus'];
foreach ($protocols as $protocol) { foreach ($protocols as $protocol) {
$query = '{nodes(protocol:"' . $protocol . '"){host}}'; $query = '{nodes(protocol:"' . $protocol . '"){host}}';
$curlResult = Network::fetchUrl('https://the-federation.info/graphql?query=' . urlencode($query)); $curlResult = DI::httpRequest()->fetch('https://the-federation.info/graphql?query=' . urlencode($query));
if (!empty($curlResult)) { if (!empty($curlResult)) {
$data = json_decode($curlResult, true); $data = json_decode($curlResult, true);
if (!empty($data['data']['nodes'])) { if (!empty($data['data']['nodes'])) {
@ -1649,7 +1652,8 @@ class GServer
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];
$curlResult = Network::curl($api, false, ['headers' => $header]); $curlResult = DI::httpRequest()->get($api, false, ['headers' => $header]);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$servers = json_decode($curlResult->getBody(), true); $servers = json_decode($curlResult->getBody(), true);

View file

@ -3682,7 +3682,7 @@ class Item
* *
* @return integer item id * @return integer item id
*/ */
public static function fetchByLink($uri, $uid = 0) public static function fetchByLink(string $uri, int $uid = 0)
{ {
$item_id = self::searchByLink($uri, $uid); $item_id = self::searchByLink($uri, $uid);
if (!empty($item_id)) { if (!empty($item_id)) {
@ -3735,7 +3735,7 @@ class Item
* *
* @return array item array with data from the original item * @return array item array with data from the original item
*/ */
public static function addShareDataFromOriginal($item) public static function addShareDataFromOriginal(array $item)
{ {
$shared = self::getShareArray($item); $shared = self::getShareArray($item);
if (empty($shared)) { if (empty($shared)) {
@ -3757,9 +3757,9 @@ class Item
} }
// Otherwhise try to find (and possibly fetch) the item via the link. This should work for Diaspora and ActivityPub posts // Otherwhise try to find (and possibly fetch) the item via the link. This should work for Diaspora and ActivityPub posts
$id = self::fetchByLink($shared['link'], $uid); $id = self::fetchByLink($shared['link'] ?? '', $uid);
if (empty($id)) { if (empty($id)) {
Logger::info('Original item not found', ['url' => $shared['link'], 'callstack' => System::callstack()]); Logger::info('Original item not found', ['url' => $shared['link'] ?? '', 'callstack' => System::callstack()]);
return $item; return $item;
} }

View file

@ -31,7 +31,6 @@ use Friendica\Model\Storage\SystemResource;
use Friendica\Object\Image; use Friendica\Object\Image;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Images; use Friendica\Util\Images;
use Friendica\Util\Network;
use Friendica\Util\Security; use Friendica\Util\Security;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -421,7 +420,7 @@ class Photo
$filename = basename($image_url); $filename = basename($image_url);
if (!empty($image_url)) { if (!empty($image_url)) {
$ret = Network::curl($image_url, true); $ret = DI::httpRequest()->get($image_url, true);
$img_str = $ret->getBody(); $img_str = $ret->getBody();
$type = $ret->getContentType(); $type = $ret->getContentType();
} else { } else {

View file

@ -737,7 +737,7 @@ class Profile
$magic_path = $basepath . '/magic' . '?owa=1&dest=' . $dest . '&' . $addr_request; $magic_path = $basepath . '/magic' . '?owa=1&dest=' . $dest . '&' . $addr_request;
// We have to check if the remote server does understand /magic without invoking something // We have to check if the remote server does understand /magic without invoking something
$serverret = Network::curl($basepath . '/magic'); $serverret = DI::httpRequest()->get($basepath . '/magic');
if ($serverret->isSuccess()) { if ($serverret->isSuccess()) {
Logger::log('Doing magic auth for visitor ' . $my_url . ' to ' . $magic_path, Logger::DEBUG); Logger::log('Doing magic auth for visitor ' . $my_url . ' to ' . $magic_path, Logger::DEBUG);
System::externalRedirect($magic_path); System::externalRedirect($magic_path);

View file

@ -823,7 +823,7 @@ class User
$photo_failure = false; $photo_failure = false;
$filename = basename($photo); $filename = basename($photo);
$curlResult = Network::curl($photo, true); $curlResult = DI::httpRequest()->get($photo, true);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$img_str = $curlResult->getBody(); $img_str = $curlResult->getBody();
$type = $curlResult->getContentType(); $type = $curlResult->getContentType();

View file

@ -31,12 +31,9 @@ use Friendica\Database\DBStructure;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Register; use Friendica\Model\Register;
use Friendica\Module\BaseAdmin; use Friendica\Module\BaseAdmin;
use Friendica\Module\Update\Profile;
use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Render\FriendicaSmarty;
use Friendica\Util\ConfigFileLoader; use Friendica\Util\ConfigFileLoader;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
class Summary extends BaseAdmin class Summary extends BaseAdmin
{ {
@ -249,7 +246,7 @@ class Summary extends BaseAdmin
private static function checkSelfHostMeta() private static function checkSelfHostMeta()
{ {
// 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
return Network::curl(DI::baseUrl()->get() . '/.well-known/host-meta')->isSuccess(); return DI::httpRequest()->get(DI::baseUrl()->get() . '/.well-known/host-meta')->isSuccess();
} }
} }

View file

@ -26,7 +26,6 @@ use Friendica\Core\Renderer;
use Friendica\DI; use Friendica\DI;
use Friendica\Model; use Friendica\Model;
use Friendica\Protocol; use Friendica\Protocol;
use Friendica\Util\Network;
/** /**
* Tests a given feed of a contact * Tests a given feed of a contact
@ -49,7 +48,7 @@ class Feed extends BaseModule
$contact = Model\Contact::getByURLForUser($url, local_user(), false); $contact = Model\Contact::getByURLForUser($url, local_user(), false);
$xml = Network::fetchUrl($contact['poll']); $xml = DI::httpRequest()->fetch($contact['poll']);
$import_result = Protocol\Feed::import($xml); $import_result = Protocol\Feed::import($xml);

View file

@ -28,7 +28,6 @@ use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
/** /**
@ -101,7 +100,7 @@ class Magic extends BaseModule
); );
// Try to get an authentication token from the other instance. // Try to get an authentication token from the other instance.
$curlResult = Network::curl($basepath . '/owa', false, ['headers' => $headers]); $curlResult = DI::httpRequest()->get($basepath . '/owa', false, ['headers' => $headers]);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$j = json_decode($curlResult->getBody(), true); $j = json_decode($curlResult->getBody(), true);

462
src/Network/HTTPRequest.php Normal file
View file

@ -0,0 +1,462 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU APGL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Network;
use DOMDocument;
use DomXPath;
use Friendica\App;
use Friendica\Core\Config\IConfig;
use Friendica\Core\System;
use Friendica\Util\Network;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/**
* Performs HTTP requests to a given URL
*/
class HTTPRequest implements IHTTPRequest
{
/** @var LoggerInterface */
private $logger;
/** @var Profiler */
private $profiler;
/** @var IConfig */
private $config;
/** @var string */
private $baseUrl;
public function __construct(LoggerInterface $logger, Profiler $profiler, IConfig $config, App\BaseURL $baseUrl)
{
$this->logger = $logger;
$this->profiler = $profiler;
$this->config = $config;
$this->baseUrl = $baseUrl->get();
}
/**
* {@inheritDoc}
*
* @param int $redirects The recursion counter for internal use - default 0
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function get(string $url, bool $binary = false, array $opts = [], int &$redirects = 0)
{
$stamp1 = microtime(true);
if (strlen($url) > 1000) {
$this->logger->debug('URL is longer than 1000 characters.', ['url' => $url, 'callstack' => System::callstack(20)]);
return CurlResult::createErrorCurl(substr($url, 0, 200));
}
$parts2 = [];
$parts = parse_url($url);
$path_parts = explode('/', $parts['path'] ?? '');
foreach ($path_parts as $part) {
if (strlen($part) <> mb_strlen($part)) {
$parts2[] = rawurlencode($part);
} else {
$parts2[] = $part;
}
}
$parts['path'] = implode('/', $parts2);
$url = Network::unparseURL($parts);
if (Network::isUrlBlocked($url)) {
$this->logger->info('Domain is blocked.', ['url' => $url]);
return CurlResult::createErrorCurl($url);
}
$ch = @curl_init($url);
if (($redirects > 8) || (!$ch)) {
return CurlResult::createErrorCurl($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
if (!empty($opts['cookiejar'])) {
curl_setopt($ch, CURLOPT_COOKIEJAR, $opts["cookiejar"]);
curl_setopt($ch, CURLOPT_COOKIEFILE, $opts["cookiejar"]);
}
// These settings aren't needed. We're following the location already.
// @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// @curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
if (!empty($opts['accept_content'])) {
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
['Accept: ' . $opts['accept_content']]
);
}
if (!empty($opts['header'])) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['header']);
}
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_USERAGENT, $this->getUserAgent());
$range = intval($this->config->get('system', 'curl_range_bytes', 0));
if ($range > 0) {
@curl_setopt($ch, CURLOPT_RANGE, '0-' . $range);
}
// Without this setting it seems as if some webservers send compressed content
// This seems to confuse curl so that it shows this uncompressed.
/// @todo We could possibly set this value to "gzip" or something similar
curl_setopt($ch, CURLOPT_ENCODING, '');
if (!empty($opts['headers'])) {
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
}
if (!empty($opts['nobody'])) {
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
}
if (!empty($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
} else {
$curl_time = $this->config->get('system', 'curl_timeout', 60);
@curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time));
}
// by default we will allow self-signed certs
// but you can override this
$check_cert = $this->config->get('system', 'verifyssl');
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
if ($check_cert) {
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
}
$proxy = $this->config->get('system', 'proxy');
if (!empty($proxy)) {
@curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
@curl_setopt($ch, CURLOPT_PROXY, $proxy);
$proxyuser = $this->config->get('system', 'proxyuser');
if (!empty($proxyuser)) {
@curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser);
}
}
if ($this->config->get('system', 'ipv4_resolve', false)) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
if ($binary) {
@curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
}
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$curl_info = @curl_getinfo($ch);
// Special treatment for HTTP Code 416
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416
if (($curl_info['http_code'] == 416) && ($range > 0)) {
@curl_setopt($ch, CURLOPT_RANGE, '');
$s = @curl_exec($ch);
$curl_info = @curl_getinfo($ch);
}
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
if ($curlResponse->isRedirectUrl()) {
$redirects++;
$this->logger->notice('Curl redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]);
@curl_close($ch);
return $this->get($curlResponse->getRedirectUrl(), $binary, $opts, $redirects);
}
@curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network', System::callstack());
return $curlResponse;
}
/**
* {@inheritDoc}
*
* @param int $redirects The recursion counter for internal use - default 0
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function post(string $url, $params, array $headers = [], int $timeout = 0, int &$redirects = 0)
{
$stamp1 = microtime(true);
if (Network::isUrlBlocked($url)) {
$this->logger->info('Domain is blocked.' . ['url' => $url]);
return CurlResult::createErrorCurl($url);
}
$ch = curl_init($url);
if (($redirects > 8) || (!$ch)) {
return CurlResult::createErrorCurl($url);
}
$this->logger->debug('Post_url: start.', ['url' => $url]);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_USERAGENT, $this->getUserAgent());
if ($this->config->get('system', 'ipv4_resolve', false)) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
if (intval($timeout)) {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
} else {
$curl_time = $this->config->get('system', 'curl_timeout', 60);
curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time));
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$check_cert = $this->config->get('system', 'verifyssl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
if ($check_cert) {
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
}
$proxy = $this->config->get('system', 'proxy');
if (!empty($proxy)) {
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
$proxyuser = $this->config->get('system', 'proxyuser');
if (!empty($proxyuser)) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser);
}
}
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$curl_info = curl_getinfo($ch);
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
if ($curlResponse->isRedirectUrl()) {
$redirects++;
$this->logger->info('Post redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]);
curl_close($ch);
return $this->post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
}
curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network', System::callstack());
// Very old versions of Lighttpd don't like the "Expect" header, so we remove it when needed
if ($curlResponse->getReturnCode() == 417) {
$redirects++;
if (empty($headers)) {
$headers = ['Expect:'];
} else {
if (!in_array('Expect:', $headers)) {
array_push($headers, 'Expect:');
}
}
$this->logger->info('Server responds with 417, applying workaround', ['url' => $url]);
return $this->post($url, $params, $headers, $redirects, $timeout);
}
$this->logger->debug('Post_url: End.', ['url' => $url]);
return $curlResponse;
}
/**
* {@inheritDoc}
*/
public function finalUrl(string $url, int $depth = 1, bool $fetchbody = false)
{
$url = Network::stripTrackingQueryParams($url);
if ($depth > 10) {
return $url;
}
$url = trim($url, "'");
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $this->getUserAgent());
curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
curl_close($ch);
$this->profiler->saveTimestamp($stamp1, "network", System::callstack());
if ($http_code == 0) {
return $url;
}
if (in_array($http_code, ['301', '302'])) {
if (!empty($curl_info['redirect_url'])) {
return $this->finalUrl($curl_info['redirect_url'], ++$depth, $fetchbody);
} elseif (!empty($curl_info['location'])) {
return $this->finalUrl($curl_info['location'], ++$depth, $fetchbody);
}
}
// Check for redirects in the meta elements of the body if there are no redirects in the header.
if (!$fetchbody) {
return $this->finalUrl($url, ++$depth, true);
}
// if the file is too large then exit
if ($curl_info["download_content_length"] > 1000000) {
return $url;
}
// if it isn't a HTML file then exit
if (!empty($curl_info["content_type"]) && !strstr(strtolower($curl_info["content_type"]), "html")) {
return $url;
}
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $this->getUserAgent());
$body = curl_exec($ch);
curl_close($ch);
$this->profiler->saveTimestamp($stamp1, "network", System::callstack());
if (trim($body) == "") {
return $url;
}
// Check for redirect in meta elements
$doc = new DOMDocument();
@$doc->loadHTML($body);
$xpath = new DomXPath($doc);
$list = $xpath->query("//meta[@content]");
foreach ($list as $node) {
$attr = [];
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
if (@$attr["http-equiv"] == 'refresh') {
$path = $attr["content"];
$pathinfo = explode(";", $path);
foreach ($pathinfo as $value) {
if (substr(strtolower($value), 0, 4) == "url=") {
return $this->finalUrl(substr($value, 4), ++$depth);
}
}
}
}
return $url;
}
/**
* {@inheritDoc}
*
* @param int $redirects The recursion counter for internal use - default 0
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function fetch(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
{
$ret = $this->fetchFull($url, $binary, $timeout, $accept_content, $cookiejar, $redirects);
return $ret->getBody();
}
/**
* {@inheritDoc}
*
* @param int $redirects The recursion counter for internal use - default 0
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function fetchFull(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
{
return $this->get(
$url,
$binary,
[
'timeout' => $timeout,
'accept_content' => $accept_content,
'cookiejar' => $cookiejar
],
$redirects
);
}
/**
* {@inheritDoc}
*/
public function getUserAgent()
{
return
FRIENDICA_PLATFORM . " '" .
FRIENDICA_CODENAME . "' " .
FRIENDICA_VERSION . '-' .
DB_UPDATE_VERSION . '; ' .
$this->baseUrl;
}
}

View file

@ -0,0 +1,119 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU APGL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Network;
/**
* Interface for calling HTTP requests and returning their responses
*/
interface IHTTPRequest
{
/**
* Fetches the content of an URL
*
* If binary flag is true, return binary results.
* Set the cookiejar argument to a string (e.g. "/tmp/friendica-cookies.txt")
* to preserve cookies from one request to the next.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
*
* @return string The fetched content
*/
public function fetch(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '');
/**
* Fetches the whole response of an URL.
*
* Inner workings and parameters are the same as @ref fetchUrl but returns an array with
* all the information collected during the fetch.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
*
* @return CurlResult With all relevant information, 'body' contains the actual fetched content.
*/
public function fetchFull(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '');
/**
* Send a GET to an URL.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param array $opts (optional parameters) assoziative array with:
* 'accept_content' => supply Accept: header with 'accept_content' as the value
* 'timeout' => int Timeout in seconds, default system config value or 60 seconds
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'nobody' => only return the header
* 'cookiejar' => path to cookie jar file
* 'header' => header array
*
* @return CurlResult
*/
public function get(string $url, bool $binary = false, array $opts = []);
/**
* Send POST request to an URL
*
* @param string $url URL to post
* @param mixed $params array of POST variables
* @param array $headers HTTP headers
* @param int $timeout The timeout in seconds, default system config value or 60 seconds
*
* @return CurlResult The content
*/
public function post(string $url, $params, array $headers = [], int $timeout = 0);
/**
* Returns the original URL of the provided URL
*
* This function strips tracking query params and follows redirections, either
* through HTTP code or meta refresh tags. Stops after 10 redirections.
*
* @param string $url A user-submitted URL
* @param int $depth The current redirection recursion level (internal)
* @param bool $fetchbody Wether to fetch the body or not after the HEAD requests
*
* @return string A canonical URL
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @see ParseUrl::getSiteinfo
*
* @todo Remove the $fetchbody parameter that generates an extraneous HEAD request
*/
public function finalUrl(string $url, int $depth = 1, bool $fetchbody = false);
/**
* Returns the current UserAgent as a String
*
* @return string the UserAgent as a String
*/
public function getUserAgent();
}

View file

@ -166,7 +166,7 @@ class Probe
Logger::info('Probing', ['host' => $host, 'ssl_url' => $ssl_url, 'url' => $url, 'callstack' => System::callstack(20)]); Logger::info('Probing', ['host' => $host, 'ssl_url' => $ssl_url, 'url' => $url, 'callstack' => System::callstack(20)]);
$xrd = null; $xrd = null;
$curlResult = Network::curl($ssl_url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); $curlResult = DI::httpRequest()->get($ssl_url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
$ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); $ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$xml = $curlResult->getBody(); $xml = $curlResult->getBody();
@ -183,7 +183,7 @@ class Probe
} }
if (!is_object($xrd) && !empty($url)) { if (!is_object($xrd) && !empty($url)) {
$curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); $curlResult = DI::httpRequest()->get($url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
$connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); $connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
Logger::info('Probing timeout', ['url' => $url]); Logger::info('Probing timeout', ['url' => $url]);
@ -427,7 +427,7 @@ class Probe
*/ */
private static function getHideStatus($url) private static function getHideStatus($url)
{ {
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return false; return false;
} }
@ -841,7 +841,7 @@ class Probe
public static function pollZot($url, $data) public static function pollZot($url, $data)
{ {
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
return $data; return $data;
} }
@ -938,7 +938,7 @@ class Probe
{ {
$xrd_timeout = DI::config()->get('system', 'xrd_timeout', 20); $xrd_timeout = DI::config()->get('system', 'xrd_timeout', 20);
$curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout, 'accept_content' => $type]); $curlResult = DI::httpRequest()->get($url, false, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return []; return [];
@ -1007,7 +1007,7 @@ class Probe
*/ */
private static function pollNoscrape($noscrape_url, $data) private static function pollNoscrape($noscrape_url, $data)
{ {
$curlResult = Network::curl($noscrape_url); $curlResult = DI::httpRequest()->get($noscrape_url);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return []; return [];
@ -1265,7 +1265,7 @@ class Probe
*/ */
private static function pollHcard($hcard_url, $data, $dfrn = false) private static function pollHcard($hcard_url, $data, $dfrn = false)
{ {
$curlResult = Network::curl($hcard_url); $curlResult = DI::httpRequest()->get($hcard_url);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return []; return [];
@ -1519,7 +1519,7 @@ class Probe
$pubkey = substr($pubkey, 5); $pubkey = substr($pubkey, 5);
} }
} elseif (Strings::normaliseLink($pubkey) == 'http://') { } elseif (Strings::normaliseLink($pubkey) == 'http://') {
$curlResult = Network::curl($pubkey); $curlResult = DI::httpRequest()->get($pubkey);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return $short ? false : []; return $short ? false : [];
@ -1552,7 +1552,7 @@ class Probe
} }
// Fetch all additional data from the feed // Fetch all additional data from the feed
$curlResult = Network::curl($data["poll"]); $curlResult = DI::httpRequest()->get($data["poll"]);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return []; return [];
@ -1604,7 +1604,7 @@ class Probe
*/ */
private static function pumpioProfileData($profile_link) private static function pumpioProfileData($profile_link)
{ {
$curlResult = Network::curl($profile_link); $curlResult = DI::httpRequest()->get($profile_link);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return []; return [];
} }
@ -1835,7 +1835,7 @@ class Probe
*/ */
private static function feed($url, $probe = true) private static function feed($url, $probe = true)
{ {
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
self::$istimeout = true; self::$istimeout = true;
return []; return [];

View file

@ -21,12 +21,12 @@
namespace Friendica\Protocol; namespace Friendica\Protocol;
use Friendica\Util\JsonLD;
use Friendica\Util\Network;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\DI;
use Friendica\Model\APContact; use Friendica\Model\APContact;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
use Friendica\Util\JsonLD;
/** /**
* ActivityPub Protocol class * ActivityPub Protocol class
@ -87,13 +87,13 @@ class ActivityPub
* @return array * @return array
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function fetchContent($url, $uid = 0) public static function fetchContent(string $url, int $uid = 0)
{ {
if (!empty($uid)) { if (!empty($uid)) {
return HTTPSignature::fetch($url, $uid); return HTTPSignature::fetch($url, $uid);
} }
$curlResult = Network::curl($url, false, ['accept_content' => 'application/activity+json, application/ld+json']); $curlResult = DI::httpRequest()->get($url, false, ['accept_content' => 'application/activity+json, application/ld+json']);
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) { if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
return false; return false;
} }

View file

@ -699,7 +699,7 @@ class Processor
* @return string fetched message URL * @return string fetched message URL
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function fetchMissingActivity($url, $child = []) public static function fetchMissingActivity(string $url, array $child = [])
{ {
if (!empty($child['receiver'])) { if (!empty($child['receiver'])) {
$uid = ActivityPub\Receiver::getFirstUserFromReceivers($child['receiver']); $uid = ActivityPub\Receiver::getFirstUserFromReceivers($child['receiver']);

View file

@ -1194,7 +1194,7 @@ class DFRN
Logger::log('dfrn_deliver: ' . $url); Logger::log('dfrn_deliver: ' . $url);
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
return -2; // timed out return -2; // timed out
@ -1343,7 +1343,7 @@ class DFRN
Logger::debug('dfrn_deliver', ['post' => $postvars]); Logger::debug('dfrn_deliver', ['post' => $postvars]);
$postResult = Network::post($contact['notify'], $postvars); $postResult = DI::httpRequest()->post($contact['notify'], $postvars);
$xml = $postResult->getBody(); $xml = $postResult->getBody();
@ -1440,7 +1440,7 @@ class DFRN
$content_type = ($public_batch ? "application/magic-envelope+xml" : "application/json"); $content_type = ($public_batch ? "application/magic-envelope+xml" : "application/json");
$postResult = Network::post($dest_url, $envelope, ["Content-Type: ".$content_type]); $postResult = DI::httpRequest()->post($dest_url, $envelope, ["Content-Type: " . $content_type]);
$xml = $postResult->getBody(); $xml = $postResult->getBody();
$curl_stat = $postResult->getReturnCode(); $curl_stat = $postResult->getReturnCode();

View file

@ -1379,7 +1379,7 @@ class Diaspora
Logger::log("Fetch post from ".$source_url, Logger::DEBUG); Logger::log("Fetch post from ".$source_url, Logger::DEBUG);
$envelope = Network::fetchUrl($source_url); $envelope = DI::httpRequest()->fetch($source_url);
if ($envelope) { if ($envelope) {
Logger::log("Envelope was fetched.", Logger::DEBUG); Logger::log("Envelope was fetched.", Logger::DEBUG);
$x = self::verifyMagicEnvelope($envelope); $x = self::verifyMagicEnvelope($envelope);
@ -3260,7 +3260,7 @@ class Diaspora
if (!intval(DI::config()->get("system", "diaspora_test"))) { if (!intval(DI::config()->get("system", "diaspora_test"))) {
$content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json"); $content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json");
$postResult = Network::post($dest_url."/", $envelope, ["Content-Type: ".$content_type]); $postResult = DI::httpRequest()->post($dest_url . "/", $envelope, ["Content-Type: " . $content_type]);
$return_code = $postResult->getReturnCode(); $return_code = $postResult->getReturnCode();
} else { } else {
Logger::log("test_mode"); Logger::log("test_mode");

View file

@ -35,6 +35,7 @@ use Friendica\Model\Contact;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Network\HTTPRequest;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network; use Friendica\Util\Network;
use Friendica\Util\ParseUrl; use Friendica\Util\ParseUrl;
@ -350,7 +351,7 @@ class Feed
$orig_plink = $item["plink"]; $orig_plink = $item["plink"];
$item["plink"] = Network::finalUrl($item["plink"]); $item["plink"] = DI::httpRequest()->finalUrl($item["plink"]);
$item["parent-uri"] = $item["uri"]; $item["parent-uri"] = $item["uri"];

View file

@ -42,7 +42,6 @@ use Friendica\Model\User;
use Friendica\Network\Probe; use Friendica\Network\Probe;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Images; use Friendica\Util\Images;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -756,7 +755,7 @@ class OStatus
self::$conv_list[$conversation] = true; self::$conv_list[$conversation] = true;
$curlResult = Network::curl($conversation, false, ['accept_content' => 'application/atom+xml, text/html']); $curlResult = DI::httpRequest()->get($conversation, false, ['accept_content' => 'application/atom+xml, text/html']);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
@ -785,7 +784,7 @@ class OStatus
} }
} }
if ($file != '') { if ($file != '') {
$conversation_atom = Network::curl($attribute['href']); $conversation_atom = DI::httpRequest()->get($attribute['href']);
if ($conversation_atom->isSuccess()) { if ($conversation_atom->isSuccess()) {
$xml = $conversation_atom->getBody(); $xml = $conversation_atom->getBody();
@ -902,7 +901,7 @@ class OStatus
return; return;
} }
$curlResult = Network::curl($self); $curlResult = DI::httpRequest()->get($self);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
@ -949,7 +948,7 @@ class OStatus
} }
$stored = false; $stored = false;
$curlResult = Network::curl($related, false, ['accept_content' => 'application/atom+xml, text/html']); $curlResult = DI::httpRequest()->get($related, false, ['accept_content' => 'application/atom+xml, text/html']);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
@ -980,7 +979,7 @@ class OStatus
} }
} }
if ($atom_file != '') { if ($atom_file != '') {
$curlResult = Network::curl($atom_file); $curlResult = DI::httpRequest()->get($atom_file);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
Logger::log('Fetched XML for URI ' . $related_uri, Logger::DEBUG); Logger::log('Fetched XML for URI ' . $related_uri, Logger::DEBUG);
@ -992,7 +991,7 @@ class OStatus
// Workaround for older GNU Social servers // Workaround for older GNU Social servers
if (($xml == '') && strstr($related, '/notice/')) { if (($xml == '') && strstr($related, '/notice/')) {
$curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom'); $curlResult = DI::httpRequest()->get(str_replace('/notice/', '/api/statuses/show/', $related) . '.atom');
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
Logger::log('GNU Social workaround to fetch XML for URI ' . $related_uri, Logger::DEBUG); Logger::log('GNU Social workaround to fetch XML for URI ' . $related_uri, Logger::DEBUG);
@ -1003,7 +1002,7 @@ class OStatus
// Even more worse workaround for GNU Social ;-) // Even more worse workaround for GNU Social ;-)
if ($xml == '') { if ($xml == '') {
$related_guess = self::convertHref($related_uri); $related_guess = self::convertHref($related_uri);
$curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom'); $curlResult = DI::httpRequest()->get(str_replace('/notice/', '/api/statuses/show/', $related_guess) . '.atom');
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
Logger::log('GNU Social workaround 2 to fetch XML for URI ' . $related_uri, Logger::DEBUG); Logger::log('GNU Social workaround 2 to fetch XML for URI ' . $related_uri, Logger::DEBUG);

View file

@ -31,7 +31,6 @@ use Friendica\DI;
use Friendica\Model\GContact; use Friendica\Model\GContact;
use Friendica\Model\GServer; use Friendica\Model\GServer;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
/** /**
@ -103,7 +102,7 @@ class PortableContact
Logger::log('load: ' . $url, Logger::DEBUG); Logger::log('load: ' . $url, Logger::DEBUG);
$fetchresult = Network::fetchUrlFull($url); $fetchresult = DI::httpRequest()->fetchFull($url);
$s = $fetchresult->getBody(); $s = $fetchresult->getBody();
Logger::log('load: returns ' . $s, Logger::DATA); Logger::log('load: returns ' . $s, Logger::DATA);
@ -251,7 +250,7 @@ class PortableContact
*/ */
private static function fetchServerlist($poco) private static function fetchServerlist($poco)
{ {
$curlResult = Network::curl($poco . "/@server"); $curlResult = DI::httpRequest()->get($poco . "/@server");
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return; return;
@ -291,7 +290,7 @@ class PortableContact
Logger::info("Fetch all users from the server " . $server["url"]); Logger::info("Fetch all users from the server " . $server["url"]);
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess() && !empty($curlResult->getBody())) { if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
$data = json_decode($curlResult->getBody(), true); $data = json_decode($curlResult->getBody(), true);
@ -314,7 +313,7 @@ class PortableContact
$success = false; $success = false;
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess() && !empty($curlResult->getBody())) { if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
Logger::info("Fetch all global contacts from the server " . $server["nurl"]); Logger::info("Fetch all global contacts from the server " . $server["nurl"]);
@ -372,7 +371,7 @@ 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,contactType,generation'; $url = $server['poco'] . '/' . $username . '/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation';
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess()) { if ($curlResult->isSuccess()) {
$data = json_decode($curlResult->getBody(), true); $data = json_decode($curlResult->getBody(), true);

View file

@ -24,7 +24,6 @@ namespace Friendica\Protocol;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Network\Probe; use Friendica\Network\Probe;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -72,7 +71,7 @@ class Salmon
$ret[$x] = substr($ret[$x], 5); $ret[$x] = substr($ret[$x], 5);
} }
} elseif (Strings::normaliseLink($ret[$x]) == 'http://') { } elseif (Strings::normaliseLink($ret[$x]) == 'http://') {
$ret[$x] = Network::fetchUrl($ret[$x]); $ret[$x] = DI::httpRequest()->fetchUrl($ret[$x]);
} }
} }
} }
@ -155,7 +154,7 @@ class Salmon
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces); $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
// slap them // slap them
$postResult = Network::post($url, $salmon, [ $postResult = DI::httpRequest()->post($url, $salmon, [
'Content-type: application/magic-envelope+xml', 'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon) 'Content-length: ' . strlen($salmon)
]); ]);
@ -180,7 +179,7 @@ class Salmon
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces); $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
// slap them // slap them
$postResult = Network::post($url, $salmon, [ $postResult = DI::httpRequest()->post($url, $salmon, [
'Content-type: application/magic-envelope+xml', 'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon) 'Content-length: ' . strlen($salmon)
]); ]);
@ -203,7 +202,7 @@ class Salmon
$salmon = XML::fromArray($xmldata, $xml, false, $namespaces); $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
// slap them // slap them
$postResult = Network::post($url, $salmon, [ $postResult = DI::httpRequest()->post($url, $salmon, [
'Content-type: application/magic-envelope+xml', 'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon)]); 'Content-length: ' . strlen($salmon)]);
$return_code = $postResult->getReturnCode(); $return_code = $postResult->getReturnCode();

View file

@ -181,7 +181,7 @@ class ExAuth
$url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user; $url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user;
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return false; return false;

View file

@ -21,11 +21,11 @@
namespace Friendica\Util; namespace Friendica\Util;
use Friendica\Database\DBA;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\User;
use Friendica\Model\APContact; use Friendica\Model\APContact;
use Friendica\Model\User;
/** /**
* Implements HTTP Signatures per draft-cavage-http-signatures-07. * Implements HTTP Signatures per draft-cavage-http-signatures-07.
@ -297,7 +297,7 @@ class HTTPSignature
$headers[] = 'Content-Type: application/activity+json'; $headers[] = 'Content-Type: application/activity+json';
$postResult = Network::post($target, $content, $headers); $postResult = DI::httpRequest()->post($target, $content, $headers);
$return_code = $postResult->getReturnCode(); $return_code = $postResult->getReturnCode();
Logger::log('Transmit to ' . $target . ' returned ' . $return_code, Logger::DEBUG); Logger::log('Transmit to ' . $target . ' returned ' . $return_code, Logger::DEBUG);
@ -442,7 +442,7 @@ class HTTPSignature
$curl_opts = $opts; $curl_opts = $opts;
$curl_opts['header'] = $headers; $curl_opts['header'] = $headers;
$curlResult = Network::curl($request, false, $curl_opts); $curlResult = DI::httpRequest()->get($request, false, $curl_opts);
$return_code = $curlResult->getReturnCode(); $return_code = $curlResult->getReturnCode();
Logger::log('Fetched for user ' . $uid . ' from ' . $request . ' returned ' . $return_code, Logger::DEBUG); Logger::log('Fetched for user ' . $uid . ' from ' . $request . ' returned ' . $return_code, Logger::DEBUG);

View file

@ -184,7 +184,7 @@ class Images
return $data; return $data;
} }
$img_str = Network::fetchUrl($url, true, 4); $img_str = DI::httpRequest()->fetch($url, true, 4);
if (!$img_str) { if (!$img_str) {
return []; return [];

View file

@ -21,346 +21,12 @@
namespace Friendica\Util; namespace Friendica\Util;
use DOMDocument;
use DomXPath;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Network\CurlResult;
class Network class Network
{ {
/**
* Curl wrapper
*
* If binary flag is true, return binary results.
* Set the cookiejar argument to a string (e.g. "/tmp/friendica-cookies.txt")
* to preserve cookies from one request to the next.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
* @param int $redirects The recursion counter for internal use - default 0
*
* @return string The fetched content
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function fetchUrl(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
{
$ret = self::fetchUrlFull($url, $binary, $timeout, $accept_content, $cookiejar, $redirects);
return $ret->getBody();
}
/**
* Curl wrapper with array of return values.
*
* Inner workings and parameters are the same as @ref fetchUrl but returns an array with
* all the information collected during the fetch.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
* @param int $redirects The recursion counter for internal use - default 0
*
* @return CurlResult With all relevant information, 'body' contains the actual fetched content.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function fetchUrlFull(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
{
return self::curl(
$url,
$binary,
[
'timeout' => $timeout,
'accept_content' => $accept_content,
'cookiejar' => $cookiejar
],
$redirects
);
}
/**
* fetches an URL.
*
* @param string $url URL to fetch
* @param bool $binary default false
* TRUE if asked to return binary results (file download)
* @param array $opts (optional parameters) assoziative array with:
* 'accept_content' => supply Accept: header with 'accept_content' as the value
* 'timeout' => int Timeout in seconds, default system config value or 60 seconds
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'nobody' => only return the header
* 'cookiejar' => path to cookie jar file
* 'header' => header array
* @param int $redirects The recursion counter for internal use - default 0
*
* @return CurlResult
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function curl(string $url, bool $binary = false, array $opts = [], int &$redirects = 0)
{
$stamp1 = microtime(true);
$a = DI::app();
if (strlen($url) > 1000) {
Logger::log('URL is longer than 1000 characters. Callstack: ' . System::callstack(20), Logger::DEBUG);
return CurlResult::createErrorCurl(substr($url, 0, 200));
}
$parts2 = [];
$parts = parse_url($url);
$path_parts = explode('/', $parts['path'] ?? '');
foreach ($path_parts as $part) {
if (strlen($part) <> mb_strlen($part)) {
$parts2[] = rawurlencode($part);
} else {
$parts2[] = $part;
}
}
$parts['path'] = implode('/', $parts2);
$url = self::unparseURL($parts);
if (self::isUrlBlocked($url)) {
Logger::log('domain of ' . $url . ' is blocked', Logger::DATA);
return CurlResult::createErrorCurl($url);
}
$ch = @curl_init($url);
if (($redirects > 8) || (!$ch)) {
return CurlResult::createErrorCurl($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
if (!empty($opts['cookiejar'])) {
curl_setopt($ch, CURLOPT_COOKIEJAR, $opts["cookiejar"]);
curl_setopt($ch, CURLOPT_COOKIEFILE, $opts["cookiejar"]);
}
// These settings aren't needed. We're following the location already.
// @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// @curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
if (!empty($opts['accept_content'])) {
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
['Accept: ' . $opts['accept_content']]
);
}
if (!empty($opts['header'])) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['header']);
}
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
$range = intval(DI::config()->get('system', 'curl_range_bytes', 0));
if ($range > 0) {
@curl_setopt($ch, CURLOPT_RANGE, '0-' . $range);
}
// Without this setting it seems as if some webservers send compressed content
// This seems to confuse curl so that it shows this uncompressed.
/// @todo We could possibly set this value to "gzip" or something similar
curl_setopt($ch, CURLOPT_ENCODING, '');
if (!empty($opts['headers'])) {
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
}
if (!empty($opts['nobody'])) {
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
}
if (!empty($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
} else {
$curl_time = DI::config()->get('system', 'curl_timeout', 60);
@curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time));
}
// by default we will allow self-signed certs
// but you can override this
$check_cert = DI::config()->get('system', 'verifyssl');
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
if ($check_cert) {
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
}
$proxy = DI::config()->get('system', 'proxy');
if (strlen($proxy)) {
@curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
@curl_setopt($ch, CURLOPT_PROXY, $proxy);
$proxyuser = @DI::config()->get('system', 'proxyuser');
if (strlen($proxyuser)) {
@curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser);
}
}
if (DI::config()->get('system', 'ipv4_resolve', false)) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
if ($binary) {
@curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
}
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$curl_info = @curl_getinfo($ch);
// Special treatment for HTTP Code 416
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416
if (($curl_info['http_code'] == 416) && ($range > 0)) {
@curl_setopt($ch, CURLOPT_RANGE, '');
$s = @curl_exec($ch);
$curl_info = @curl_getinfo($ch);
}
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
if ($curlResponse->isRedirectUrl()) {
$redirects++;
Logger::log('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
@curl_close($ch);
return self::curl($curlResponse->getRedirectUrl(), $binary, $opts, $redirects);
}
@curl_close($ch);
DI::profiler()->saveTimestamp($stamp1, 'network', System::callstack());
return $curlResponse;
}
/**
* Send POST request to $url
*
* @param string $url URL to post
* @param mixed $params array of POST variables
* @param array $headers HTTP headers
* @param int $redirects Recursion counter for internal use - default = 0
* @param int $timeout The timeout in seconds, default system config value or 60 seconds
*
* @return CurlResult The content
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function post(string $url, $params, array $headers = [], int $timeout = 0, int &$redirects = 0)
{
$stamp1 = microtime(true);
if (self::isUrlBlocked($url)) {
Logger::log('post_url: domain of ' . $url . ' is blocked', Logger::DATA);
return CurlResult::createErrorCurl($url);
}
$a = DI::app();
$ch = curl_init($url);
if (($redirects > 8) || (!$ch)) {
return CurlResult::createErrorCurl($url);
}
Logger::log('post_url: start ' . $url, Logger::DATA);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
if (DI::config()->get('system', 'ipv4_resolve', false)) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
if (intval($timeout)) {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
} else {
$curl_time = DI::config()->get('system', 'curl_timeout', 60);
curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time));
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$check_cert = DI::config()->get('system', 'verifyssl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
if ($check_cert) {
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
}
$proxy = DI::config()->get('system', 'proxy');
if (strlen($proxy)) {
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
$proxyuser = DI::config()->get('system', 'proxyuser');
if (strlen($proxyuser)) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser);
}
}
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$curl_info = curl_getinfo($ch);
$curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
if ($curlResponse->isRedirectUrl()) {
$redirects++;
Logger::log('post_url: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
curl_close($ch);
return self::post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
}
curl_close($ch);
DI::profiler()->saveTimestamp($stamp1, 'network', System::callstack());
// Very old versions of Lighttpd don't like the "Expect" header, so we remove it when needed
if ($curlResponse->getReturnCode() == 417) {
$redirects++;
if (empty($headers)) {
$headers = ['Expect:'];
} else {
if (!in_array('Expect:', $headers)) {
array_push($headers, 'Expect:');
}
}
Logger::info('Server responds with 417, applying workaround', ['url' => $url]);
return self::post($url, $params, $headers, $redirects, $timeout);
}
Logger::log('post_url: end ' . $url, Logger::DATA);
return $curlResponse;
}
/** /**
* Return raw post data from a post request * Return raw post data from a post request
@ -645,126 +311,6 @@ class Network
return self::unparseURL($parts); return self::unparseURL($parts);
} }
/**
* Returns the original URL of the provided URL
*
* This function strips tracking query params and follows redirections, either
* through HTTP code or meta refresh tags. Stops after 10 redirections.
*
* @todo Remove the $fetchbody parameter that generates an extraneous HEAD request
*
* @see ParseUrl::getSiteinfo
*
* @param string $url A user-submitted URL
* @param int $depth The current redirection recursion level (internal)
* @param bool $fetchbody Wether to fetch the body or not after the HEAD requests
* @return string A canonical URL
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function finalUrl(string $url, int $depth = 1, bool $fetchbody = false)
{
$a = DI::app();
$url = self::stripTrackingQueryParams($url);
if ($depth > 10) {
return $url;
}
$url = trim($url, "'");
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
curl_close($ch);
DI::profiler()->saveTimestamp($stamp1, "network", System::callstack());
if ($http_code == 0) {
return $url;
}
if (in_array($http_code, ['301', '302'])) {
if (!empty($curl_info['redirect_url'])) {
return self::finalUrl($curl_info['redirect_url'], ++$depth, $fetchbody);
} elseif (!empty($curl_info['location'])) {
return self::finalUrl($curl_info['location'], ++$depth, $fetchbody);
}
}
// Check for redirects in the meta elements of the body if there are no redirects in the header.
if (!$fetchbody) {
return(self::finalUrl($url, ++$depth, true));
}
// if the file is too large then exit
if ($curl_info["download_content_length"] > 1000000) {
return $url;
}
// if it isn't a HTML file then exit
if (!empty($curl_info["content_type"]) && !strstr(strtolower($curl_info["content_type"]), "html")) {
return $url;
}
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
$body = curl_exec($ch);
curl_close($ch);
DI::profiler()->saveTimestamp($stamp1, "network", System::callstack());
if (trim($body) == "") {
return $url;
}
// Check for redirect in meta elements
$doc = new DOMDocument();
@$doc->loadHTML($body);
$xpath = new DomXPath($doc);
$list = $xpath->query("//meta[@content]");
foreach ($list as $node) {
$attr = [];
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
if (@$attr["http-equiv"] == 'refresh') {
$path = $attr["content"];
$pathinfo = explode(";", $path);
foreach ($pathinfo as $value) {
if (substr(strtolower($value), 0, 4) == "url=") {
return self::finalUrl(substr($value, 4), ++$depth);
}
}
}
}
return $url;
}
/** /**
* Find the matching part between two url * Find the matching part between two url
* *

View file

@ -27,6 +27,7 @@ use Friendica\Content\OEmbed;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI;
/** /**
* Get information about a given URL * Get information about a given URL
@ -159,7 +160,7 @@ class ParseUrl
return $siteinfo; return $siteinfo;
} }
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if (!$curlResult->isSuccess()) { if (!$curlResult->isSuccess()) {
return $siteinfo; return $siteinfo;
} }

View file

@ -24,7 +24,6 @@ namespace Friendica\Worker;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Util\Network;
/** /**
* Check the git repository VERSION file and save the version to the DB * Check the git repository VERSION file and save the version to the DB
@ -55,7 +54,7 @@ class CheckVersion
Logger::log("Checking VERSION from: ".$checked_url, Logger::DEBUG); Logger::log("Checking VERSION from: ".$checked_url, Logger::DEBUG);
// fetch the VERSION file // fetch the VERSION file
$gitversion = DBA::escape(trim(Network::fetchUrl($checked_url))); $gitversion = DBA::escape(trim(DI::httpRequest()->fetch($checked_url)));
Logger::log("Upstream VERSION is: ".$gitversion, Logger::DEBUG); Logger::log("Upstream VERSION is: ".$gitversion, Logger::DEBUG);
DI::config()->set('system', 'git_friendica_version', $gitversion); DI::config()->set('system', 'git_friendica_version', $gitversion);

View file

@ -30,12 +30,9 @@ use Friendica\Database\PostUpdate;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\GContact; use Friendica\Model\GContact;
use Friendica\Model\GServer;
use Friendica\Model\Nodeinfo; use Friendica\Model\Nodeinfo;
use Friendica\Model\Photo; use Friendica\Model\Photo;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Network\Probe;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -63,7 +60,7 @@ class CronJobs
// Now trying to register // Now trying to register
$url = 'http://the-federation.info/register/' . DI::baseUrl()->getHostname(); $url = 'http://the-federation.info/register/' . DI::baseUrl()->getHostname();
Logger::debug('Check registering url', ['url' => $url]); Logger::debug('Check registering url', ['url' => $url]);
$ret = Network::fetchUrl($url); $ret = DI::httpRequest()->fetch($url);
Logger::debug('Check registering answer', ['answer' => $ret]); Logger::debug('Check registering answer', ['answer' => $ret]);
Logger::info('cron_end'); Logger::info('cron_end');
break; break;

View file

@ -26,7 +26,6 @@ use Friendica\Core\Logger;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Util\Network;
/** /**
* Sends updated profile data to the directory * Sends updated profile data to the directory
@ -54,7 +53,7 @@ class Directory
Logger::log('Updating directory: ' . $arr['url'], Logger::DEBUG); Logger::log('Updating directory: ' . $arr['url'], Logger::DEBUG);
if (strlen($arr['url'])) { if (strlen($arr['url'])) {
Network::fetchUrl($dir . '?url=' . bin2hex($arr['url'])); DI::httpRequest()->fetch($dir . '?url=' . bin2hex($arr['url']));
} }
return; return;

View file

@ -34,7 +34,6 @@ use Friendica\Protocol\Email;
use Friendica\Protocol\Feed; use Friendica\Protocol\Feed;
use Friendica\Protocol\PortableContact; use Friendica\Protocol\PortableContact;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -291,7 +290,7 @@ class OnePoll
. '&type=data&last_update=' . $last_update . '&type=data&last_update=' . $last_update
. '&perm=' . $perm; . '&perm=' . $perm;
$curlResult = Network::curl($url); $curlResult = DI::httpRequest()->get($url);
if (!$curlResult->isSuccess() && ($curlResult->getErrorNumber() == 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
@ -405,7 +404,7 @@ class OnePoll
$postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
$postvars['perm'] = 'rw'; $postvars['perm'] = 'rw';
return Network::post($contact['poll'], $postvars)->getBody(); return DI::httpRequest()->post($contact['poll'], $postvars)->getBody();
} }
/** /**
@ -444,7 +443,7 @@ class OnePoll
} }
$cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-'); $cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-');
$curlResult = Network::curl($contact['poll'], false, ['cookiejar' => $cookiejar]); $curlResult = DI::httpRequest()->get($contact['poll'], false, ['cookiejar' => $cookiejar]);
unlink($cookiejar); unlink($cookiejar);
if ($curlResult->isTimeout()) { if ($curlResult->isTimeout()) {
@ -756,7 +755,7 @@ class OnePoll
DBA::update('contact', ['hub-verify' => $verify_token], ['id' => $contact['id']]); DBA::update('contact', ['hub-verify' => $verify_token], ['id' => $contact['id']]);
} }
$postResult = Network::post($url, $params); $postResult = DI::httpRequest()->post($url, $params);
Logger::log('subscribe_to_hub: returns: ' . $postResult->getReturnCode(), Logger::DEBUG); Logger::log('subscribe_to_hub: returns: ' . $postResult->getReturnCode(), Logger::DEBUG);

View file

@ -26,7 +26,6 @@ use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\PushSubscriber; use Friendica\Model\PushSubscriber;
use Friendica\Protocol\OStatus; use Friendica\Protocol\OStatus;
use Friendica\Util\Network;
class PubSubPublish class PubSubPublish
{ {
@ -68,7 +67,7 @@ class PubSubPublish
Logger::log('POST ' . print_r($headers, true) . "\n" . $params, Logger::DATA); Logger::log('POST ' . print_r($headers, true) . "\n" . $params, Logger::DATA);
$postResult = Network::post($subscriber['callback_url'], $params, $headers); $postResult = DI::httpRequest()->post($subscriber['callback_url'], $params, $headers);
$ret = $postResult->getReturnCode(); $ret = $postResult->getReturnCode();
if ($ret >= 200 && $ret <= 299) { if ($ret >= 200 && $ret <= 299) {

View file

@ -30,7 +30,6 @@ use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\GContact; use Friendica\Model\GContact;
use Friendica\Model\GServer; use Friendica\Model\GServer;
use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
class SearchDirectory class SearchDirectory
@ -52,7 +51,7 @@ class SearchDirectory
} }
} }
$x = Network::fetchUrl(Search::getGlobalDirectory() . '/lsearch?p=1&n=500&search=' . urlencode($search)); $x = DI::httpRequest()->fetch(Search::getGlobalDirectory() . '/lsearch?p=1&n=500&search=' . urlencode($search));
$j = json_decode($x); $j = json_decode($x);
if (!empty($j->results)) { if (!empty($j->results)) {

View file

@ -46,6 +46,7 @@ use Friendica\Database\Database;
use Friendica\Factory; use Friendica\Factory;
use Friendica\Model\Storage\IStorage; use Friendica\Model\Storage\IStorage;
use Friendica\Model\User\Cookie; use Friendica\Model\User\Cookie;
use Friendica\Network;
use Friendica\Util; use Friendica\Util;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -219,4 +220,7 @@ return [
['getBackend', [], Dice::CHAIN_CALL], ['getBackend', [], Dice::CHAIN_CALL],
], ],
], ],
Network\IHTTPRequest::class => [
'instanceOf' => Network\HTTPRequest::class,
]
]; ];

View file

@ -26,9 +26,9 @@ use Dice\Dice;
use Friendica\Core\Config\Cache; use Friendica\Core\Config\Cache;
use Friendica\DI; use Friendica\DI;
use Friendica\Network\CurlResult; use Friendica\Network\CurlResult;
use Friendica\Network\IHTTPRequest;
use Friendica\Test\MockedTest; use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait; use Friendica\Test\Util\VFSTrait;
use Friendica\Util\Network;
use Mockery\MockInterface; use Mockery\MockInterface;
class InstallerTest extends MockedTest class InstallerTest extends MockedTest
@ -39,6 +39,10 @@ class InstallerTest extends MockedTest
* @var \Friendica\Core\L10n|MockInterface * @var \Friendica\Core\L10n|MockInterface
*/ */
private $l10nMock; private $l10nMock;
/**
* @var Dice|MockInterface
*/
private $dice;
public function setUp() public function setUp()
{ {
@ -49,14 +53,14 @@ class InstallerTest extends MockedTest
$this->l10nMock = \Mockery::mock(\Friendica\Core\L10n::class); $this->l10nMock = \Mockery::mock(\Friendica\Core\L10n::class);
/** @var Dice|MockInterface $dice */ /** @var Dice|MockInterface $dice */
$dice = \Mockery::mock(Dice::class)->makePartial(); $this->dice = \Mockery::mock(Dice::class)->makePartial();
$dice = $dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); $this->dice = $this->dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php');
$dice->shouldReceive('create') $this->dice->shouldReceive('create')
->with(\Friendica\Core\L10n::class) ->with(\Friendica\Core\L10n::class)
->andReturn($this->l10nMock); ->andReturn($this->l10nMock);
DI::init($dice); DI::init($this->dice);
} }
private function mockL10nT(string $text, $times = null) private function mockL10nT(string $text, $times = null)
@ -305,16 +309,22 @@ class InstallerTest extends MockedTest
->andReturn('test Error'); ->andReturn('test Error');
// Mocking the CURL Request // Mocking the CURL Request
$networkMock = \Mockery::mock('alias:' . Network::class); $networkMock = \Mockery::mock(IHTTPRequest::class);
$networkMock $networkMock
->shouldReceive('fetchUrlFull') ->shouldReceive('fetchFull')
->with('https://test/install/testrewrite') ->with('https://test/install/testrewrite')
->andReturn($curlResult); ->andReturn($curlResult);
$networkMock $networkMock
->shouldReceive('fetchUrlFull') ->shouldReceive('fetchFull')
->with('http://test/install/testrewrite') ->with('http://test/install/testrewrite')
->andReturn($curlResult); ->andReturn($curlResult);
$this->dice->shouldReceive('create')
->with(IHTTPRequest::class)
->andReturn($networkMock);
DI::init($this->dice);
// Mocking that we can use CURL // Mocking that we can use CURL
$this->setFunctions(['curl_init' => true]); $this->setFunctions(['curl_init' => true]);
@ -346,16 +356,22 @@ class InstallerTest extends MockedTest
->andReturn('204'); ->andReturn('204');
// Mocking the CURL Request // Mocking the CURL Request
$networkMock = \Mockery::mock('alias:' . Network::class); $networkMock = \Mockery::mock(IHTTPRequest::class);
$networkMock $networkMock
->shouldReceive('fetchUrlFull') ->shouldReceive('fetchFull')
->with('https://test/install/testrewrite') ->with('https://test/install/testrewrite')
->andReturn($curlResultF); ->andReturn($curlResultF);
$networkMock $networkMock
->shouldReceive('fetchUrlFull') ->shouldReceive('fetchFull')
->with('http://test/install/testrewrite') ->with('http://test/install/testrewrite')
->andReturn($curlResultW); ->andReturn($curlResultW);
$this->dice->shouldReceive('create')
->with(IHTTPRequest::class)
->andReturn($networkMock);
DI::init($this->dice);
// Mocking that we can use CURL // Mocking that we can use CURL
$this->setFunctions(['curl_init' => true]); $this->setFunctions(['curl_init' => true]);