diff --git a/boot.php b/boot.php index ede6fc77b..98db95227 100644 --- a/boot.php +++ b/boot.php @@ -32,7 +32,6 @@ use Friendica\Model\Contact; use Friendica\Database\DBStructure; use Friendica\Module\Login; -require_once 'include/network.php'; require_once 'include/text.php'; require_once 'include/datetime.php'; diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 599b543ad..72f49a40b 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -11,6 +11,7 @@ use Friendica\Core\L10n; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Model\GContact; +use Friendica\Util\Network; require_once "mod/proxy.php"; @@ -733,7 +734,7 @@ function navbar_complete(App $a) { if (! $localsearch) { $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : ''); - $x = z_fetch_url(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); + $x = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search)); if ($x['success']) { $j = json_decode($x['body'],true); if ($j && isset($j['results'])) { diff --git a/include/api.php b/include/api.php index 8579d2d18..7164f85ab 100644 --- a/include/api.php +++ b/include/api.php @@ -35,6 +35,7 @@ use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Network\HTTPException\TooManyRequestsException; use Friendica\Object\Image; use Friendica\Protocol\Diaspora; +use Friendica\Util\Network; use Friendica\Util\XML; require_once 'include/bbcode.php'; @@ -5073,7 +5074,7 @@ function api_get_nick($profile) if ($StatusnetHost != $profile) { $StatusnetUser = preg_replace("=https?://(.*)/user/(.*)=ism", "$2", $profile); if ($StatusnetUser != $profile) { - $UserData = fetch_url("http://".$StatusnetHost."/api/users/show.json?user_id=".$StatusnetUser); + $UserData = Network::fetchUrl("http://".$StatusnetHost."/api/users/show.json?user_id=".$StatusnetUser); $user = json_decode($UserData); if ($user) { $nick = $user->screen_name; diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 2673750ee..95047d61a 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -1,5 +1,6 @@ loadHTML($body); @@ -804,9 +803,7 @@ function bb_CleanPictureLinksSub($match) { $text = "[img]".$match[2]."[/img]"; // if its not a picture then look if its a page that contains a picture link - require_once("include/network.php"); - - $body = fetch_url($match[1]); + $body = Network::fetchUrl($match[1]); $doc = new DOMDocument(); @$doc->loadHTML($body); diff --git a/include/conversation.php b/include/conversation.php index e0f9856ba..af4bb0559 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -15,6 +15,7 @@ use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Object\Thread; use Friendica\Object\Post; +use Friendica\Util\XML; require_once "include/bbcode.php"; require_once "include/acl_selectors.php"; @@ -184,8 +185,8 @@ function localize_item(&$item) { $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">"; - $obj = parse_xml_string($xmlhead.$item['object']); - $links = parse_xml_string($xmlhead."".unxmlify($obj->link).""); + $obj = XML::parseString($xmlhead.$item['object']); + $links = XML::parseString($xmlhead."".unxmlify($obj->link).""); $Bname = $obj->title; $Blink = ""; $Bphoto = ""; @@ -220,8 +221,8 @@ function localize_item(&$item) { $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">"; - $obj = parse_xml_string($xmlhead.$item['object']); - $links = parse_xml_string($xmlhead."".unxmlify($obj->link).""); + $obj = XML::parseString($xmlhead.$item['object']); + $links = XML::parseString($xmlhead."".unxmlify($obj->link).""); $Bname = $obj->title; $Blink = ""; @@ -295,7 +296,7 @@ function localize_item(&$item) { } $plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]'; - $parsedobj = parse_xml_string($xmlhead.$item['object']); + $parsedobj = XML::parseString($xmlhead.$item['object']); $tag = sprintf('#[url=%s]%s[/url]', $parsedobj->id, $parsedobj->content); $item['body'] = L10n::t('%1$s tagged %2$s\'s %3$s with %4$s', $author, $objauthor, $plink, $tag ); @@ -312,7 +313,7 @@ function localize_item(&$item) { $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">"; - $obj = parse_xml_string($xmlhead.$item['object']); + $obj = XML::parseString($xmlhead.$item['object']); if (strlen($obj->id)) { $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($obj->id), diff --git a/include/html2bbcode.php b/include/html2bbcode.php index 2404e42f6..a5967d2cb 100644 --- a/include/html2bbcode.php +++ b/include/html2bbcode.php @@ -9,6 +9,7 @@ */ use Friendica\Core\Addon; +use Friendica\Util\Network; use Friendica\Util\XML; function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb) @@ -362,7 +363,7 @@ function addHostnameSub($matches, $basepath) $url = $matches[1]; $parts = array_merge($base, parse_url($url)); - $url2 = unParseUrl($parts); + $url2 = Network::unparseURL($parts); return str_replace($url, $url2, $link); } diff --git a/include/items.php b/include/items.php index edc757dc2..1951b340c 100644 --- a/include/items.php +++ b/include/items.php @@ -22,6 +22,7 @@ use Friendica\Object\Image; use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; use Friendica\Protocol\Feed; +use Friendica\Util\Network; use Friendica\Util\ParseUrl; require_once 'include/bbcode.php'; @@ -1480,7 +1481,7 @@ function subscribe_to_hub($url, $importer, $contact, $hubmode = 'subscribe') { dba::update('contact', ['hub-verify' => $verify_token], ['id' => $contact['id']]); } - post_url($url, $params); + Network::post($url, $params); logger('subscribe_to_hub: returns: ' . $a->get_curl_code(), LOGGER_DEBUG); diff --git a/include/network.php b/include/network.php deleted file mode 100644 index 73fa80f98..000000000 --- a/include/network.php +++ /dev/null @@ -1,1087 +0,0 @@ -$timeout, - 'accept_content'=>$accept_content, - 'cookiejar'=>$cookiejar - ] - ); - - return($ret['body']); -} - -/** - * @brief fetches an URL. - * - * @param string $url URL to fetch - * @param boolean $binary default false - * TRUE if asked to return binary results (file download) - * @param int $redirects The recursion counter for internal use - default 0 - * @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 - * - * @return array an assoziative array with: - * int 'return_code' => HTTP return code or 0 if timeout or failure - * boolean 'success' => boolean true (if HTTP 2xx result) or false - * string 'redirect_url' => in case of redirect, content was finally retrieved from this URL - * string 'header' => HTTP headers - * string 'body' => fetched content - */ -function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = []) -{ - $ret = ['return_code' => 0, 'success' => false, 'header' => '', 'info' => '', 'body' => '']; - - $stamp1 = microtime(true); - - $a = get_app(); - - if (blocked_url($url)) { - logger('z_fetch_url: domain of ' . $url . ' is blocked', LOGGER_DATA); - return $ret; - } - - $ch = @curl_init($url); - - if (($redirects > 8) || (!$ch)) { - return $ret; - } - - @curl_setopt($ch, CURLOPT_HEADER, true); - - if (x($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 (x($opts, 'accept_content')) { - curl_setopt( - $ch, - CURLOPT_HTTPHEADER, - ['Accept: ' . $opts['accept_content']] - ); - } - - @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - @curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent()); - - $range = intval(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 (x($opts, 'headers')) { - @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); - } - - if (x($opts, 'nobody')) { - @curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']); - } - - if (x($opts, 'timeout')) { - @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']); - } else { - $curl_time = 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 = 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 = Config::get('system', 'proxy'); - - if (strlen($proxy)) { - @curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); - @curl_setopt($ch, CURLOPT_PROXY, $proxy); - $proxyuser = @Config::get('system', 'proxyuser'); - - if (strlen($proxyuser)) { - @curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser); - } - } - - if (Config::get('system', 'ipv4_resolve', false)) { - curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - } - - if ($binary) { - @curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); - } - - $a->set_curl_code(0); - - // 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); - } - - if (curl_errno($ch) !== CURLE_OK) { - logger('fetch_url error fetching ' . $url . ': ' . curl_error($ch), LOGGER_NORMAL); - } - - $ret['errno'] = curl_errno($ch); - - $base = $s; - $ret['info'] = $curl_info; - - $http_code = $curl_info['http_code']; - - logger('fetch_url ' . $url . ': ' . $http_code . " " . $s, LOGGER_DATA); - $header = ''; - - // Pull out multiple headers, e.g. proxy and continuation headers - // allow for HTTP/2.x without fixing code - - while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) { - $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); - $header .= $chunk; - $base = substr($base, strlen($chunk)); - } - - $a->set_curl_code($http_code); - $a->set_curl_content_type($curl_info['content_type']); - $a->set_curl_headers($header); - - if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) { - $new_location_info = @parse_url($curl_info['redirect_url']); - $old_location_info = @parse_url($curl_info['url']); - - $newurl = $curl_info['redirect_url']; - - if (($new_location_info['path'] == '') && ( $new_location_info['host'] != '')) { - $newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path']; - } - - $matches = []; - - if (preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches)) { - $newurl = trim(array_pop($matches)); - } - if (strpos($newurl, '/') === 0) { - $newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl; - } - - if (filter_var($newurl, FILTER_VALIDATE_URL)) { - $redirects++; - @curl_close($ch); - return z_fetch_url($newurl, $binary, $redirects, $opts); - } - } - - $a->set_curl_code($http_code); - $a->set_curl_content_type($curl_info['content_type']); - - $rc = intval($http_code); - $ret['return_code'] = $rc; - $ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false); - $ret['redirect_url'] = $url; - - if (!$ret['success']) { - $ret['error'] = curl_error($ch); - $ret['debug'] = $curl_info; - logger('z_fetch_url: error: '.$url.': '.$ret['return_code'].' - '.$ret['error'], LOGGER_DEBUG); - logger('z_fetch_url: debug: '.print_r($curl_info, true), LOGGER_DATA); - } - - $ret['body'] = substr($s, strlen($header)); - $ret['header'] = $header; - - if (x($opts, 'debug')) { - $ret['debug'] = $curl_info; - } - - @curl_close($ch); - - $a->save_timestamp($stamp1, 'network'); - - return($ret); -} - -/** - * @brief Send POST request to $url - * - * @param string $url URL to post - * @param mixed $params array of POST variables - * @param string $headers HTTP headers - * @param integer $redirects Recursion counter for internal use - default = 0 - * @param integer $timeout The timeout in seconds, default system config value or 60 seconds - * - * @return string The content - */ -function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0) -{ - $stamp1 = microtime(true); - - if (blocked_url($url)) { - logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA); - return false; - } - - $a = get_app(); - $ch = curl_init($url); - - if (($redirects > 8) || (!$ch)) { - return false; - } - - logger('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->get_useragent()); - - if (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 = Config::get('system', 'curl_timeout', 60); - curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time)); - } - - if (defined('LIGHTTPD')) { - if (!is_array($headers)) { - $headers = ['Expect:']; - } else { - if (!in_array('Expect:', $headers)) { - array_push($headers, 'Expect:'); - } - } - } - - if ($headers) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $check_cert = 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 = Config::get('system', 'proxy'); - - if (strlen($proxy)) { - curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); - curl_setopt($ch, CURLOPT_PROXY, $proxy); - $proxyuser = Config::get('system', 'proxyuser'); - if (strlen($proxyuser)) { - curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser); - } - } - - $a->set_curl_code(0); - - // don't let curl abort the entire application - // if it throws any errors. - - $s = @curl_exec($ch); - - $base = $s; - $curl_info = curl_getinfo($ch); - $http_code = $curl_info['http_code']; - - logger('post_url: result ' . $http_code . ' - ' . $url, LOGGER_DATA); - - $header = ''; - - // Pull out multiple headers, e.g. proxy and continuation headers - // allow for HTTP/2.x without fixing code - - while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) { - $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); - $header .= $chunk; - $base = substr($base, strlen($chunk)); - } - - if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) { - $matches = []; - preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches); - $newurl = trim(array_pop($matches)); - - if (strpos($newurl, '/') === 0) { - $newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl; - } - - if (filter_var($newurl, FILTER_VALIDATE_URL)) { - $redirects++; - logger('post_url: redirect ' . $url . ' to ' . $newurl); - return post_url($newurl, $params, $headers, $redirects, $timeout); - } - } - - $a->set_curl_code($http_code); - - $body = substr($s, strlen($header)); - - $a->set_curl_headers($header); - - curl_close($ch); - - $a->save_timestamp($stamp1, 'network'); - - logger('post_url: end ' . $url, LOGGER_DATA); - - return $body; -} - -// Generic XML return -// Outputs a basic dfrn XML status structure to STDOUT, with a variable -// of $st and an optional text of $message and terminates the current process. - -function xml_status($st, $message = '') -{ - $result = ['status' => $st]; - - if ($message != '') { - $result['message'] = $message; - } - - if ($st) { - logger('xml_status returning non_zero: ' . $st . " message=" . $message); - } - - header("Content-type: text/xml"); - - $xmldata = ["result" => $result]; - - echo XML::fromArray($xmldata, $xml); - - killme(); -} - -/** - * @brief Send HTTP status header and exit. - * - * @param integer $val HTTP status result value - * @param array $description optional message - * 'title' => header title - * 'description' => optional message - */ - -/** - * @brief Send HTTP status header and exit. - * - * @param integer $val HTTP status result value - * @param array $description optional message - * 'title' => header title - * 'description' => optional message - */ -function http_status_exit($val, $description = []) -{ - $err = ''; - if ($val >= 400) { - $err = 'Error'; - if (!isset($description["title"])) { - $description["title"] = $err." ".$val; - } - } - if ($val >= 200 && $val < 300) - $err = 'OK'; - - logger('http_status_exit ' . $val); - header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err); - - if (isset($description["title"])) { - $tpl = get_markup_template('http_status.tpl'); - echo replace_macros( - $tpl, - [ - '$title' => $description["title"], - '$description' => $description["description"]] - ); - } - - killme(); -} - -/** - * @brief Check URL to se if ts's real - * - * Take a URL from the wild, prepend http:// if necessary - * and check DNS to see if it's real (or check if is a valid IP address) - * - * @param string $url The URL to be validated - * @return string|boolean The actual working URL, false else - */ -function validate_url($url) -{ - if (Config::get('system', 'disable_url_validation')) { - return $url; - } - - // no naked subdomains (allow localhost for tests) - if (strpos($url, '.') === false && strpos($url, '/localhost/') === false) { - return false; - } - - if (substr($url, 0, 4) != 'http') { - $url = 'http://' . $url; - } - - /// @TODO Really suppress function outcomes? Why not find them + debug them? - $h = @parse_url($url); - - if ((is_array($h)) && (@dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { - return $url; - } - - return false; -} - -/** - * @brief Checks that email is an actual resolvable internet address - * - * @param string $addr The email address - * @return boolean True if it's a valid email address, false if it's not - */ -function validate_email($addr) -{ - if (Config::get('system', 'disable_email_validation')) { - return true; - } - - if (! strpos($addr, '@')) { - return false; - } - - $h = substr($addr, strpos($addr, '@') + 1); - - if (($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX) || filter_var($h, FILTER_VALIDATE_IP) )) { - return true; - } - return false; -} - -/** - * @brief Check if URL is allowed - * - * Check $url against our list of allowed sites, - * wildcards allowed. If allowed_sites is unset return true; - * - * @param string $url URL which get tested - * @return boolean True if url is allowed otherwise return false - */ -function allowed_url($url) -{ - $h = @parse_url($url); - - if (! $h) { - return false; - } - - $str_allowed = Config::get('system', 'allowed_sites'); - if (! $str_allowed) { - return true; - } - - $found = false; - - $host = strtolower($h['host']); - - // always allow our own site - if ($host == strtolower($_SERVER['SERVER_NAME'])) { - return true; - } - - $fnmatch = function_exists('fnmatch'); - $allowed = explode(',', $str_allowed); - - if (count($allowed)) { - foreach ($allowed as $a) { - $pat = strtolower(trim($a)); - if (($fnmatch && fnmatch($pat, $host)) || ($pat == $host)) { - $found = true; - break; - } - } - } - return $found; -} - -/** - * Checks if the provided url domain is on the domain blocklist. - * Returns true if it is or malformed URL, false if not. - * - * @param string $url The url to check the domain from - * - * @return boolean - */ -function blocked_url($url) -{ - $h = @parse_url($url); - - if (! $h) { - return true; - } - - $domain_blocklist = Config::get('system', 'blocklist', []); - if (! $domain_blocklist) { - return false; - } - - $host = strtolower($h['host']); - - foreach ($domain_blocklist as $domain_block) { - if (strtolower($domain_block['domain']) == $host) { - return true; - } - } - - return false; -} - -/** - * @brief Check if email address is allowed to register here. - * - * Compare against our list (wildcards allowed). - * - * @param string $email email address - * @return boolean False if not allowed, true if allowed - * or if allowed list is not configured - */ -function allowed_email($email) -{ - $domain = strtolower(substr($email, strpos($email, '@') + 1)); - if (!$domain) { - return false; - } - - $str_allowed = Config::get('system', 'allowed_email', ''); - if (!x($str_allowed)) { - return true; - } - - $allowed = explode(',', $str_allowed); - - return allowed_domain($domain, $allowed); -} - -/** - * Checks for the existence of a domain in a domain list - * - * @brief Checks for the existence of a domain in a domain list - * @param string $domain - * @param array $domain_list - * @return boolean - */ -function allowed_domain($domain, array $domain_list) -{ - $found = false; - - foreach ($domain_list as $item) { - $pat = strtolower(trim($item)); - if (fnmatch($pat, $domain) || ($pat == $domain)) { - $found = true; - break; - } - } - - return $found; -} - -function avatar_img($email) -{ - $avatar['size'] = 175; - $avatar['email'] = $email; - $avatar['url'] = ''; - $avatar['success'] = false; - - Addon::callHooks('avatar_lookup', $avatar); - - if (! $avatar['success']) { - $avatar['url'] = System::baseUrl() . '/images/person-175.jpg'; - } - - logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); - return $avatar['url']; -} - - -function parse_xml_string($s, $strict = true) -{ - // the "strict" parameter is deactivated - - /// @todo Move this function to the xml class - libxml_use_internal_errors(true); - - $x = @simplexml_load_string($s); - if (!$x) { - logger('libxml: parse: error: ' . $s, LOGGER_DATA); - foreach (libxml_get_errors() as $err) { - logger('libxml: parse: ' . $err->code." at ".$err->line.":".$err->column." : ".$err->message, LOGGER_DATA); - } - libxml_clear_errors(); - } - return $x; -} - -function scale_external_images($srctext, $include_link = true, $scale_replace = false) -{ - // Suppress "view full size" - if (intval(Config::get('system', 'no_view_full_size'))) { - $include_link = false; - } - - // Picture addresses can contain special characters - $s = htmlspecialchars_decode($srctext); - - $matches = null; - $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER); - if ($c) { - foreach ($matches as $mtch) { - logger('scale_external_image: ' . $mtch[1]); - - $hostname = str_replace('www.', '', substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3)); - if (stristr($mtch[1], $hostname)) { - continue; - } - - // $scale_replace, if passed, is an array of two elements. The - // first is the name of the full-size image. The second is the - // name of a remote, scaled-down version of the full size image. - // This allows Friendica to display the smaller remote image if - // one exists, while still linking to the full-size image - if ($scale_replace) { - $scaled = str_replace($scale_replace[0], $scale_replace[1], $mtch[1]); - } else { - $scaled = $mtch[1]; - } - $i = fetch_url($scaled); - if (! $i) { - return $srctext; - } - - // guess mimetype from headers or filename - $type = Image::guessType($mtch[1], true); - - if ($i) { - $Image = new Image($i, $type); - if ($Image->isValid()) { - $orig_width = $Image->getWidth(); - $orig_height = $Image->getHeight(); - - if ($orig_width > 640 || $orig_height > 640) { - $Image->scaleDown(640); - $new_width = $Image->getWidth(); - $new_height = $Image->getHeight(); - logger('scale_external_images: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG); - $s = str_replace( - $mtch[0], - '[img=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/img]' - . "\n" . (($include_link) - ? '[url=' . $mtch[1] . ']' . L10n::t('view full size') . '[/url]' . "\n" - : ''), - $s - ); - logger('scale_external_images: new string: ' . $s, LOGGER_DEBUG); - } - } - } - } - } - - // replace the special char encoding - $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8'); - return $s; -} - - -function fix_contact_ssl_policy(&$contact, $new_policy) -{ - $ssl_changed = false; - if ((intval($new_policy) == SSL_POLICY_SELFSIGN || $new_policy === 'self') && strstr($contact['url'], 'https:')) { - $ssl_changed = true; - $contact['url'] = str_replace('https:', 'http:', $contact['url']); - $contact['request'] = str_replace('https:', 'http:', $contact['request']); - $contact['notify'] = str_replace('https:', 'http:', $contact['notify']); - $contact['poll'] = str_replace('https:', 'http:', $contact['poll']); - $contact['confirm'] = str_replace('https:', 'http:', $contact['confirm']); - $contact['poco'] = str_replace('https:', 'http:', $contact['poco']); - } - - if ((intval($new_policy) == SSL_POLICY_FULL || $new_policy === 'full') && strstr($contact['url'], 'http:')) { - $ssl_changed = true; - $contact['url'] = str_replace('http:', 'https:', $contact['url']); - $contact['request'] = str_replace('http:', 'https:', $contact['request']); - $contact['notify'] = str_replace('http:', 'https:', $contact['notify']); - $contact['poll'] = str_replace('http:', 'https:', $contact['poll']); - $contact['confirm'] = str_replace('http:', 'https:', $contact['confirm']); - $contact['poco'] = str_replace('http:', 'https:', $contact['poco']); - } - - if ($ssl_changed) { - $fields = ['url' => $contact['url'], 'request' => $contact['request'], - 'notify' => $contact['notify'], 'poll' => $contact['poll'], - 'confirm' => $contact['confirm'], 'poco' => $contact['poco']]; - dba::update('contact', $fields, ['id' => $contact['id']]); - } -} - -/** - * @brief Remove Google Analytics and other tracking platforms params from URL - * - * @param string $url Any user-submitted URL that may contain tracking params - * @return string The same URL stripped of tracking parameters - */ -function strip_tracking_query_params($url) -{ - $urldata = parse_url($url); - if (is_string($urldata["query"])) { - $query = $urldata["query"]; - parse_str($query, $querydata); - - if (is_array($querydata)) { - foreach ($querydata as $param => $value) { - if (in_array( - $param, - [ - "utm_source", "utm_medium", "utm_term", "utm_content", "utm_campaign", - "wt_mc", "pk_campaign", "pk_kwd", "mc_cid", "mc_eid", - "fb_action_ids", "fb_action_types", "fb_ref", - "awesm", "wtrid", - "woo_campaign", "woo_source", "woo_medium", "woo_content", "woo_term"] - ) - ) { - $pair = $param . "=" . urlencode($value); - $url = str_replace($pair, "", $url); - - // Second try: if the url isn't encoded completely - $pair = $param . "=" . str_replace(" ", "+", $value); - $url = str_replace($pair, "", $url); - - // Third try: Maybey the url isn't encoded at all - $pair = $param . "=" . $value; - $url = str_replace($pair, "", $url); - - $url = str_replace(["?&", "&&"], ["?", ""], $url); - } - } - } - - if (substr($url, -1, 1) == "?") { - $url = substr($url, 0, -1); - } - } - - return $url; -} - -/** - * @brief 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 - */ -function original_url($url, $depth = 1, $fetchbody = false) -{ - $a = get_app(); - - $url = strip_tracking_query_params($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->get_useragent()); - - curl_exec($ch); - $curl_info = @curl_getinfo($ch); - $http_code = $curl_info['http_code']; - curl_close($ch); - - $a->save_timestamp($stamp1, "network"); - - if ($http_code == 0) - return($url); - - if ((($curl_info['http_code'] == "301") || ($curl_info['http_code'] == "302")) - && (($curl_info['redirect_url'] != "") || ($curl_info['location'] != "")) - ) { - if ($curl_info['redirect_url'] != "") { - return(original_url($curl_info['redirect_url'], ++$depth, $fetchbody)); - } else { - return(original_url($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(original_url($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 (($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->get_useragent()); - - $body = curl_exec($ch); - curl_close($ch); - - $a->save_timestamp($stamp1, "network"); - - 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(original_url(substr($value, 4), ++$depth)); - } - } - } - } - - return $url; -} - -function short_link($url) -{ - require_once 'library/slinky.php'; - $slinky = new Slinky($url); - $yourls_url = Config::get('yourls', 'url1'); - if ($yourls_url) { - $yourls_username = Config::get('yourls', 'username1'); - $yourls_password = Config::get('yourls', 'password1'); - $yourls_ssl = Config::get('yourls', 'ssl1'); - $yourls = new Slinky_YourLS(); - $yourls->set('username', $yourls_username); - $yourls->set('password', $yourls_password); - $yourls->set('ssl', $yourls_ssl); - $yourls->set('yourls-url', $yourls_url); - $slinky->set_cascade([$yourls, new Slinky_Ur1ca(), new Slinky_TinyURL()]); - } else { - // setup a cascade of shortening services - // try to get a short link from these services - // in the order ur1.ca, tinyurl - $slinky->set_cascade([new Slinky_Ur1ca(), new Slinky_TinyURL()]); - } - return $slinky->short(); -} - -/** - * @brief Encodes content to json - * - * This function encodes an array to json format - * and adds an application/json HTTP header to the output. - * After finishing the process is getting killed. - * - * @param array $x The input content - */ -function json_return_and_die($x) -{ - header("content-type: application/json"); - echo json_encode($x); - killme(); -} - -/** - * @brief Find the matching part between two url - * - * @param string $url1 - * @param string $url2 - * @return string The matching part - */ -function matching_url($url1, $url2) -{ - if (($url1 == "") || ($url2 == "")) { - return ""; - } - - $url1 = normalise_link($url1); - $url2 = normalise_link($url2); - - $parts1 = parse_url($url1); - $parts2 = parse_url($url2); - - if (!isset($parts1["host"]) || !isset($parts2["host"])) { - return ""; - } - - if ($parts1["scheme"] != $parts2["scheme"]) { - return ""; - } - - if ($parts1["host"] != $parts2["host"]) { - return ""; - } - - if ($parts1["port"] != $parts2["port"]) { - return ""; - } - - $match = $parts1["scheme"]."://".$parts1["host"]; - - if ($parts1["port"]) { - $match .= ":".$parts1["port"]; - } - - $pathparts1 = explode("/", $parts1["path"]); - $pathparts2 = explode("/", $parts2["path"]); - - $i = 0; - $path = ""; - do { - $path1 = $pathparts1[$i]; - $path2 = $pathparts2[$i]; - - if ($path1 == $path2) { - $path .= $path1."/"; - } - } while (($path1 == $path2) && ($i++ <= count($pathparts1))); - - $match .= $path; - - return normalise_link($match); -} - -/** - * @brief Glue url parts together - * - * @param array $parsed URL parts - * - * @return string The glued URL - */ -function unParseUrl($parsed) -{ - $get = function ($key) use ($parsed) { - return isset($parsed[$key]) ? $parsed[$key] : null; - }; - - $pass = $get('pass'); - $user = $get('user'); - $userinfo = $pass !== null ? "$user:$pass" : $user; - $port = $get('port'); - $scheme = $get('scheme'); - $query = $get('query'); - $fragment = $get('fragment'); - $authority = ($userinfo !== null ? $userinfo."@" : '') . - $get('host') . - ($port ? ":$port" : ''); - - return (strlen($scheme) ? $scheme.":" : '') . - (strlen($authority) ? "//".$authority : '') . - $get('path') . - (strlen($query) ? "?".$query : '') . - (strlen($fragment) ? "#".$fragment : ''); -} diff --git a/mod/_well_known.php b/mod/_well_known.php index 4b37c0b97..25289171f 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -2,10 +2,11 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\System; -require_once("mod/hostxrd.php"); -require_once("mod/nodeinfo.php"); -require_once("mod/xrd.php"); +require_once 'mod/hostxrd.php'; +require_once 'mod/nodeinfo.php'; +require_once 'mod/xrd.php'; function _well_known_init(App $a) { @@ -25,7 +26,7 @@ function _well_known_init(App $a) break; } } - http_status_exit(404); + System::httpExit(404); killme(); } diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index a712e439f..3066a871f 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -30,6 +30,8 @@ use Friendica\Model\User; use Friendica\Network\Probe; use Friendica\Protocol\Diaspora; use Friendica\Util\Crypto; +use Friendica\Util\Network; +use Friendica\Util\XML; require_once 'include/enotify.php'; require_once 'include/items.php'; @@ -220,7 +222,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) * */ - $res = post_url($dfrn_confirm, $params, null, $redirects, 120); + $res = Network::post($dfrn_confirm, $params, null, $redirects, 120); logger(' Confirm: received data: ' . $res, LOGGER_DATA); @@ -251,7 +253,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) return; } - $xml = parse_xml_string($res); + $xml = XML::parseString($res); $status = (int) $xml->status; $message = unxmlify($xml->message); // human readable text of what may have gone wrong. switch ($status) { @@ -492,7 +494,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) $user = dba::selectFirst('user', [], ['nickname' => $node]); if (!DBM::is_result($user)) { $message = L10n::t('No user record found for \'%s\' ', $node); - xml_status(3, $message); // failure + System::xmlExit(3, $message); // failure // NOTREACHED } @@ -502,7 +504,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) if (!strstr($my_prvkey, 'PRIVATE KEY')) { $message = L10n::t('Our site encryption key is apparently messed up.'); - xml_status(3, $message); + System::xmlExit(3, $message); } // verify everything @@ -513,7 +515,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) if (!strlen($decrypted_source_url)) { $message = L10n::t('Empty site URL was provided or URL could not be decrypted by us.'); - xml_status(3, $message); + System::xmlExit(3, $message); // NOTREACHED } @@ -529,7 +531,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) if (!DBM::is_result($contact)) { // this is either a bogus confirmation (?) or we deleted the original introduction. $message = L10n::t('Contact record was not found for you on our site.'); - xml_status(3, $message); + System::xmlExit(3, $message); return; // NOTREACHED } } @@ -543,7 +545,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) if (!$foreign_pubkey) { $message = L10n::t('Site public key not available in contact record for URL %s.', $decrypted_source_url); - xml_status(3, $message); + System::xmlExit(3, $message); } $decrypted_dfrn_id = ""; @@ -559,7 +561,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) if (dba::exists('contact', ['dfrn-id' => $decrypted_dfrn_id])) { $message = L10n::t('The ID provided by your system is a duplicate on our system. It should work if you try again.'); - xml_status(1, $message); // Birthday paradox - duplicate dfrn-id + System::xmlExit(1, $message); // Birthday paradox - duplicate dfrn-id // NOTREACHED } @@ -570,7 +572,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) ); if (!DBM::is_result($r)) { $message = L10n::t('Unable to set your contact credentials on our system.'); - xml_status(3, $message); + System::xmlExit(3, $message); } // It's possible that the other person also requested friendship. @@ -625,7 +627,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) ); if (!DBM::is_result($r)) { // indicates schema is messed up or total db failure $message = L10n::t('Unable to update your contact profile details on our system'); - xml_status(3, $message); + System::xmlExit(3, $message); } // Otherwise everything seems to have worked and we are almost done. Yay! @@ -706,7 +708,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) } } } - xml_status(0); // Success + System::xmlExit(0); // Success return; // NOTREACHED ////////////////////// End of this scenario /////////////////////////////////////////////// } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 8903d66e3..2f4edafc5 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Protocol\DFRN; @@ -48,7 +49,7 @@ function dfrn_notify_post(App $a) { ); if (! DBM::is_result($r)) { logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge); - xml_status(3, 'Could not match challenge'); + System::xmlExit(3, 'Could not match challenge'); } $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s'", @@ -70,7 +71,7 @@ function dfrn_notify_post(App $a) { $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id)); break; default: - xml_status(3, 'Invalid direction'); + System::xmlExit(3, 'Invalid direction'); break; // NOTREACHED } @@ -96,7 +97,7 @@ function dfrn_notify_post(App $a) { if (! DBM::is_result($r)) { logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id); - xml_status(3, 'Contact not found'); + System::xmlExit(3, 'Contact not found'); //NOTREACHED } @@ -122,7 +123,7 @@ function dfrn_notify_post(App $a) { // if contact's ssl policy changed, update our links - fix_contact_ssl_policy($importer,$ssl_policy); + $importer = Contact::updateSslPolicy($importer, $ssl_policy); logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']); logger('dfrn_notify: data: ' . $data, LOGGER_DATA); @@ -131,7 +132,7 @@ function dfrn_notify_post(App $a) { // Relationship is dissolved permanently Contact::remove($importer['id']); logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']); - xml_status(0, 'relationship dissolved'); + System::xmlExit(0, 'relationship dissolved'); } $rino = Config::get('system', 'rino_encrypt'); @@ -145,7 +146,7 @@ function dfrn_notify_post(App $a) { // but only for $remote_rino > 1, because old code did't send rino version if ($rino_remote > 1 && $rino < $rino_remote) { logger("rino version '$rino_remote' is lower than supported '$rino'"); - xml_status(0, "rino version '$rino_remote' is lower than supported '$rino'"); + System::xmlExit(0, "rino version '$rino_remote' is lower than supported '$rino'"); } $rawkey = hex2bin(trim($key)); @@ -175,14 +176,14 @@ function dfrn_notify_post(App $a) { break; default: logger("rino: invalid sent version '$rino_remote'"); - xml_status(0, "Invalid sent version '$rino_remote'"); + System::xmlExit(0, "Invalid sent version '$rino_remote'"); } logger('rino: decrypted data: ' . $data, LOGGER_DATA); } $ret = DFRN::import($data, $importer); - xml_status($ret, 'Processed'); + System::xmlExit($ret, 'Processed'); // NOTREACHED } diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index e5ca96934..7d5418c36 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -11,6 +11,8 @@ use Friendica\Database\DBM; use Friendica\Module\Login; use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; +use Friendica\Util\Network; +use Friendica\Util\XML; require_once 'include/items.php'; @@ -47,7 +49,7 @@ function dfrn_poll_init(App $a) if (($dfrn_id === '') && (!x($_POST, 'dfrn_id'))) { if (Config::get('system', 'block_public') && !local_user() && !remote_user()) { - http_status_exit(403); + System::httpExit(403); } $user = ''; @@ -56,7 +58,7 @@ function dfrn_poll_init(App $a) dbesc($a->argv[1]) ); if (!$r) { - http_status_exit(404); + System::httpExit(404); } $hidewall = ($r[0]['hidewall'] && !local_user()); @@ -98,12 +100,12 @@ function dfrn_poll_init(App $a) ); if (DBM::is_result($r)) { - $s = fetch_url($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check'); + $s = Network::fetchUrl($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check'); logger("dfrn_poll: old profile returns " . $s, LOGGER_DATA); if (strlen($s)) { - $xml = parse_xml_string($s); + $xml = XML::parseString($s); if ((int) $xml->status === 1) { $_SESSION['authenticated'] = 1; @@ -143,7 +145,7 @@ function dfrn_poll_init(App $a) dbesc($sec) ); if (!DBM::is_result($r)) { - xml_status(3, 'No ticket'); + System::xmlExit(3, 'No ticket'); // NOTREACHED } @@ -156,7 +158,7 @@ function dfrn_poll_init(App $a) intval($r[0]['cid']) ); if (!DBM::is_result($c)) { - xml_status(3, 'No profile'); + System::xmlExit(3, 'No profile'); } $contact = $c[0]; @@ -183,7 +185,7 @@ function dfrn_poll_init(App $a) if ($final_dfrn_id != $orig_id) { logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG); // did not decode properly - cannot trust this site - xml_status(3, 'Bad decryption'); + System::xmlExit(3, 'Bad decryption'); } header("Content-type: text/xml"); @@ -207,10 +209,10 @@ function dfrn_poll_init(App $a) $r = q("SELECT * FROM `profile_check` WHERE `dfrn_id` = '%s' ORDER BY `expire` DESC", dbesc($dfrn_id)); if (DBM::is_result($r)) { - xml_status(1); + System::xmlExit(1); return; // NOTREACHED } - xml_status(0); + System::xmlExit(0); return; // NOTREACHED } } @@ -235,7 +237,7 @@ function dfrn_poll_post(App $a) dbesc($sec) ); if (!DBM::is_result($r)) { - xml_status(3, 'No ticket'); + System::xmlExit(3, 'No ticket'); // NOTREACHED } @@ -248,7 +250,7 @@ function dfrn_poll_post(App $a) intval($r[0]['cid']) ); if (!DBM::is_result($c)) { - xml_status(3, 'No profile'); + System::xmlExit(3, 'No profile'); } $contact = $c[0]; @@ -275,7 +277,7 @@ function dfrn_poll_post(App $a) if ($final_dfrn_id != $orig_id) { logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG); // did not decode properly - cannot trust this site - xml_status(3, 'Bad decryption'); + System::xmlExit(3, 'Bad decryption'); } header("Content-type: text/xml"); @@ -481,7 +483,7 @@ function dfrn_poll_content(App $a) if (($type === 'profile') && (strlen($sec))) { // URL reply if ($dfrn_version < 2.2) { - $s = fetch_url($r[0]['poll'] + $s = Network::fetchUrl($r[0]['poll'] . '?dfrn_id=' . $encrypted_id . '&type=profile-check' . '&dfrn_version=' . DFRN_PROTOCOL_VERSION @@ -489,7 +491,7 @@ function dfrn_poll_content(App $a) . '&sec=' . $sec ); } else { - $s = post_url($r[0]['poll'], [ + $s = Network::post($r[0]['poll'], [ 'dfrn_id' => $encrypted_id, 'type' => 'profile-check', 'dfrn_version' => DFRN_PROTOCOL_VERSION, @@ -520,7 +522,7 @@ function dfrn_poll_content(App $a) logger("dfrn_poll: sec profile: " . $s, LOGGER_DATA); if (strlen($s) && strstr($s, 'cmd); return; // NOTREACHED } - if (!allowed_url($url)) { + if (!Network::isUrlAllowed($url)) { notice(L10n::t('Disallowed profile URL.') . EOL); goaway(System::baseUrl() . '/' . $a->cmd); return; // NOTREACHED } - if (blocked_url($url)) { + if (Network::isUrlBlocked($url)) { notice(L10n::t('Blocked domain') . EOL); goaway(System::baseUrl() . '/' . $a->cmd); return; // NOTREACHED diff --git a/mod/dirfind.php b/mod/dirfind.php index f1119a297..9db4eeb7b 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -14,6 +14,7 @@ use Friendica\Model\GContact; use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; +use Friendica\Util\Network; require_once 'mod/contacts.php'; @@ -45,7 +46,7 @@ function dirfind_content(App $a, $prefix = "") { if (strpos($search,'@') === 0) { $search = substr($search,1); $header = L10n::t('People Search - %s', $search); - if ((valid_email($search) && validate_email($search)) || + if ((valid_email($search) && Network::isEmailDomainValid($search)) || (substr(normalise_link($search), 0, 7) == "http://")) { $user_data = Probe::uri($search); $discover_user = (in_array($user_data["network"], [NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA])); @@ -177,7 +178,7 @@ function dirfind_content(App $a, $prefix = "") { $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : ''); if(strlen(Config::get('system','directory'))) - $x = fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search)); + $x = Network::fetchUrl(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search)); $j = json_decode($x); } diff --git a/mod/display.php b/mod/display.php index d62b398a7..8d991d476 100644 --- a/mod/display.php +++ b/mod/display.php @@ -423,7 +423,7 @@ function display_content(App $a, $update = false, $update_uid = 0) { function displayShowFeed($item_id, $conversation) { $xml = DFRN::itemFeed($item_id, $conversation); if ($xml == '') { - http_status_exit(500); + System::httpExit(500); } header("Content-type: application/atom+xml"); echo $xml; diff --git a/mod/hovercard.php b/mod/hovercard.php index 334bf228a..01d9feb1e 100644 --- a/mod/hovercard.php +++ b/mod/hovercard.php @@ -9,6 +9,7 @@ */ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\System; use Friendica\Model\Contact; use Friendica\Model\GContact; use Friendica\Model\Profile; @@ -26,7 +27,7 @@ function hovercard_content() // Get out if the system doesn't have public access allowed if (intval(Config::get('system', 'block_public'))) { - http_status_exit(401); + System::httpExit(401); } // Return the raw content of the template. We use this to make templates usable for js functions. @@ -90,7 +91,7 @@ function hovercard_content() return $o; } else { - json_return_and_die($profile); + System::jsonExit($profile); } } diff --git a/mod/install.php b/mod/install.php index cbad3b254..c5f2e985f 100644 --- a/mod/install.php +++ b/mod/install.php @@ -8,6 +8,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Database\DBStructure; use Friendica\Object\Image; +use Friendica\Util\Network; $install_wizard_pass = 1; @@ -482,10 +483,10 @@ function check_htaccess(&$checks) { $status = true; $help = ""; if (function_exists('curl_init')) { - $test = fetch_url(System::baseUrl()."/install/testrewrite"); + $test = Network::fetchUrl(System::baseUrl()."/install/testrewrite"); if ($test != "ok") { - $test = fetch_url(normalise_link(System::baseUrl()."/install/testrewrite")); + $test = Network::fetchUrl(normalise_link(System::baseUrl()."/install/testrewrite")); } if ($test != "ok") { diff --git a/mod/item.php b/mod/item.php index d1186a2a0..1a512acec 100644 --- a/mod/item.php +++ b/mod/item.php @@ -519,7 +519,7 @@ function item_post(App $a) { // Fold multi-line [code] sequences $body = preg_replace('/\[\/code\]\s*\[code\]/ism', "\n", $body); - $body = scale_external_images($body, false); + $body = BBCode::scaleExternalImages($body, false); // Setting the object type if not defined before if (!$objecttype) { diff --git a/mod/match.php b/mod/match.php index 47b24e9f7..c5e35031f 100644 --- a/mod/match.php +++ b/mod/match.php @@ -10,6 +10,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Model\Profile; +use Friendica\Util\Network; require_once 'include/text.php'; require_once 'mod/proxy.php'; @@ -58,9 +59,9 @@ function match_content(App $a) } if (strlen(Config::get('system', 'directory'))) { - $x = post_url(get_server().'/msearch', $params); + $x = Network::post(get_server().'/msearch', $params); } else { - $x = post_url(System::baseUrl() . '/msearch', $params); + $x = Network::post(System::baseUrl() . '/msearch', $params); } $j = json_decode($x); diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index bcaf8e7a9..5cadc41c4 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Addon; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Util\Network; function nodeinfo_wellknown(App $a) { $nodeinfo = ['links' => [['rel' => 'http://nodeinfo.diaspora.software/ns/schema/1.0', @@ -21,12 +22,12 @@ function nodeinfo_wellknown(App $a) { function nodeinfo_init(App $a) { if (!Config::get('system', 'nodeinfo')) { - http_status_exit(404); + System::httpExit(404); killme(); } if (($a->argc != 2) || ($a->argv[1] != '1.0')) { - http_status_exit(404); + System::httpExit(404); killme(); } @@ -246,7 +247,7 @@ function nodeinfo_cron() { // Now trying to register $url = 'http://the-federation.info/register/'.$a->get_hostname(); logger('registering url: '.$url, LOGGER_DEBUG); - $ret = fetch_url($url); + $ret = Network::fetchUrl($url); logger('registering answer: '.$ret, LOGGER_DEBUG); logger('cron_end'); diff --git a/mod/notifications.php b/mod/notifications.php index 64fb52742..46519075b 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -11,8 +11,6 @@ use Friendica\Core\NotificationsManager; use Friendica\Core\System; use Friendica\Database\DBM; -require_once "include/network.php"; - function notifications_post(App $a) { if (! local_user()) { @@ -139,8 +137,9 @@ function notifications_content(App $a) { $notifs['page'] = $a->pager['page']; // Json output - if(intval($json) === 1) - json_return_and_die($notifs); + if (intval($json) === 1) { + System::jsonExit($notifs); + } $notif_tpl = get_markup_template('notifications.tpl'); diff --git a/mod/oexchange.php b/mod/oexchange.php index 902499c03..feca39d35 100644 --- a/mod/oexchange.php +++ b/mod/oexchange.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Module\Login; +use Friendica\Util\Network; function oexchange_init(App $a) { @@ -39,7 +40,7 @@ function oexchange_content(App $a) { $tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags'])) ? '&tags=' . urlencode(notags(trim($_REQUEST['tags']))) : ''); - $s = fetch_url(System::baseUrl() . '/parse_url?f=&url=' . $url . $title . $description . $tags); + $s = Network::fetchUrl(System::baseUrl() . '/parse_url?f=&url=' . $url . $title . $description . $tags); if (! strlen($s)) { return; diff --git a/mod/ostatus_subscribe.php b/mod/ostatus_subscribe.php index 295ccfee6..07f4647e6 100644 --- a/mod/ostatus_subscribe.php +++ b/mod/ostatus_subscribe.php @@ -8,6 +8,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Model\Contact; use Friendica\Network\Probe; +use Friendica\Util\Network; function ostatus_subscribe_content(App $a) { @@ -40,7 +41,7 @@ function ostatus_subscribe_content(App $a) { $api = $contact["baseurl"]."/api/"; // Fetching friends - $data = z_fetch_url($api."statuses/friends.json?screen_name=".$contact["nick"]); + $data = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]); if (!$data["success"]) { return $o.L10n::t("Couldn't fetch friends for contact."); diff --git a/mod/parse_url.php b/mod/parse_url.php index 6fb404f1b..ea860f6d3 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -12,6 +12,7 @@ use Friendica\App; use Friendica\Core\Addon; +use Friendica\Util\Network; use Friendica\Util\ParseUrl; require_once("include/items.php"); @@ -60,7 +61,7 @@ function parse_url_content(App $a) { // the URL with the corresponding BBCode media tag $redirects = 0; // Fetch the header of the URL - $result = z_fetch_url($url, false, $redirects, ["novalidate" => true, "nobody" => true]); + $result = Network::curl($url, false, $redirects, ["novalidate" => true, "nobody" => true]); if($result["success"]) { // Convert the header fields into an array $hdrs = []; diff --git a/mod/poco.php b/mod/poco.php index 761a9c2b8..c27cd7c49 100644 --- a/mod/poco.php +++ b/mod/poco.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Core\Cache; use Friendica\Core\Config; +use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Protocol\PortableContact; @@ -13,7 +14,7 @@ function poco_init(App $a) { $system_mode = false; if (intval(Config::get('system', 'block_public')) || (Config::get('system', 'block_local_dir'))) { - http_status_exit(401); + System::httpExit(401); } if ($a->argc > 1) { @@ -22,7 +23,7 @@ function poco_init(App $a) { if (! x($user)) { $c = q("SELECT * FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1"); if (! DBM::is_result($c)) { - http_status_exit(401); + System::httpExit(401); } $system_mode = true; } @@ -63,7 +64,7 @@ function poco_init(App $a) { dbesc($user) ); if (! DBM::is_result($users) || $users[0]['hidewall'] || $users[0]['hide-friends']) { - http_status_exit(404); + System::httpExit(404); } $user = $users[0]; @@ -357,7 +358,7 @@ function poco_init(App $a) { $ret['entry'][] = []; } } else { - http_status_exit(500); + System::httpExit(500); } logger("End of poco", LOGGER_DEBUG); @@ -371,6 +372,6 @@ function poco_init(App $a) { echo json_encode($ret); killme(); } else { - http_status_exit(500); + System::httpExit(500); } } diff --git a/mod/probe.php b/mod/probe.php index deb80c0de..b4f6ff3a4 100644 --- a/mod/probe.php +++ b/mod/probe.php @@ -4,12 +4,13 @@ */ use Friendica\App; use Friendica\Core\L10n; +use Friendica\Core\System; use Friendica\Network\Probe; function probe_content(App $a) { if (!local_user()) { - http_status_exit(403, ["title" => L10n::t("Public access denied."), + System::httpExit(403, ["title" => L10n::t("Public access denied."), "description" => L10n::t("Only logged in users are permitted to perform a probing.")]); killme(); } diff --git a/mod/proxy.php b/mod/proxy.php index 538275ef0..7efc0ffba 100644 --- a/mod/proxy.php +++ b/mod/proxy.php @@ -10,6 +10,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Photo; use Friendica\Object\Image; +use Friendica\Util\Network; define('PROXY_DEFAULT_TIME', 86400); // 1 Day @@ -161,7 +162,7 @@ function proxy_init(App $a) { // It shouldn't happen but it does - spaces in URL $_REQUEST['url'] = str_replace(' ', '+', $_REQUEST['url']); $redirects = 0; - $img_str = fetch_url($_REQUEST['url'], true, $redirects, 10); + $img_str = Network::fetchUrl($_REQUEST['url'], true, $redirects, 10); $tempfile = tempnam(get_temppath(), 'cache'); file_put_contents($tempfile, $img_str); diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php index f3134308f..ac85657dd 100644 --- a/mod/pubsubhubbub.php +++ b/mod/pubsubhubbub.php @@ -2,7 +2,9 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Util\Network; function post_var($name) { return (x($_POST, $name)) ? notags(trim($_POST[$name])) : ''; @@ -12,7 +14,7 @@ function pubsubhubbub_init(App $a) { // PuSH subscription must be considered "public" so just block it // if public access isn't enabled. if (Config::get('system', 'block_public')) { - http_status_exit(403); + System::httpExit(403); } // Subscription request from subscriber @@ -40,7 +42,7 @@ function pubsubhubbub_init(App $a) { $subscribe = 0; } else { logger("pubsubhubbub: invalid hub_mode=$hub_mode, ignoring."); - http_status_exit(404); + System::httpExit(404); } logger("pubsubhubbub: $hub_mode request from " . @@ -56,7 +58,7 @@ function pubsubhubbub_init(App $a) { if (!$nick) { logger('pubsubhubbub: bad hub_topic=$hub_topic, ignoring.'); - http_status_exit(404); + System::httpExit(404); } // fetch user from database given the nickname @@ -66,7 +68,7 @@ function pubsubhubbub_init(App $a) { if (!DBM::is_result($r)) { logger('pubsubhubbub: local account not found: ' . $nick); - http_status_exit(404); + System::httpExit(404); } $owner = $r[0]; @@ -75,7 +77,7 @@ function pubsubhubbub_init(App $a) { if ($r[0]['hidewall']) { logger('pubsubhubbub: local user ' . $nick . 'has chosen to hide wall, ignoring.'); - http_status_exit(403); + System::httpExit(403); } // get corresponding row from contact table @@ -84,7 +86,7 @@ function pubsubhubbub_init(App $a) { intval($owner['uid'])); if (!DBM::is_result($r)) { logger('pubsubhubbub: contact not found.'); - http_status_exit(404); + System::httpExit(404); } $contact = $r[0]; @@ -93,7 +95,7 @@ function pubsubhubbub_init(App $a) { if (!link_compare($hub_topic, $contact['poll'])) { logger('pubsubhubbub: hub topic ' . $hub_topic . ' != ' . $contact['poll']); - http_status_exit(404); + System::httpExit(404); } // do subscriber verification according to the PuSH protocol @@ -109,14 +111,14 @@ function pubsubhubbub_init(App $a) { // we don't actually enforce the lease time because GNU // Social/StatusNet doesn't honour it (yet) - $body = fetch_url($hub_callback . "?" . $params); + $body = Network::fetchUrl($hub_callback . "?" . $params); $ret = $a->get_curl_code(); // give up if the HTTP return code wasn't a success (2xx) if ($ret < 200 || $ret > 299) { logger("pubsubhubbub: subscriber verification at $hub_callback ". "returned $ret, ignoring."); - http_status_exit(404); + System::httpExit(404); } // check that the correct hub_challenge code was echoed back @@ -124,7 +126,7 @@ function pubsubhubbub_init(App $a) { logger("pubsubhubbub: subscriber did not echo back ". "hub.challenge, ignoring."); logger("\"$hub_challenge\" != \"".trim($body)."\""); - http_status_exit(404); + System::httpExit(404); } // fetch the old subscription if it exists @@ -162,7 +164,7 @@ function pubsubhubbub_init(App $a) { logger("pubsubhubbub: successfully unsubscribed [$hub_callback]."); // we do nothing here, since the row was already deleted } - http_status_exit(202); + System::httpExit(202); } killme(); diff --git a/mod/receive.php b/mod/receive.php index 0c7a7e095..41f2225cb 100644 --- a/mod/receive.php +++ b/mod/receive.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Protocol\Diaspora; @@ -18,7 +19,7 @@ function receive_post(App $a) $enabled = intval(Config::get('system', 'diaspora_enabled')); if (!$enabled) { logger('mod-diaspora: disabled'); - http_status_exit(500); + System::httpExit(500); } if (($a->argc == 2) && ($a->argv[1] === 'public')) { @@ -28,13 +29,13 @@ function receive_post(App $a) $public = false; if ($a->argc != 3 || $a->argv[1] !== 'users') { - http_status_exit(500); + System::httpExit(500); } $guid = $a->argv[2]; $importer = dba::selectFirst('user', [], ['guid' => $guid, 'account_expired' => false, 'account_removed' => false]); if (!DBM::is_result($importer)) { - http_status_exit(500); + System::httpExit(500); } } @@ -47,7 +48,7 @@ function receive_post(App $a) if (!$xml) { $postdata = file_get_contents("php://input"); if ($postdata == '') { - http_status_exit(500); + System::httpExit(500); } logger('mod-diaspora: message is in the new format', LOGGER_DEBUG); @@ -67,7 +68,7 @@ function receive_post(App $a) logger('mod-diaspora: decoded msg: ' . print_r($msg, true), LOGGER_DATA); if (!is_array($msg)) { - http_status_exit(500); + System::httpExit(500); } logger('mod-diaspora: dispatching', LOGGER_DEBUG); @@ -79,6 +80,6 @@ function receive_post(App $a) $ret = Diaspora::dispatch($importer, $msg); } - http_status_exit(($ret) ? 200 : 500); + System::httpExit(($ret) ? 200 : 500); // NOTREACHED } diff --git a/mod/salmon.php b/mod/salmon.php index d5b0fe243..af8f5fa55 100644 --- a/mod/salmon.php +++ b/mod/salmon.php @@ -4,6 +4,7 @@ */ use Friendica\App; use Friendica\Core\PConfig; +use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Protocol\OStatus; @@ -38,7 +39,7 @@ function salmon_post(App $a) { dbesc($nick) ); if (! DBM::is_result($r)) { - http_status_exit(500); + System::httpExit(500); } $importer = $r[0]; @@ -58,7 +59,7 @@ function salmon_post(App $a) { if(! $base) { logger('mod-salmon: unable to locate salmon data in xml '); - http_status_exit(400); + System::httpExit(400); } // Stash the signature away for now. We have to find their key or it won't be good for anything. @@ -96,7 +97,7 @@ function salmon_post(App $a) { if(! $author_link) { logger('mod-salmon: Could not retrieve author URI.'); - http_status_exit(400); + System::httpExit(400); } // Once we have the author URI, go to the web and try to find their public key @@ -107,7 +108,7 @@ function salmon_post(App $a) { if(! $key) { logger('mod-salmon: Could not retrieve author key.'); - http_status_exit(400); + System::httpExit(400); } $key_info = explode('.',$key); @@ -139,7 +140,7 @@ function salmon_post(App $a) { if (! $verify) { logger('mod-salmon: Message did not verify. Discarding.'); - http_status_exit(400); + System::httpExit(400); } logger('mod-salmon: Message verified with mode '.$mode); @@ -183,7 +184,7 @@ function salmon_post(App $a) { //if((DBM::is_result($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) { if (DBM::is_result($r) && $r[0]['blocked']) { logger('mod-salmon: Ignoring this author.'); - http_status_exit(202); + System::httpExit(202); // NOTREACHED } @@ -194,5 +195,5 @@ function salmon_post(App $a) { OStatus::import($data, $importer, $contact_rec, $hub); - http_status_exit(200); + System::httpExit(200); } diff --git a/mod/search.php b/mod/search.php index b48fafe78..c1990bf87 100644 --- a/mod/search.php +++ b/mod/search.php @@ -8,6 +8,7 @@ use Friendica\Content\Nav; use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\L10n; +use Friendica\Core\System; use Friendica\Database\DBM; require_once "include/bbcode.php"; @@ -99,7 +100,7 @@ function search_content(App $a) { } if (Config::get('system','local_search') && !local_user() && !remote_user()) { - http_status_exit(403, + System::httpExit(403, ["title" => L10n::t("Public access denied."), "description" => L10n::t("Only logged in users are permitted to perform a search.")]); killme(); @@ -124,7 +125,7 @@ function search_content(App $a) { if (!is_null($result)) { $resultdata = json_decode($result); if (($resultdata->time > (time() - $crawl_permit_period)) && ($resultdata->accesses > $free_crawls)) { - http_status_exit(429, + System::httpExit(429, ["title" => L10n::t("Too Many Requests"), "description" => L10n::t("Only one search per minute is permitted for not logged in users.")]); killme(); diff --git a/mod/settings.php b/mod/settings.php index 5b4bd903e..2ea6d5334 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -17,6 +17,7 @@ use Friendica\Model\GContact; use Friendica\Model\Group; use Friendica\Model\User; use Friendica\Protocol\Email; +use Friendica\Util\Network; function get_theme_config_file($theme) { @@ -535,7 +536,7 @@ function settings_post(App $a) // If openid has changed or if there's an openid but no openidserver, try and discover it. if ($openid != $a->user['openid'] || (strlen($openid) && (!strlen($openidserver)))) { - if (validate_url($openid)) { + if (Network::isUrlValid($openid)) { logger('updating openidserver'); require_once 'library/openid.php'; $open_id_obj = new LightOpenID; diff --git a/mod/smilies.php b/mod/smilies.php index d96a4bfc6..a33cbf6ad 100644 --- a/mod/smilies.php +++ b/mod/smilies.php @@ -1,10 +1,10 @@ $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]]; } - json_return_and_die($results); + System::jsonExit($results); } else { return Smilies::replace('', true); } diff --git a/mod/statistics_json.php b/mod/statistics_json.php index f2c6e074f..c035c1c05 100644 --- a/mod/statistics_json.php +++ b/mod/statistics_json.php @@ -7,11 +7,12 @@ use Friendica\App; use Friendica\Core\Addon; use Friendica\Core\Config; +use Friendica\Core\System; function statistics_json_init(App $a) { if (!Config::get("system", "nodeinfo")) { - http_status_exit(404); + System::httpExit(404); killme(); } diff --git a/mod/webfinger.php b/mod/webfinger.php index 3e205ec03..c88679352 100644 --- a/mod/webfinger.php +++ b/mod/webfinger.php @@ -4,12 +4,13 @@ */ use Friendica\App; use Friendica\Core\L10n; +use Friendica\Core\System; use Friendica\Network\Probe; function webfinger_content(App $a) { if (!local_user()) { - http_status_exit( + System::httpExit( 403, [ "title" => L10n::t("Public access denied."), diff --git a/spec/dfrn2_contact_confirmation.svg b/spec/dfrn2_contact_confirmation.svg index bb506a232..fc5b33162 100644 --- a/spec/dfrn2_contact_confirmation.svg +++ b/spec/dfrn2_contact_confirmation.svg @@ -69,7 +69,7 @@ text { font:12px Dialog; } getting transmitted (if $aes_allow -> encrypt the the public key) -> add duplex state and page-flags to the params -> send params to Bobs dfrn_confirm page ($res = -post_url($dfrn_confirm,$params); +Network::post($dfrn_confirm,$params); dfrn_confirm_post() diff --git a/spec/dfrn2_contact_request.svg b/spec/dfrn2_contact_request.svg index e85eaf20b..cc78be55c 100644 --- a/spec/dfrn2_contact_request.svg +++ b/spec/dfrn2_contact_request.svg @@ -93,9 +93,9 @@ text { font:12px Dialog; } - create a contact for Karen in the contact table with the scraped data with blocked = 1 and pending = 1 (Karens pubkey becomes the contact site-pubkey) -- fetch_url($dfrn_request . '?confirm_key=' . +- Network::fetchUrl($dfrn_request . '?confirm_key=' . $confirm_key); -- fetch_url(http://karenhomepage.com/dfrn_request? +- Network::fetchUrl(http://karenhomepage.com/dfrn_request? confirm_key=”ABC123”) diff --git a/src/Content/OEmbed.php b/src/Content/OEmbed.php index 9f1df5174..170ee7ba2 100644 --- a/src/Content/OEmbed.php +++ b/src/Content/OEmbed.php @@ -10,6 +10,7 @@ use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Util\Network; use Friendica\Util\ParseUrl; use dba; use DOMDocument; @@ -77,7 +78,7 @@ class OEmbed if (!in_array($ext, $noexts)) { // try oembed autodiscovery $redirects = 0; - $html_text = fetch_url($embedurl, false, $redirects, 15, "text/*"); + $html_text = Network::fetchUrl($embedurl, false, $redirects, 15, "text/*"); if ($html_text) { $dom = @DOMDocument::loadHTML($html_text); if ($dom) { @@ -85,13 +86,13 @@ class OEmbed $entries = $xpath->query("//link[@type='application/json+oembed']"); foreach ($entries as $e) { $href = $e->getAttributeNode("href")->nodeValue; - $txt = fetch_url($href . '&maxwidth=' . $a->videowidth); + $txt = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); break; } $entries = $xpath->query("//link[@type='text/json+oembed']"); foreach ($entries as $e) { $href = $e->getAttributeNode("href")->nodeValue; - $txt = fetch_url($href . '&maxwidth=' . $a->videowidth); + $txt = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); break; } } @@ -311,7 +312,7 @@ class OEmbed $allowed = explode(',', $str_allowed); - return allowed_domain($domain, $allowed); + return Network::isDomainAllowed($domain, $allowed); } public static function getHTML($url, $title = null) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 9162316d7..8493e41b6 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -6,13 +6,15 @@ namespace Friendica\Content\Text; use Friendica\App; use Friendica\Content\Text\Plaintext; +use Friendica\Core\Config; +use Friendica\Core\L10n; use Friendica\Core\PConfig; +use Friendica\Core\System; use Friendica\Object\Image; use Friendica\Util\ParseUrl; require_once "include/bbcode.php"; require_once "include/html2plain.php"; -require_once "include/network.php"; class BBCode { @@ -476,4 +478,74 @@ class BBCode return($post); } + + public static function scaleExternalImages($srctext, $include_link = true, $scale_replace = false) + { + // Suppress "view full size" + if (intval(Config::get('system', 'no_view_full_size'))) { + $include_link = false; + } + + // Picture addresses can contain special characters + $s = htmlspecialchars_decode($srctext); + + $matches = null; + $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER); + if ($c) { + foreach ($matches as $mtch) { + logger('scale_external_image: ' . $mtch[1]); + + $hostname = str_replace('www.', '', substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3)); + if (stristr($mtch[1], $hostname)) { + continue; + } + + // $scale_replace, if passed, is an array of two elements. The + // first is the name of the full-size image. The second is the + // name of a remote, scaled-down version of the full size image. + // This allows Friendica to display the smaller remote image if + // one exists, while still linking to the full-size image + if ($scale_replace) { + $scaled = str_replace($scale_replace[0], $scale_replace[1], $mtch[1]); + } else { + $scaled = $mtch[1]; + } + $i = self::fetchURL($scaled); + if (! $i) { + return $srctext; + } + + // guess mimetype from headers or filename + $type = Image::guessType($mtch[1], true); + + if ($i) { + $Image = new Image($i, $type); + if ($Image->isValid()) { + $orig_width = $Image->getWidth(); + $orig_height = $Image->getHeight(); + + if ($orig_width > 640 || $orig_height > 640) { + $Image->scaleDown(640); + $new_width = $Image->getWidth(); + $new_height = $Image->getHeight(); + logger('scale_external_images: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG); + $s = str_replace( + $mtch[0], + '[img=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/img]' + . "\n" . (($include_link) + ? '[url=' . $mtch[1] . ']' . L10n::t('view full size') . '[/url]' . "\n" + : ''), + $s + ); + logger('scale_external_images: new string: ' . $s, LOGGER_DEBUG); + } + } + } + } + } + + // replace the special char encoding + $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8'); + return $s; + } } diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index e88b4218b..7c2760a85 100644 --- a/src/Core/NotificationsManager.php +++ b/src/Core/NotificationsManager.php @@ -13,6 +13,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Model\Profile; +use Friendica\Util\XML; require_once 'include/dba.php'; require_once 'include/html2plain.php'; @@ -337,7 +338,7 @@ class NotificationsManager extends BaseObject case ACTIVITY_FRIEND: $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">"; - $obj = parse_xml_string($xmlhead . $it['object']); + $obj = XML::parseString($xmlhead . $it['object']); $it['fname'] = $obj->title; $notif = [ diff --git a/src/Core/System.php b/src/Core/System.php index 469016770..d0eb651e9 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -5,6 +5,7 @@ namespace Friendica\Core; use Friendica\BaseObject; +use Friendica\Util\XML; /** * @file include/Core/System.php @@ -97,6 +98,86 @@ EOT; killme(); } + /** + * Generic XML return + * Outputs a basic dfrn XML status structure to STDOUT, with a variable + * of $st and an optional text of $message and terminates the current process. + */ + public static function xmlExit($st, $message = '') + { + $result = ['status' => $st]; + + if ($message != '') { + $result['message'] = $message; + } + + if ($st) { + logger('xml_status returning non_zero: ' . $st . " message=" . $message); + } + + header("Content-type: text/xml"); + + $xmldata = ["result" => $result]; + + echo XML::fromArray($xmldata, $xml); + + killme(); + } + + /** + * @brief Send HTTP status header and exit. + * + * @param integer $val HTTP status result value + * @param array $description optional message + * 'title' => header title + * 'description' => optional message + */ + public static function httpExit($val, $description = []) + { + $err = ''; + if ($val >= 400) { + $err = 'Error'; + if (!isset($description["title"])) { + $description["title"] = $err." ".$val; + } + } + + if ($val >= 200 && $val < 300) { + $err = 'OK'; + } + + logger('http_status_exit ' . $val); + header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err); + + if (isset($description["title"])) { + $tpl = get_markup_template('http_status.tpl'); + echo replace_macros( + $tpl, + [ + '$title' => $description["title"], + '$description' => $description["description"]] + ); + } + + killme(); + } + + /** + * @brief Encodes content to json + * + * This function encodes an array to json format + * and adds an application/json HTTP header to the output. + * After finishing the process is getting killed. + * + * @param array $x The input content + */ + public static function jsonExit($x) + { + header("content-type: application/json"); + echo json_encode($x); + killme(); + } + /// @todo Move the following functions from boot.php /* function get_guid($size = 16, $prefix = "") diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 893b1bccc..ee313bef0 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -10,7 +10,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Process; use Friendica\Util\Lock; - +use Friendica\Util\Network; use dba; require_once 'include/dba.php'; @@ -888,7 +888,7 @@ class Worker } $url = System::baseUrl()."/worker"; - fetch_url($url, false, $redirects, 1); + Network::fetchUrl($url, false, $redirects, 1); } /** diff --git a/src/Model/Contact.php b/src/Model/Contact.php index acdb4815e..ba9536b39 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -20,6 +20,7 @@ use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; use Friendica\Protocol\PortableContact; use Friendica\Protocol\Salmon; +use Friendica\Util\Network; use dba; require_once 'boot.php'; @@ -1131,12 +1132,12 @@ class Contact extends BaseObject // remove ajax junk, e.g. Twitter $url = str_replace('/#!/', '/', $url); - if (!allowed_url($url)) { + if (!Network::isUrlAllowed($url)) { $result['message'] = L10n::t('Disallowed profile URL.'); return $result; } - if (blocked_url($url)) { + if (Network::isUrlBlocked($url)) { $result['message'] = L10n::t('Blocked domain'); return $result; } @@ -1320,4 +1321,37 @@ class Contact extends BaseObject $result['success'] = true; return $result; } + + public static function updateSslPolicy($contact, $new_policy) + { + $ssl_changed = false; + if ((intval($new_policy) == SSL_POLICY_SELFSIGN || $new_policy === 'self') && strstr($contact['url'], 'https:')) { + $ssl_changed = true; + $contact['url'] = str_replace('https:', 'http:', $contact['url']); + $contact['request'] = str_replace('https:', 'http:', $contact['request']); + $contact['notify'] = str_replace('https:', 'http:', $contact['notify']); + $contact['poll'] = str_replace('https:', 'http:', $contact['poll']); + $contact['confirm'] = str_replace('https:', 'http:', $contact['confirm']); + $contact['poco'] = str_replace('https:', 'http:', $contact['poco']); + } + + if ((intval($new_policy) == SSL_POLICY_FULL || $new_policy === 'full') && strstr($contact['url'], 'http:')) { + $ssl_changed = true; + $contact['url'] = str_replace('http:', 'https:', $contact['url']); + $contact['request'] = str_replace('http:', 'https:', $contact['request']); + $contact['notify'] = str_replace('http:', 'https:', $contact['notify']); + $contact['poll'] = str_replace('http:', 'https:', $contact['poll']); + $contact['confirm'] = str_replace('http:', 'https:', $contact['confirm']); + $contact['poco'] = str_replace('http:', 'https:', $contact['poco']); + } + + if ($ssl_changed) { + $fields = ['url' => $contact['url'], 'request' => $contact['request'], + 'notify' => $contact['notify'], 'poll' => $contact['poll'], + 'confirm' => $contact['confirm'], 'poco' => $contact['poco']]; + dba::update('contact', $fields, ['id' => $contact['id']]); + } + + return $contact; + } } diff --git a/src/Model/GContact.php b/src/Model/GContact.php index d125ff8fe..0d0969ca0 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -13,12 +13,12 @@ use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; +use Friendica\Util\Network; use dba; use Exception; require_once 'include/datetime.php'; require_once 'include/dba.php'; -require_once 'include/network.php'; require_once 'include/html2bbcode.php'; /** @@ -568,7 +568,7 @@ class GContact $done[] = System::baseUrl() . '/poco'; if (strlen(Config::get('system', 'directory'))) { - $x = fetch_url(get_server()."/pubsites"); + $x = Network::fetchUrl(get_server()."/pubsites"); if ($x) { $j = json_decode($x); if ($j->entries) { @@ -980,7 +980,7 @@ class GContact $url = $server."/main/statistics"; - $result = z_fetch_url($url); + $result = Network::curl($url); if (!$result["success"]) { return false; } diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 94d5581bf..fc6e60a9c 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -12,6 +12,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Object\Image; +use Friendica\Util\Network; use dba; require_once 'include/dba.php'; @@ -101,7 +102,7 @@ class Photo $photo_failure = false; $filename = basename($image_url); - $img_str = fetch_url($image_url, true); + $img_str = Network::fetchUrl($image_url, true); if ($quit_on_error && ($img_str == "")) { return false; diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 8e32f60ae..df53b5d80 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -17,6 +17,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Protocol\Diaspora; +use Friendica\Util\Network; use dba; require_once 'include/dba.php'; @@ -963,7 +964,7 @@ class Profile public static function zrlInit(App $a) { $my_url = self::getMyURL(); - $my_url = validate_url($my_url); + $my_url = Network::isUrlValid($my_url); if ($my_url) { // Is it a DDoS attempt? // The check fetches the cached value from gprobe to reduce the load for this system diff --git a/src/Model/User.php b/src/Model/User.php index 07df7ca61..4eba5112a 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -17,13 +17,13 @@ use Friendica\Model\Group; use Friendica\Model\Photo; use Friendica\Object\Image; use Friendica\Util\Crypto; +use Friendica\Util\Network; use dba; use Exception; require_once 'boot.php'; require_once 'include/dba.php'; require_once 'include/enotify.php'; -require_once 'include/network.php'; require_once 'library/openid.php'; require_once 'include/text.php'; /** @@ -281,7 +281,7 @@ class User if (!x($username) || !x($email) || !x($nickname)) { if ($openid_url) { - if (!validate_url($openid_url)) { + if (!Network::isUrlValid($openid_url)) { throw new Exception(L10n::t('Invalid OpenID url')); } $_SESSION['register'] = 1; @@ -304,7 +304,7 @@ class User throw new Exception(L10n::t('Please enter the required information.')); } - if (!validate_url($openid_url)) { + if (!Network::isUrlValid($openid_url)) { $openid_url = ''; } @@ -329,11 +329,11 @@ class User } } - if (!allowed_email($email)) { + if (!Network::isEmailDomainAllowed($email)) { throw new Exception(L10n::t('Your email domain is not among those allowed on this site.')); } - if (!valid_email($email) || !validate_email($email)) { + if (!valid_email($email) || !Network::isEmailDomainValid($email)) { throw new Exception(L10n::t('Not a valid email address.')); } @@ -460,7 +460,7 @@ class User // if we have no OpenID photo try to look up an avatar if (!strlen($photo)) { - $photo = avatar_img($email); + $photo = Network::lookupAvatarByEmail($email); } // unless there is no avatar-addon loaded @@ -468,7 +468,7 @@ class User $photo_failure = false; $filename = basename($photo); - $img_str = fetch_url($photo, true); + $img_str = Network::fetchUrl($photo, true); // guess mimetype from headers or filename $type = Image::guessType($photo, true); diff --git a/src/Module/Feed.php b/src/Module/Feed.php index 678e77e83..485d070e3 100644 --- a/src/Module/Feed.php +++ b/src/Module/Feed.php @@ -3,6 +3,7 @@ namespace Friendica\Module; use Friendica\BaseModule; +use Friendica\Core\System; use Friendica\Protocol\OStatus; /** @@ -31,7 +32,7 @@ class Feed extends BaseModule $nocache = x($_GET, 'nocache') && local_user(); if ($a->argc < 2) { - http_status_exit(400); + System::httpExit(400); } $type = null; diff --git a/src/Module/Login.php b/src/Module/Login.php index fdfa6623f..e080663d7 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -10,6 +10,7 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Database\DBM; use Friendica\Model\User; +use Friendica\Util\Network; use dba; require_once 'boot.php'; @@ -59,7 +60,7 @@ class Login extends BaseModule $openid_url = trim($_POST['openid_url'] ? : $_POST['username']); // if it's an email address or doesn't resolve to a URL, fail. - if ($noid || strpos($openid_url, '@') || !validate_url($openid_url)) { + if ($noid || strpos($openid_url, '@') || !Network::isUrlValid($openid_url)) { notice(L10n::t('Login failed.') . EOL); goaway(self::getApp()->get_baseurl()); // NOTREACHED diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 2cc855216..f7c3b84fd 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -18,6 +18,7 @@ use Friendica\Model\Profile; use Friendica\Protocol\Email; use Friendica\Protocol\Feed; use Friendica\Util\Crypto; +use Friendica\Util\Network; use Friendica\Util\XML; use dba; @@ -25,7 +26,6 @@ use DOMXPath; use DOMDocument; require_once 'include/dba.php'; -require_once 'include/network.php'; /** * @brief This class contain functions for probing URL @@ -107,21 +107,21 @@ class Probe logger("Probing for ".$host, LOGGER_DEBUG); - $ret = z_fetch_url($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); + $ret = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); if ($ret['success']) { $xml = $ret['body']; - $xrd = parse_xml_string($xml, false); + $xrd = XML::parseString($xml, false); $host_url = 'https://'.$host; } if (!is_object($xrd)) { - $ret = z_fetch_url($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); + $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { logger("Probing timeout for ".$url, LOGGER_DEBUG); return false; } $xml = $ret['body']; - $xrd = parse_xml_string($xml, false); + $xrd = XML::parseString($xml, false); $host_url = 'http://'.$host; } if (!is_object($xrd)) { @@ -209,7 +209,7 @@ class Probe /** * @brief Check an URI for LRDD data * - * this is a replacement for the "lrdd" function in include/network.php. + * this is a replacement for the "lrdd" function. * It isn't used in this class and has some redundancies in the code. * When time comes we can check the existing calls for "lrdd" if we can rework them. * @@ -331,7 +331,7 @@ class Probe } if (x($data, "photo")) { - $data["baseurl"] = matching_url(normalise_link($data["baseurl"]), normalise_link($data["photo"])); + $data["baseurl"] = Network::getUrlMatch(normalise_link($data["baseurl"]), normalise_link($data["photo"])); } else { $data["photo"] = System::baseUrl().'/images/person-175.jpg'; } @@ -692,7 +692,7 @@ class Probe $xrd_timeout = Config::get('system', 'xrd_timeout', 20); $redirects = 0; - $ret = z_fetch_url($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]); + $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -708,7 +708,7 @@ class Probe } // If it is not JSON, maybe it is XML - $xrd = parse_xml_string($data, false); + $xrd = XML::parseString($data, false); if (!is_object($xrd)) { logger("No webfinger data retrievable for ".$url, LOGGER_DEBUG); return false; @@ -759,7 +759,7 @@ class Probe */ private static function pollNoscrape($noscrape_url, $data) { - $ret = z_fetch_url($noscrape_url); + $ret = Network::curl($noscrape_url); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -993,7 +993,7 @@ class Probe */ private static function pollHcard($hcard_url, $data, $dfrn = false) { - $ret = z_fetch_url($hcard_url); + $ret = Network::curl($hcard_url); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -1232,7 +1232,7 @@ class Probe $pubkey = substr($pubkey, 5); } } elseif (normalise_link($pubkey) == 'http://') { - $ret = z_fetch_url($pubkey); + $ret = Network::curl($pubkey); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -1264,7 +1264,7 @@ class Probe } // Fetch all additional data from the feed - $ret = z_fetch_url($data["poll"]); + $ret = Network::curl($data["poll"]); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -1448,7 +1448,7 @@ class Probe */ private static function feed($url, $probe = true) { - $ret = z_fetch_url($url); + $ret = Network::curl($url); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return false; } @@ -1509,7 +1509,7 @@ class Probe */ private static function mail($uri, $uid) { - if (!validate_email($uri)) { + if (!Network::isEmailDomainValid($uri)) { return false; } @@ -1543,7 +1543,7 @@ class Probe $data["network"] = NETWORK_MAIL; $data["name"] = substr($uri, 0, strpos($uri, '@')); $data["nick"] = $data["name"]; - $data["photo"] = avatar_img($uri); + $data["photo"] = Network::lookupAvatarByEmail($uri); $data["url"] = 'mailto:'.$uri; $data["notify"] = 'smtp '.random_string(); $data["poll"] = 'email '.random_string(); diff --git a/src/Object/Image.php b/src/Object/Image.php index 2feb3b924..d8d6dafc3 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -12,6 +12,7 @@ use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Photo; +use Friendica\Util\Network; use Exception; use Imagick; use ImagickPixel; @@ -773,7 +774,7 @@ class Image $data = Cache::get($url); if (is_null($data) || !$data || !is_array($data)) { - $img_str = fetch_url($url, true, $redirects, 4); + $img_str = Network::fetchUrl($url, true, $redirects, 4); $filesize = strlen($img_str); if (function_exists("getimagesizefromstring")) { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 808e8aaa2..59141576b 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -25,6 +25,7 @@ use Friendica\Model\User; use Friendica\Object\Image; use Friendica\Protocol\OStatus; use Friendica\Util\Crypto; +use Friendica\Util\Network; use Friendica\Util\XML; use dba; @@ -792,7 +793,7 @@ class DFRN if ($activity) { $entry = $doc->createElement($element); - $r = parse_xml_string($activity, false); + $r = XML::parseString($activity, false); if (!$r) { return false; } @@ -815,7 +816,7 @@ class DFRN $r->link = preg_replace('/\/', '', $r->link); // XML does need a single element as root element so we add a dummy element here - $data = parse_xml_string("" . $r->link . "", false); + $data = XML::parseString("" . $r->link . "", false); if (is_object($data)) { foreach ($data->link as $link) { $attributes = []; @@ -1186,7 +1187,7 @@ class DFRN logger('dfrn_deliver: ' . $url); - $ret = z_fetch_url($url); + $ret = Network::curl($url); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { return -2; // timed out @@ -1211,7 +1212,7 @@ class DFRN return 3; } - $res = parse_xml_string($xml); + $res = XML::parseString($xml); if ((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) { return (($res->status) ? $res->status : 3); @@ -1332,7 +1333,7 @@ class DFRN logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars, true), LOGGER_DATA); - $xml = post_url($contact['notify'], $postvars); + $xml = Network::post($contact['notify'], $postvars); logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); @@ -1356,7 +1357,7 @@ class DFRN Contact::unmarkForArchival($contact); } - $res = parse_xml_string($xml); + $res = XML::parseString($xml); if (!isset($res->status)) { return -11; @@ -2187,7 +2188,7 @@ class DFRN if (!$verb) { return; } - $xo = parse_xml_string($item["object"], false); + $xo = XML::parseString($item["object"], false); if (($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) { // somebody was poked/prodded. Was it me? @@ -2309,8 +2310,8 @@ class DFRN } if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { - $xo = parse_xml_string($item["object"], false); - $xt = parse_xml_string($item["target"], false); + $xo = XML::parseString($item["object"], false); + $xt = XML::parseString($item["target"], false); if ($xt->type == ACTIVITY_OBJ_NOTE) { $r = q( @@ -2517,7 +2518,7 @@ class DFRN $item["object"] = self::transformActivity($xpath, $object, "object"); if (trim($item["object"]) != "") { - $r = parse_xml_string($item["object"], false); + $r = XML::parseString($item["object"], false); if (isset($r->type)) { $item["object-type"] = $r->type; } @@ -2786,8 +2787,8 @@ class DFRN } if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { - $xo = parse_xml_string($item["object"], false); - $xt = parse_xml_string($item["target"], false); + $xo = XML::parseString($item["object"], false); + $xt = XML::parseString($item["target"], false); if ($xt->type == ACTIVITY_OBJ_NOTE) { $i = q( diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 540f82cc6..86fdb2374 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -25,8 +25,8 @@ use Friendica\Model\Queue; use Friendica\Model\User; use Friendica\Network\Probe; use Friendica\Util\Crypto; +use Friendica\Util\Network; use Friendica\Util\XML; - use dba; use SimpleXMLElement; @@ -186,7 +186,7 @@ class Diaspora */ private static function verifyMagicEnvelope($envelope) { - $basedom = parse_xml_string($envelope); + $basedom = XML::parseString($envelope); if (!is_object($basedom)) { logger("Envelope is no XML file"); @@ -285,7 +285,7 @@ class Diaspora if (!is_object($j_outer_key_bundle)) { logger('Outer Salmon did not verify. Discarding.'); - http_status_exit(400); + System::httpExit(400); } $outer_iv = base64_decode($j_outer_key_bundle->iv); @@ -296,11 +296,11 @@ class Diaspora $xml = $raw; } - $basedom = parse_xml_string($xml); + $basedom = XML::parseString($xml); if (!is_object($basedom)) { logger('Received data does not seem to be an XML. Discarding. '.$xml); - http_status_exit(400); + System::httpExit(400); } $base = $basedom->children(NAMESPACE_SALMON_ME); @@ -325,7 +325,7 @@ class Diaspora $verify = Crypto::rsaVerify($signed_data, $signature, $key); if (!$verify) { logger('Message did not verify. Discarding.'); - http_status_exit(400); + System::httpExit(400); } return ['message' => (string)base64url_decode($base->data), @@ -347,7 +347,7 @@ class Diaspora public static function decode($importer, $xml) { $public = false; - $basedom = parse_xml_string($xml); + $basedom = XML::parseString($xml); if (!is_object($basedom)) { logger("XML is not parseable."); @@ -381,7 +381,7 @@ class Diaspora $decrypted = self::aesDecrypt($outer_key, $outer_iv, $ciphertext); logger('decrypted: '.$decrypted, LOGGER_DEBUG); - $idom = parse_xml_string($decrypted); + $idom = XML::parseString($decrypted); $inner_iv = base64_decode($idom->iv); $inner_aes_key = base64_decode($idom->aes_key); @@ -403,7 +403,7 @@ class Diaspora if (!$base) { logger('unable to locate salmon data in xml'); - http_status_exit(400); + System::httpExit(400); } @@ -441,7 +441,7 @@ class Diaspora if (!$author_link) { logger('Could not retrieve author URI.'); - http_status_exit(400); + System::httpExit(400); } // Once we have the author URI, go to the web and try to find their public key // (first this will look it up locally if it is in the fcontact cache) @@ -452,14 +452,14 @@ class Diaspora if (!$key) { logger('Could not retrieve author key.'); - http_status_exit(400); + System::httpExit(400); } $verify = Crypto::rsaVerify($signed_data, $signature, $key); if (!$verify) { logger('Message did not verify. Discarding.'); - http_status_exit(400); + System::httpExit(400); } logger('Message verified.'); @@ -631,7 +631,7 @@ class Diaspora */ private static function validPosting($msg) { - $data = parse_xml_string($msg["message"]); + $data = XML::parseString($msg["message"]); if (!is_object($data)) { logger("No valid XML ".$msg["message"], LOGGER_DEBUG); @@ -1257,7 +1257,7 @@ class Diaspora logger("Fetch post from ".$source_url, LOGGER_DEBUG); - $envelope = fetch_url($source_url); + $envelope = Network::fetchUrl($source_url); if ($envelope) { logger("Envelope was fetched.", LOGGER_DEBUG); $x = self::verifyMagicEnvelope($envelope); @@ -1275,13 +1275,13 @@ class Diaspora $source_url = $server."/p/".urlencode($guid).".xml"; logger("Fetch post from ".$source_url, LOGGER_DEBUG); - $x = fetch_url($source_url); + $x = Network::fetchUrl($source_url); if (!$x) { return false; } } - $source_xml = parse_xml_string($x); + $source_xml = XML::parseString($x); if (!is_object($source_xml)) { return false; @@ -3229,7 +3229,7 @@ class Diaspora if (!intval(Config::get("system", "diaspora_test"))) { $content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json"); - post_url($dest_url."/", $envelope, ["Content-Type: ".$content_type]); + Network::post($dest_url."/", $envelope, ["Content-Type: ".$content_type]); $return_code = $a->get_curl_code(); } else { logger("test_mode"); diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index c129c31b0..cc0915472 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -9,6 +9,7 @@ namespace Friendica\Protocol; use Friendica\Database\DBM; use Friendica\Core\System; use Friendica\Model\Item; +use Friendica\Util\Network; use dba; use DOMDocument; use DOMXPath; @@ -243,7 +244,7 @@ class Feed { $orig_plink = $item["plink"]; - $item["plink"] = original_url($item["plink"]); + $item["plink"] = Network::finalUrl($item["plink"]); $item["parent-uri"] = $item["uri"]; diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 3b04a11d2..e41f3addc 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -17,6 +17,7 @@ use Friendica\Model\Conversation; use Friendica\Network\Probe; use Friendica\Object\Image; use Friendica\Util\Lock; +use Friendica\Util\Network; use Friendica\Util\XML; use dba; use DOMDocument; @@ -725,7 +726,7 @@ class OStatus self::$conv_list[$conversation] = true; - $conversation_data = z_fetch_url($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); + $conversation_data = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); if (!$conversation_data['success']) { return; @@ -753,7 +754,7 @@ class OStatus } } if ($file != '') { - $conversation_atom = z_fetch_url($attribute['href']); + $conversation_atom = Network::curl($attribute['href']); if ($conversation_atom['success']) { $xml = $conversation_atom['body']; @@ -869,7 +870,7 @@ class OStatus return; } - $self_data = z_fetch_url($self); + $self_data = Network::curl($self); if (!$self_data['success']) { return; @@ -914,7 +915,7 @@ class OStatus } $stored = false; - $related_data = z_fetch_url($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); + $related_data = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']); if (!$related_data['success']) { return; @@ -945,7 +946,7 @@ class OStatus } } if ($atom_file != '') { - $related_atom = z_fetch_url($atom_file); + $related_atom = Network::curl($atom_file); if ($related_atom['success']) { logger('Fetched XML for URI '.$related_uri, LOGGER_DEBUG); @@ -957,7 +958,7 @@ class OStatus // Workaround for older GNU Social servers if (($xml == '') && strstr($related, '/notice/')) { - $related_atom = z_fetch_url(str_replace('/notice/', '/api/statuses/show/', $related).'.atom'); + $related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom'); if ($related_atom['success']) { logger('GNU Social workaround to fetch XML for URI '.$related_uri, LOGGER_DEBUG); @@ -968,7 +969,7 @@ class OStatus // Even more worse workaround for GNU Social ;-) if ($xml == '') { $related_guess = OStatus::convertHref($related_uri); - $related_atom = z_fetch_url(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom'); + $related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom'); if ($related_atom['success']) { logger('GNU Social workaround 2 to fetch XML for URI '.$related_uri, LOGGER_DEBUG); diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 22615fee1..f2def21ec 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -15,6 +15,7 @@ use Friendica\Database\DBM; use Friendica\Model\GContact; use Friendica\Model\Profile; use Friendica\Network\Probe; +use Friendica\Util\Network; use dba; use DOMDocument; use DOMXPath; @@ -22,7 +23,6 @@ use Exception; require_once 'include/dba.php'; require_once 'include/datetime.php'; -require_once 'include/network.php'; require_once 'include/html2bbcode.php'; class PortableContact @@ -85,7 +85,7 @@ class PortableContact logger('load: ' . $url, LOGGER_DEBUG); - $s = fetch_url($url); + $s = Network::fetchUrl($url); logger('load: returns ' . $s, LOGGER_DATA); @@ -287,7 +287,7 @@ class PortableContact } // Fetch the host-meta to check if this really is a server - $serverret = z_fetch_url($server_url."/.well-known/host-meta"); + $serverret = Network::curl($server_url."/.well-known/host-meta"); if (!$serverret["success"]) { return ""; } @@ -366,7 +366,7 @@ class PortableContact $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($server_url))); if ($server) { - $noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); + $noscraperet = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); if ($noscraperet["success"] && ($noscraperet["body"] != "")) { $noscrape = json_decode($noscraperet["body"], true); @@ -480,7 +480,7 @@ class PortableContact GContact::update($contact); - $feedret = z_fetch_url($data["poll"]); + $feedret = Network::curl($data["poll"]); if (!$feedret["success"]) { $fields = ['last_failure' => datetime_convert()]; @@ -631,7 +631,7 @@ class PortableContact */ private static function fetchNodeinfo($server_url) { - $serverret = z_fetch_url($server_url."/.well-known/nodeinfo"); + $serverret = Network::curl($server_url."/.well-known/nodeinfo"); if (!$serverret["success"]) { return false; } @@ -663,7 +663,7 @@ class PortableContact return false; } - $serverret = z_fetch_url($nodeinfo_url); + $serverret = Network::curl($nodeinfo_url); if (!$serverret["success"]) { return false; } @@ -872,7 +872,7 @@ class PortableContact $server_url = str_replace("http://", "https://", $server_url); // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); + $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); // Quit if there is a timeout. // But we want to make sure to only quit if we are mostly sure that this server url fits. @@ -889,7 +889,7 @@ class PortableContact $server_url = str_replace("https://", "http://", $server_url); // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); + $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]); // Quit if there is a timeout if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) { @@ -925,7 +925,7 @@ class PortableContact // Look for poco if (!$failure) { - $serverret = z_fetch_url($server_url."/poco"); + $serverret = Network::curl($server_url."/poco"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->totalResults)) { @@ -951,7 +951,7 @@ class PortableContact if (!$failure) { // Test for Diaspora, Hubzilla, Mastodon or older Friendica servers - $serverret = z_fetch_url($server_url); + $serverret = Network::curl($server_url); if (!$serverret["success"] || ($serverret["body"] == "")) { $failure = true; @@ -990,7 +990,7 @@ class PortableContact // Test for Statusnet // Will also return data for Friendica and GNU Social - but it will be overwritten later // The "not implemented" is a special treatment for really, really old Friendica versions - $serverret = z_fetch_url($server_url."/api/statusnet/version.json"); + $serverret = Network::curl($server_url."/api/statusnet/version.json"); if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { $platform = "StatusNet"; @@ -1001,7 +1001,7 @@ class PortableContact } // Test for GNU Social - $serverret = z_fetch_url($server_url."/api/gnusocial/version.json"); + $serverret = Network::curl($server_url."/api/gnusocial/version.json"); if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { $platform = "GNU Social"; @@ -1013,7 +1013,7 @@ class PortableContact // Test for Mastodon $orig_version = $version; - $serverret = z_fetch_url($server_url."/api/v1/instance"); + $serverret = Network::curl($server_url."/api/v1/instance"); if ($serverret["success"] && ($serverret["body"] != '')) { $data = json_decode($serverret["body"]); @@ -1036,7 +1036,7 @@ class PortableContact if (!$failure) { // Test for Hubzilla and Red - $serverret = z_fetch_url($server_url."/siteinfo.json"); + $serverret = Network::curl($server_url."/siteinfo.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->url)) { @@ -1064,7 +1064,7 @@ class PortableContact } } else { // Test for Hubzilla, Redmatrix or Friendica - $serverret = z_fetch_url($server_url."/api/statusnet/config.json"); + $serverret = Network::curl($server_url."/api/statusnet/config.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); if (isset($data->site->server)) { @@ -1119,7 +1119,7 @@ class PortableContact // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix if (!$failure) { - $serverret = z_fetch_url($server_url."/statistics.json"); + $serverret = Network::curl($server_url."/statistics.json"); if ($serverret["success"]) { $data = json_decode($serverret["body"]); @@ -1181,10 +1181,10 @@ class PortableContact // Check for noscrape // Friendica servers could be detected as OStatus servers if (!$failure && in_array($network, [NETWORK_DFRN, NETWORK_OSTATUS])) { - $serverret = z_fetch_url($server_url."/friendica/json"); + $serverret = Network::curl($server_url."/friendica/json"); if (!$serverret["success"]) { - $serverret = z_fetch_url($server_url."/friendika/json"); + $serverret = Network::curl($server_url."/friendika/json"); } if ($serverret["success"]) { @@ -1294,7 +1294,7 @@ class PortableContact */ private static function fetchServerlist($poco) { - $serverret = z_fetch_url($poco."/@server"); + $serverret = Network::curl($poco."/@server"); if (!$serverret["success"]) { return; } @@ -1343,7 +1343,7 @@ class PortableContact if (!empty($accesstoken)) { $api = 'https://instances.social/api/1.0/instances/list?count=0'; $header = ['Authorization: Bearer '.$accesstoken]; - $serverdata = z_fetch_url($api, false, $redirects, ['headers' => $header]); + $serverdata = Network::curl($api, false, $redirects, ['headers' => $header]); if ($serverdata['success']) { $servers = json_decode($serverdata['body']); foreach ($servers->instances as $server) { @@ -1360,7 +1360,7 @@ class PortableContact //if (!Config::get('system','ostatus_disabled')) { // $serverdata = "http://gstools.org/api/get_open_instances/"; - // $result = z_fetch_url($serverdata); + // $result = Network::curl($serverdata); // if ($result["success"]) { // $servers = json_decode($result["body"]); @@ -1389,7 +1389,7 @@ class PortableContact logger("Fetch all users from the server ".$server["url"], LOGGER_DEBUG); - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { $data = json_decode($retdata["body"]); @@ -1408,7 +1408,7 @@ class PortableContact $success = false; - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG); $success = self::discoverServer(json_decode($retdata["body"])); @@ -1493,7 +1493,7 @@ class PortableContact // Fetch all contacts from a given user from the other server $url = $server["poco"]."/".$username."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; - $retdata = z_fetch_url($url); + $retdata = Network::curl($url); if ($retdata["success"]) { self::discoverServer(json_decode($retdata["body"]), 3); } diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php index 5b0c66fb9..f30488ce1 100644 --- a/src/Protocol/Salmon.php +++ b/src/Protocol/Salmon.php @@ -6,6 +6,7 @@ namespace Friendica\Protocol; use Friendica\Network\Probe; use Friendica\Util\Crypto; +use Friendica\Util\Network; use Friendica\Util\XML; /** @@ -50,7 +51,7 @@ class Salmon $ret[$x] = substr($ret[$x], 5); } } elseif (normalise_link($ret[$x]) == 'http://') { - $ret[$x] = fetch_url($ret[$x]); + $ret[$x] = Network::fetchUrl($ret[$x]); } } } @@ -132,7 +133,7 @@ class Salmon $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them - post_url($url, $salmon, [ + Network::post($url, $salmon, [ 'Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon) ]); @@ -158,7 +159,7 @@ class Salmon $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them - post_url($url, $salmon, [ + Network::post($url, $salmon, [ 'Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon) ]); @@ -181,10 +182,9 @@ class Salmon $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them - post_url($url, $salmon, [ + Network::post($url, $salmon, [ 'Content-type: application/magic-envelope+xml', - 'Content-length: ' . strlen($salmon)] - ); + 'Content-length: ' . strlen($salmon)]); $return_code = $a->get_curl_code(); } diff --git a/src/Util/ExAuth.php b/src/Util/ExAuth.php index 8940c0205..a6851c385 100644 --- a/src/Util/ExAuth.php +++ b/src/Util/ExAuth.php @@ -38,9 +38,9 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Database\DBM; use Friendica\Model\User; +use Friendica\Util\Network; use dba; -require_once 'include/dba.php'; require_once 'include/dba.php'; class ExAuth @@ -181,7 +181,7 @@ class ExAuth $url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user; - $data = z_fetch_url($url); + $data = Network::curl($url); if (!is_array($data)) { return false; diff --git a/src/Util/Network.php b/src/Util/Network.php new file mode 100644 index 000000000..1f9184ae9 --- /dev/null +++ b/src/Util/Network.php @@ -0,0 +1,889 @@ +$timeout, + 'accept_content'=>$accept_content, + 'cookiejar'=>$cookiejar + ] + ); + + return($ret['body']); + } + + /** + * @brief fetches an URL. + * + * @param string $url URL to fetch + * @param boolean $binary default false + * TRUE if asked to return binary results (file download) + * @param int $redirects The recursion counter for internal use - default 0 + * @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 + * + * @return array an assoziative array with: + * int 'return_code' => HTTP return code or 0 if timeout or failure + * boolean 'success' => boolean true (if HTTP 2xx result) or false + * string 'redirect_url' => in case of redirect, content was finally retrieved from this URL + * string 'header' => HTTP headers + * string 'body' => fetched content + */ + public static function curl($url, $binary = false, &$redirects = 0, $opts = []) + { + $ret = ['return_code' => 0, 'success' => false, 'header' => '', 'info' => '', 'body' => '']; + + $stamp1 = microtime(true); + + $a = get_app(); + + if (self::isUrlBlocked($url)) { + logger('z_fetch_url: domain of ' . $url . ' is blocked', LOGGER_DATA); + return $ret; + } + + $ch = @curl_init($url); + + if (($redirects > 8) || (!$ch)) { + return $ret; + } + + @curl_setopt($ch, CURLOPT_HEADER, true); + + if (x($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 (x($opts, 'accept_content')) { + curl_setopt( + $ch, + CURLOPT_HTTPHEADER, + ['Accept: ' . $opts['accept_content']] + ); + } + + @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + @curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent()); + + $range = intval(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 (x($opts, 'headers')) { + @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); + } + + if (x($opts, 'nobody')) { + @curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']); + } + + if (x($opts, 'timeout')) { + @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']); + } else { + $curl_time = 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 = 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 = Config::get('system', 'proxy'); + + if (strlen($proxy)) { + @curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); + @curl_setopt($ch, CURLOPT_PROXY, $proxy); + $proxyuser = @Config::get('system', 'proxyuser'); + + if (strlen($proxyuser)) { + @curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser); + } + } + + if (Config::get('system', 'ipv4_resolve', false)) { + curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + } + + if ($binary) { + @curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); + } + + $a->set_curl_code(0); + + // 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); + } + + if (curl_errno($ch) !== CURLE_OK) { + logger('fetch_url error fetching ' . $url . ': ' . curl_error($ch), LOGGER_NORMAL); + } + + $ret['errno'] = curl_errno($ch); + + $base = $s; + $ret['info'] = $curl_info; + + $http_code = $curl_info['http_code']; + + logger('fetch_url ' . $url . ': ' . $http_code . " " . $s, LOGGER_DATA); + $header = ''; + + // Pull out multiple headers, e.g. proxy and continuation headers + // allow for HTTP/2.x without fixing code + + while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) { + $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); + $header .= $chunk; + $base = substr($base, strlen($chunk)); + } + + $a->set_curl_code($http_code); + $a->set_curl_content_type($curl_info['content_type']); + $a->set_curl_headers($header); + + if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) { + $new_location_info = @parse_url($curl_info['redirect_url']); + $old_location_info = @parse_url($curl_info['url']); + + $newurl = $curl_info['redirect_url']; + + if (($new_location_info['path'] == '') && ( $new_location_info['host'] != '')) { + $newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path']; + } + + $matches = []; + + if (preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches)) { + $newurl = trim(array_pop($matches)); + } + if (strpos($newurl, '/') === 0) { + $newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl; + } + + if (filter_var($newurl, FILTER_VALIDATE_URL)) { + $redirects++; + @curl_close($ch); + return self::curl($newurl, $binary, $redirects, $opts); + } + } + + $a->set_curl_code($http_code); + $a->set_curl_content_type($curl_info['content_type']); + + $rc = intval($http_code); + $ret['return_code'] = $rc; + $ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false); + $ret['redirect_url'] = $url; + + if (!$ret['success']) { + $ret['error'] = curl_error($ch); + $ret['debug'] = $curl_info; + logger('z_fetch_url: error: '.$url.': '.$ret['return_code'].' - '.$ret['error'], LOGGER_DEBUG); + logger('z_fetch_url: debug: '.print_r($curl_info, true), LOGGER_DATA); + } + + $ret['body'] = substr($s, strlen($header)); + $ret['header'] = $header; + + if (x($opts, 'debug')) { + $ret['debug'] = $curl_info; + } + + @curl_close($ch); + + $a->save_timestamp($stamp1, 'network'); + + return($ret); + } + + /** + * @brief Send POST request to $url + * + * @param string $url URL to post + * @param mixed $params array of POST variables + * @param string $headers HTTP headers + * @param integer $redirects Recursion counter for internal use - default = 0 + * @param integer $timeout The timeout in seconds, default system config value or 60 seconds + * + * @return string The content + */ + public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0) + { + $stamp1 = microtime(true); + + if (self::isUrlBlocked($url)) { + logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA); + return false; + } + + $a = get_app(); + $ch = curl_init($url); + + if (($redirects > 8) || (!$ch)) { + return false; + } + + logger('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->get_useragent()); + + if (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 = Config::get('system', 'curl_timeout', 60); + curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time)); + } + + if (defined('LIGHTTPD')) { + if (!is_array($headers)) { + $headers = ['Expect:']; + } else { + if (!in_array('Expect:', $headers)) { + array_push($headers, 'Expect:'); + } + } + } + + if ($headers) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + $check_cert = 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 = Config::get('system', 'proxy'); + + if (strlen($proxy)) { + curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); + curl_setopt($ch, CURLOPT_PROXY, $proxy); + $proxyuser = Config::get('system', 'proxyuser'); + if (strlen($proxyuser)) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser); + } + } + + $a->set_curl_code(0); + + // don't let curl abort the entire application + // if it throws any errors. + + $s = @curl_exec($ch); + + $base = $s; + $curl_info = curl_getinfo($ch); + $http_code = $curl_info['http_code']; + + logger('post_url: result ' . $http_code . ' - ' . $url, LOGGER_DATA); + + $header = ''; + + // Pull out multiple headers, e.g. proxy and continuation headers + // allow for HTTP/2.x without fixing code + + while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) { + $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); + $header .= $chunk; + $base = substr($base, strlen($chunk)); + } + + if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) { + $matches = []; + preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches); + $newurl = trim(array_pop($matches)); + + if (strpos($newurl, '/') === 0) { + $newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl; + } + + if (filter_var($newurl, FILTER_VALIDATE_URL)) { + $redirects++; + logger('post_url: redirect ' . $url . ' to ' . $newurl); + return self::post($newurl, $params, $headers, $redirects, $timeout); + } + } + + $a->set_curl_code($http_code); + + $body = substr($s, strlen($header)); + + $a->set_curl_headers($header); + + curl_close($ch); + + $a->save_timestamp($stamp1, 'network'); + + logger('post_url: end ' . $url, LOGGER_DATA); + + return $body; + } + + /** + * @brief Check URL to see if it's real + * + * Take a URL from the wild, prepend http:// if necessary + * and check DNS to see if it's real (or check if is a valid IP address) + * + * @param string $url The URL to be validated + * @return string|boolean The actual working URL, false else + */ + public static function isUrlValid($url) + { + if (Config::get('system', 'disable_url_validation')) { + return $url; + } + + // no naked subdomains (allow localhost for tests) + if (strpos($url, '.') === false && strpos($url, '/localhost/') === false) { + return false; + } + + if (substr($url, 0, 4) != 'http') { + $url = 'http://' . $url; + } + + /// @TODO Really suppress function outcomes? Why not find them + debug them? + $h = @parse_url($url); + + if ((is_array($h)) && (@dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { + return $url; + } + + return false; + } + + /** + * @brief Checks that email is an actual resolvable internet address + * + * @param string $addr The email address + * @return boolean True if it's a valid email address, false if it's not + */ + public static function isEmailDomainValid($addr) + { + if (Config::get('system', 'disable_email_validation')) { + return true; + } + + if (! strpos($addr, '@')) { + return false; + } + + $h = substr($addr, strpos($addr, '@') + 1); + + if (($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX) || filter_var($h, FILTER_VALIDATE_IP) )) { + return true; + } + return false; + } + + /** + * @brief Check if URL is allowed + * + * Check $url against our list of allowed sites, + * wildcards allowed. If allowed_sites is unset return true; + * + * @param string $url URL which get tested + * @return boolean True if url is allowed otherwise return false + */ + public static function isUrlAllowed($url) + { + $h = @parse_url($url); + + if (! $h) { + return false; + } + + $str_allowed = Config::get('system', 'allowed_sites'); + if (! $str_allowed) { + return true; + } + + $found = false; + + $host = strtolower($h['host']); + + // always allow our own site + if ($host == strtolower($_SERVER['SERVER_NAME'])) { + return true; + } + + $fnmatch = function_exists('fnmatch'); + $allowed = explode(',', $str_allowed); + + if (count($allowed)) { + foreach ($allowed as $a) { + $pat = strtolower(trim($a)); + if (($fnmatch && fnmatch($pat, $host)) || ($pat == $host)) { + $found = true; + break; + } + } + } + return $found; + } + + /** + * Checks if the provided url domain is on the domain blocklist. + * Returns true if it is or malformed URL, false if not. + * + * @param string $url The url to check the domain from + * + * @return boolean + */ + public static function isUrlBlocked($url) + { + $h = @parse_url($url); + + if (! $h) { + return true; + } + + $domain_blocklist = Config::get('system', 'blocklist', []); + if (! $domain_blocklist) { + return false; + } + + $host = strtolower($h['host']); + + foreach ($domain_blocklist as $domain_block) { + if (strtolower($domain_block['domain']) == $host) { + return true; + } + } + + return false; + } + + /** + * @brief Check if email address is allowed to register here. + * + * Compare against our list (wildcards allowed). + * + * @param string $email email address + * @return boolean False if not allowed, true if allowed + * or if allowed list is not configured + */ + public static function isEmailDomainAllowed($email) + { + $domain = strtolower(substr($email, strpos($email, '@') + 1)); + if (!$domain) { + return false; + } + + $str_allowed = Config::get('system', 'allowed_email', ''); + if (!x($str_allowed)) { + return true; + } + + $allowed = explode(',', $str_allowed); + + return self::isDomainAllowed($domain, $allowed); + } + + /** + * Checks for the existence of a domain in a domain list + * + * @brief Checks for the existence of a domain in a domain list + * @param string $domain + * @param array $domain_list + * @return boolean + */ + public static function isDomainAllowed($domain, array $domain_list) + { + $found = false; + + foreach ($domain_list as $item) { + $pat = strtolower(trim($item)); + if (fnmatch($pat, $domain) || ($pat == $domain)) { + $found = true; + break; + } + } + + return $found; + } + + public static function lookupAvatarByEmail($email) + { + $avatar['size'] = 175; + $avatar['email'] = $email; + $avatar['url'] = ''; + $avatar['success'] = false; + + Addon::callHooks('avatar_lookup', $avatar); + + if (! $avatar['success']) { + $avatar['url'] = System::baseUrl() . '/images/person-175.jpg'; + } + + logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); + return $avatar['url']; + } + + /** + * @brief Remove Google Analytics and other tracking platforms params from URL + * + * @param string $url Any user-submitted URL that may contain tracking params + * @return string The same URL stripped of tracking parameters + */ + public static function stripTrackingQueryParams($url) + { + $urldata = parse_url($url); + if (is_string($urldata["query"])) { + $query = $urldata["query"]; + parse_str($query, $querydata); + + if (is_array($querydata)) { + foreach ($querydata as $param => $value) { + if (in_array( + $param, + [ + "utm_source", "utm_medium", "utm_term", "utm_content", "utm_campaign", + "wt_mc", "pk_campaign", "pk_kwd", "mc_cid", "mc_eid", + "fb_action_ids", "fb_action_types", "fb_ref", + "awesm", "wtrid", + "woo_campaign", "woo_source", "woo_medium", "woo_content", "woo_term"] + ) + ) { + $pair = $param . "=" . urlencode($value); + $url = str_replace($pair, "", $url); + + // Second try: if the url isn't encoded completely + $pair = $param . "=" . str_replace(" ", "+", $value); + $url = str_replace($pair, "", $url); + + // Third try: Maybey the url isn't encoded at all + $pair = $param . "=" . $value; + $url = str_replace($pair, "", $url); + + $url = str_replace(["?&", "&&"], ["?", ""], $url); + } + } + } + + if (substr($url, -1, 1) == "?") { + $url = substr($url, 0, -1); + } + } + + return $url; + } + + /** + * @brief 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 + */ + public static function finalUrl($url, $depth = 1, $fetchbody = false) + { + $a = get_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->get_useragent()); + + curl_exec($ch); + $curl_info = @curl_getinfo($ch); + $http_code = $curl_info['http_code']; + curl_close($ch); + + $a->save_timestamp($stamp1, "network"); + + if ($http_code == 0) { + return($url); + } + + if ((($curl_info['http_code'] == "301") || ($curl_info['http_code'] == "302")) + && (($curl_info['redirect_url'] != "") || ($curl_info['location'] != "")) + ) { + if ($curl_info['redirect_url'] != "") { + return(self::finalUrl($curl_info['redirect_url'], ++$depth, $fetchbody)); + } else { + 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 (($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->get_useragent()); + + $body = curl_exec($ch); + curl_close($ch); + + $a->save_timestamp($stamp1, "network"); + + 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; + } + + public static function shortenUrl($url) + { + $slinky = new Slinky($url); + $yourls_url = Config::get('yourls', 'url1'); + if ($yourls_url) { + $yourls_username = Config::get('yourls', 'username1'); + $yourls_password = Config::get('yourls', 'password1'); + $yourls_ssl = Config::get('yourls', 'ssl1'); + $yourls = new Slinky_YourLS(); + $yourls->set('username', $yourls_username); + $yourls->set('password', $yourls_password); + $yourls->set('ssl', $yourls_ssl); + $yourls->set('yourls-url', $yourls_url); + $slinky->set_cascade([$yourls, new Slinky_Ur1ca(), new Slinky_TinyURL()]); + } else { + // setup a cascade of shortening services + // try to get a short link from these services + // in the order ur1.ca, tinyurl + $slinky->set_cascade([new Slinky_Ur1ca(), new Slinky_TinyURL()]); + } + return $slinky->short(); + } + + /** + * @brief Find the matching part between two url + * + * @param string $url1 + * @param string $url2 + * @return string The matching part + */ + public static function getUrlMatch($url1, $url2) + { + if (($url1 == "") || ($url2 == "")) { + return ""; + } + + $url1 = normalise_link($url1); + $url2 = normalise_link($url2); + + $parts1 = parse_url($url1); + $parts2 = parse_url($url2); + + if (!isset($parts1["host"]) || !isset($parts2["host"])) { + return ""; + } + + if ($parts1["scheme"] != $parts2["scheme"]) { + return ""; + } + + if ($parts1["host"] != $parts2["host"]) { + return ""; + } + + if ($parts1["port"] != $parts2["port"]) { + return ""; + } + + $match = $parts1["scheme"]."://".$parts1["host"]; + + if ($parts1["port"]) { + $match .= ":".$parts1["port"]; + } + + $pathparts1 = explode("/", $parts1["path"]); + $pathparts2 = explode("/", $parts2["path"]); + + $i = 0; + $path = ""; + do { + $path1 = $pathparts1[$i]; + $path2 = $pathparts2[$i]; + + if ($path1 == $path2) { + $path .= $path1."/"; + } + } while (($path1 == $path2) && ($i++ <= count($pathparts1))); + + $match .= $path; + + return normalise_link($match); + } + + /** + * @brief Glue url parts together + * + * @param array $parsed URL parts + * + * @return string The glued URL + */ + public static function unparseURL($parsed) + { + $get = function ($key) use ($parsed) { + return isset($parsed[$key]) ? $parsed[$key] : null; + }; + + $pass = $get('pass'); + $user = $get('user'); + $userinfo = $pass !== null ? "$user:$pass" : $user; + $port = $get('port'); + $scheme = $get('scheme'); + $query = $get('query'); + $fragment = $get('fragment'); + $authority = ($userinfo !== null ? $userinfo."@" : '') . + $get('host') . + ($port ? ":$port" : ''); + + return (strlen($scheme) ? $scheme.":" : '') . + (strlen($authority) ? "//".$authority : '') . + $get('path') . + (strlen($query) ? "?".$query : '') . + (strlen($fragment) ? "#".$fragment : ''); + } +} diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index b03fcd982..868bd7ede 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -8,6 +8,7 @@ namespace Friendica\Util; use Friendica\Content\OEmbed; use Friendica\Core\Addon; use Friendica\Object\Image; +use Friendica\Util\Network; use Friendica\Util\XML; use dba; @@ -15,7 +16,6 @@ use DOMXPath; use DOMDocument; require_once 'include/dba.php'; -require_once "include/network.php"; /** * @brief Class with methods for extracting certain content from an url @@ -140,12 +140,12 @@ class ParseUrl $url = trim($url, "'"); $url = trim($url, '"'); - $url = strip_tracking_query_params($url); + $url = Network::stripTrackingQueryParams($url); $siteinfo["url"] = $url; $siteinfo["type"] = "link"; - $data = z_fetch_url($url); + $data = Network::curl($url); if (!$data['success']) { return($siteinfo); } diff --git a/src/Util/XML.php b/src/Util/XML.php index c866475c1..d8c5e0323 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -413,4 +413,20 @@ class XML $child->parentNode->removeChild($child); } } + + public static function parseString($s, $strict = true) + { + // the "strict" parameter is deactivated + libxml_use_internal_errors(true); + + $x = @simplexml_load_string($s); + if (!$x) { + logger('libxml: parse: error: ' . $s, LOGGER_DATA); + foreach (libxml_get_errors() as $err) { + logger('libxml: parse: ' . $err->code." at ".$err->line.":".$err->column." : ".$err->message, LOGGER_DATA); + } + libxml_clear_errors(); + } + return $x; + } } diff --git a/src/Worker/CheckVersion.php b/src/Worker/CheckVersion.php index b7e99cb67..a6056ccbc 100644 --- a/src/Worker/CheckVersion.php +++ b/src/Worker/CheckVersion.php @@ -8,6 +8,7 @@ namespace Friendica\Worker; use Friendica\Core\Config; +use Friendica\Util\Network; /** * @brief check the git repository VERSION file and save the version to the DB @@ -37,7 +38,7 @@ class CheckVersion { logger("Checking VERSION from: ".$checked_url, LOGGER_DEBUG); // fetch the VERSION file - $gitversion = dbesc(trim(fetch_url($checked_url))); + $gitversion = dbesc(trim(Network::fetchUrl($checked_url))); logger("Upstream VERSION is: ".$gitversion, LOGGER_DEBUG); Config::set('system', 'git_friendica_version', $gitversion); diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index a5befb844..e17d68f88 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -299,7 +299,7 @@ class Delivery { } $ssl_policy = Config::get('system','ssl_policy'); - fix_contact_ssl_policy($x[0],$ssl_policy); + $x[0] = Contact::updateSslPolicy($x[0], $ssl_policy); // If we are setup as a soapbox we aren't accepting top level posts from this person diff --git a/src/Worker/Directory.php b/src/Worker/Directory.php index e38f9eeee..a59461037 100644 --- a/src/Worker/Directory.php +++ b/src/Worker/Directory.php @@ -10,9 +10,12 @@ use Friendica\Core\Addon; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Util\Network; -class Directory { - public static function execute($url = '') { +class Directory +{ + public static function execute($url = '') + { $dir = Config::get('system', 'directory'); if (!strlen($dir)) { @@ -32,7 +35,7 @@ class Directory { logger('Updating directory: ' . $arr['url'], LOGGER_DEBUG); if (strlen($arr['url'])) { - fetch_url($dir . '?url=' . bin2hex($arr['url'])); + Network::fetchUrl($dir . '?url=' . bin2hex($arr['url'])); } return; diff --git a/src/Worker/DiscoverPoCo.php b/src/Worker/DiscoverPoCo.php index c00db89ff..0657b0e1b 100644 --- a/src/Worker/DiscoverPoCo.php +++ b/src/Worker/DiscoverPoCo.php @@ -11,6 +11,7 @@ use Friendica\Database\DBM; use Friendica\Model\GContact; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; +use Friendica\Util\Network; require_once 'include/datetime.php'; @@ -217,7 +218,7 @@ class DiscoverPoCo { } } - $x = fetch_url(get_server()."/lsearch?p=1&n=500&search=".urlencode($search)); + $x = Network::fetchUrl(get_server()."/lsearch?p=1&n=500&search=".urlencode($search)); $j = json_decode($x); if (count($j->results)) { @@ -280,7 +281,7 @@ class DiscoverPoCo { $url = "http://gstools.org/api/users_search/".urlencode($search); - $result = z_fetch_url($url); + $result = Network::curl($url); if (!$result["success"]) { return false; } diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 293cd265e..3a5fa5575 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -10,6 +10,8 @@ use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Protocol\Email; use Friendica\Protocol\PortableContact; +use Friendica\Util\Network; +use Friendica\Util\XML; use dba; require_once 'include/dba.php'; @@ -176,7 +178,7 @@ class OnePoll . '&type=data&last_update=' . $last_update . '&perm=' . $perm ; - $ret = z_fetch_url($url); + $ret = Network::curl($url); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { // set the last-update so we don't keep polling @@ -218,7 +220,7 @@ class OnePoll } - $res = parse_xml_string($handshake_xml); + $res = XML::parseString($handshake_xml); if (intval($res->status) == 1) { logger("$url replied status 1 - marking for death "); @@ -280,7 +282,7 @@ class OnePoll $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; $postvars['perm'] = 'rw'; - $xml = post_url($contact['poll'], $postvars); + $xml = Network::post($contact['poll'], $postvars); } elseif (($contact['network'] === NETWORK_OSTATUS) || ($contact['network'] === NETWORK_DIASPORA) @@ -311,7 +313,7 @@ class OnePoll } $cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-'); - $ret = z_fetch_url($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]); + $ret = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]); unlink($cookiejar); if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { diff --git a/src/Worker/PubSubPublish.php b/src/Worker/PubSubPublish.php index 2656cef24..03608bea6 100644 --- a/src/Worker/PubSubPublish.php +++ b/src/Worker/PubSubPublish.php @@ -11,6 +11,7 @@ use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; use Friendica\Protocol\OStatus; +use Friendica\Util\Network; require_once 'include/items.php'; @@ -68,7 +69,7 @@ class PubSubPublish { logger('POST '.print_r($headers, true)."\n".$params, LOGGER_DEBUG); - post_url($rr['callback_url'], $params, $headers); + Network::post($rr['callback_url'], $params, $headers); $ret = $a->get_curl_code(); if ($ret >= 200 && $ret <= 299) {