]> git.mxchange.org Git - friendica.git/blobdiff - include/network.php
Merge pull request #4035 from friendica/revert-4031-task/3878-move-objects-to-model
[friendica.git] / include / network.php
index 752920e424bff876df359d87bf6fb4db882378bb..45f5d4e79a9c4572e63d35bc88c92879a44f7661 100644 (file)
@@ -1,13 +1,13 @@
 <?php
-
 /**
  * @file include/network.php
  */
-
-use \Friendica\Core\Config;
-
-require_once("include/xml.php");
-require_once('include/Probe.php');
+use Friendica\App;
+use Friendica\Core\System;
+use Friendica\Core\Config;
+use Friendica\Network\Probe;
+use Friendica\Object\Photo;
+use Friendica\Util\XML;
 
 /**
  * @brief Curl wrapper
@@ -16,18 +16,18 @@ require_once('include/Probe.php');
  * Set the cookiejar argument to a string (e.g. "/tmp/friendica-cookies.txt")
  * to preserve cookies from one request to the next.
  *
- * @param string $url URL to fetch
- * @param boolean $binary default false
- *    TRUE if asked to return binary results (file download)
- * @param integer $redirects The recursion counter for internal use - default 0
- * @param integer $timeout Timeout in seconds, default system config value or 60 seconds
- * @param string $accept_content supply Accept: header with 'accept_content' as the value
- * @param string $cookiejar Path to cookie jar file
+ * @param string  $url            URL to fetch
+ * @param boolean $binary         default false
+ *                                TRUE if asked to return binary results (file download)
+ * @param integer $redirects      The recursion counter for internal use - default 0
+ * @param integer $timeout        Timeout in seconds, default system config value or 60 seconds
+ * @param string  $accept_content supply Accept: header with 'accept_content' as the value
+ * @param string  $cookiejar      Path to cookie jar file
  *
  * @return string The fetched content
  */
-function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_content=Null, $cookiejar = 0) {
-
+function fetch_url($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = 0)
+{
        $ret = z_fetch_url(
                $url,
                $binary,
@@ -35,7 +35,8 @@ function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_
                array('timeout'=>$timeout,
                'accept_content'=>$accept_content,
                'cookiejar'=>$cookiejar
-               ));
+               )
+       );
 
        return($ret['body']);
 }
@@ -43,17 +44,17 @@ function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_
 /**
  * @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
+ * @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
@@ -62,8 +63,9 @@ function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_
  *    string 'header' => HTTP headers
  *    string 'body' => fetched content
  */
-function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
-       $ret = array('return_code' => 0, 'success' => false, 'header' => '', 'body' => '');
+function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array())
+{
+       $ret = array('return_code' => 0, 'success' => false, 'header' => '', 'info' => '', 'body' => '');
 
        $stamp1 = microtime(true);
 
@@ -87,14 +89,16 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
                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);
+       // 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, array(
-                       'Accept: ' . $opts['accept_content']
-               ));
+               curl_setopt(
+                       $ch,
+                       CURLOPT_HTTPHEADER,
+                       array('Accept: ' . $opts['accept_content'])
+               );
        }
 
        @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -106,6 +110,11 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
                @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']);
        }
@@ -117,32 +126,36 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
        if (x($opts, 'timeout')) {
                @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
        } else {
-               $curl_time = intval(get_config('system', 'curl_timeout'));
-               @curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
+               $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 = get_config('system', 'verifyssl');
+       $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 = get_config('system', 'proxy');
+       $proxy = Config::get('system', 'proxy');
 
        if (strlen($proxy)) {
                @curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
                @curl_setopt($ch, CURLOPT_PROXY, $proxy);
-               $proxyuser = @get_config('system', 'proxyuser');
+               $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);
        }
@@ -153,6 +166,15 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
        // 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);
@@ -161,9 +183,10 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
        $ret['errno'] = curl_errno($ch);
 
        $base = $s;
-       $curl_info = @curl_getinfo($ch);
+       $ret['info'] = $curl_info;
 
        $http_code = $curl_info['http_code'];
+
        logger('fetch_url ' . $url . ': ' . $http_code . " " . $s, LOGGER_DATA);
        $header = '';
 
@@ -186,7 +209,7 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
 
                $newurl = $curl_info['redirect_url'];
 
-               if (($new_location_info['path'] == '') AND ( $new_location_info['host'] != '')) {
+               if (($new_location_info['path'] == '') && ( $new_location_info['host'] != '')) {
                        $newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
                }
 
@@ -195,9 +218,8 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
                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;
+                       $newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl;
                }
 
                if (filter_var($newurl, FILTER_VALIDATE_URL)) {
@@ -220,8 +242,8 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
        if (!$ret['success']) {
                $ret['error'] = curl_error($ch);
                $ret['debug'] = $curl_info;
-               logger('z_fetch_url: error: ' . $url . ': ' . $ret['error'], LOGGER_DEBUG);
-               logger('z_fetch_url: debug: ' . print_r($curl_info, true), LOGGER_DATA);
+               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));
@@ -241,15 +263,16 @@ function z_fetch_url($url, $binary = false, &$redirects = 0, $opts = array()) {
 /**
  * @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 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
+ * @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) {
+function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
+{
        $stamp1 = microtime(true);
 
        if (blocked_url($url)) {
@@ -272,11 +295,15 @@ function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
        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 = intval(get_config('system', 'curl_timeout'));
-               curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
+               $curl_time = Config::get('system', 'curl_timeout', 60);
+               curl_setopt($ch, CURLOPT_TIMEOUT, intval($curl_time));
        }
 
        if (defined('LIGHTTPD')) {
@@ -293,19 +320,19 @@ function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
 
-       $check_cert = get_config('system', 'verifyssl');
+       $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 = get_config('system', 'proxy');
+       $proxy = Config::get('system', 'proxy');
 
        if (strlen($proxy)) {
                curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
                curl_setopt($ch, CURLOPT_PROXY, $proxy);
-               $proxyuser = get_config('system', 'proxyuser');
+               $proxyuser = Config::get('system', 'proxyuser');
                if (strlen($proxyuser)) {
                        curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyuser);
                }
@@ -341,7 +368,7 @@ function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
                $newurl = trim(array_pop($matches));
 
                if (strpos($newurl, '/') === 0) {
-                       $newurl = $old_location_info['scheme'] . '://' . $old_location_info['host'] . $newurl;
+                       $newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl;
                }
 
                if (filter_var($newurl, FILTER_VALIDATE_URL)) {
@@ -370,16 +397,24 @@ function post_url($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
 // Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable
 // of $st and an optional text <message> of $message and terminates the current process.
 
-function xml_status($st, $message = '') {
+function xml_status($st, $message = '')
+{
+       $result = array('status' => $st);
 
-       $xml_message = ((strlen($message)) ? "\t<message>" . xmlify($message) . "</message>\r\n" : '');
+       if ($message != '') {
+               $result['message'] = $message;
+       }
 
-       if($st)
+       if ($st) {
                logger('xml_status returning non_zero: ' . $st . " message=" . $message);
+       }
+
+       header("Content-type: text/xml");
+
+       $xmldata = array("result" => $result);
+
+       echo XML::fromArray($xmldata, $xml);
 
-       header( "Content-type: text/xml" );
-       echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
-       echo "<result>\r\n\t<status>$st</status>\r\n$xml_message</result>\r\n";
        killme();
 }
 
@@ -395,19 +430,21 @@ function xml_status($st, $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
+ * @param integer $val         HTTP status result value
+ * @param array   $description optional message
+ *                             'title' => header title
+ *                             'description' => optional message
  */
-function http_status_exit($val, $description = array()) {
+function http_status_exit($val, $description = array())
+{
        $err = '';
-       if($val >= 400) {
+       if ($val >= 400) {
                $err = 'Error';
-               if (!isset($description["title"]))
+               if (!isset($description["title"])) {
                        $description["title"] = $err." ".$val;
+               }
        }
-       if($val >= 200 && $val < 300)
+       if ($val >= 200 && $val < 300)
                $err = 'OK';
 
        logger('http_status_exit ' . $val);
@@ -415,12 +452,15 @@ function http_status_exit($val, $description = array()) {
 
        if (isset($description["title"])) {
                $tpl = get_markup_template('http_status.tpl');
-               echo replace_macros($tpl, array('$title' => $description["title"],
-                                               '$description' => $description["description"]));
+               echo replace_macros(
+                       $tpl,
+                       array(
+                               '$title' => $description["title"],
+                               '$description' => $description["description"])
+               );
        }
 
        killme();
-
 }
 
 /**
@@ -432,21 +472,23 @@ function http_status_exit($val, $description = array()) {
  * @param string $url The URL to be validated
  * @return boolean True if it's a valid URL, fals if something wrong with it
  */
-function validate_url(&$url) {
-       if(get_config('system','disable_url_validation'))
+function validate_url(&$url)
+{
+       if (Config::get('system', 'disable_url_validation')) {
                return true;
+       }
 
        // no naked subdomains (allow localhost for tests)
-       if(strpos($url,'.') === false && strpos($url,'/localhost/') === false)
+       if (strpos($url, '.') === false && strpos($url, '/localhost/') === false)
                return false;
 
-       if(substr($url,0,4) != 'http')
+       if (substr($url, 0, 4) != 'http')
                $url = 'http://' . $url;
 
        /// @TODO Really supress 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) )) {
+       if ((is_array($h)) && (dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) {
                return true;
        }
 
@@ -459,16 +501,19 @@ function validate_url(&$url) {
  * @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(get_config('system','disable_email_validation'))
+function validate_email($addr)
+{
+       if (Config::get('system', 'disable_email_validation')) {
                return true;
+       }
 
-       if(! strpos($addr,'@'))
+       if (! strpos($addr, '@')) {
                return false;
-       $h = substr($addr,strpos($addr,'@') + 1);
+       }
+
+       $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) )) {
+       if (($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX) || filter_var($h, FILTER_VALIDATE_IP) )) {
                return true;
        }
        return false;
@@ -483,8 +528,8 @@ function validate_email($addr) {
  * @param string $url URL which get tested
  * @return boolean True if url is allowed otherwise return false
  */
-function allowed_url($url) {
-
+function allowed_url($url)
+{
        $h = @parse_url($url);
 
        if (! $h) {
@@ -501,7 +546,6 @@ function allowed_url($url) {
        $host = strtolower($h['host']);
 
        // always allow our own site
-
        if ($host == strtolower($_SERVER['SERVER_NAME'])) {
                return true;
        }
@@ -526,9 +570,11 @@ function allowed_url($url) {
  * 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) {
+function blocked_url($url)
+{
        $h = @parse_url($url);
 
        if (! $h) {
@@ -556,30 +602,31 @@ function blocked_url($url) {
  *
  * Compare against our list (wildcards allowed).
  *
- * @param type $email
+ * @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)
+function allowed_email($email)
+{
+       $domain = strtolower(substr($email, strpos($email, '@') + 1));
+       if (! $domain) {
                return false;
+       }
 
-       $str_allowed = get_config('system','allowed_email');
-       if(! $str_allowed)
+       $str_allowed = Config::get('system', 'allowed_email');
+       if (! $str_allowed) {
                return true;
+       }
 
        $found = false;
 
        $fnmatch = function_exists('fnmatch');
-       $allowed = explode(',',$str_allowed);
+       $allowed = explode(',', $str_allowed);
 
-       if(count($allowed)) {
-               foreach($allowed as $a) {
+       if (count($allowed)) {
+               foreach ($allowed as $a) {
                        $pat = strtolower(trim($a));
-                       if(($fnmatch && fnmatch($pat,$domain)) || ($pat == $domain)) {
+                       if (($fnmatch && fnmatch($pat, $domain)) || ($pat == $domain)) {
                                $found = true;
                                break;
                        }
@@ -588,8 +635,8 @@ function allowed_email($email) {
        return $found;
 }
 
-function avatar_img($email) {
-
+function avatar_img($email)
+{
        $avatar['size'] = 175;
        $avatar['email'] = $email;
        $avatar['url'] = '';
@@ -598,7 +645,7 @@ function avatar_img($email) {
        call_hooks('avatar_lookup', $avatar);
 
        if (! $avatar['success']) {
-               $avatar['url'] = App::get_baseurl() . '/images/person-175.jpg';
+               $avatar['url'] = System::baseUrl() . '/images/person-175.jpg';
        }
 
        logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG);
@@ -606,20 +653,16 @@ function avatar_img($email) {
 }
 
 
-function parse_xml_string($s,$strict = true) {
+function parse_xml_string($s, $strict = true)
+{
+       // the "strict" parameter is deactivated
+
        /// @todo Move this function to the xml class
-       if($strict) {
-               if(! strstr($s,'<?xml'))
-                       return false;
-               $s2 = substr($s,strpos($s,'<?xml'));
-       }
-       else
-               $s2 = $s;
        libxml_use_internal_errors(true);
 
-       $x = @simplexml_load_string($s2);
-       if (! $x) {
-               logger('libxml: parse: error: ' . $s2, LOGGER_DATA);
+       $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);
                }
@@ -628,10 +671,10 @@ function parse_xml_string($s,$strict = true) {
        return $x;
 }
 
-function scale_external_images($srctext, $include_link = true, $scale_replace = false) {
-
+function scale_external_images($srctext, $include_link = true, $scale_replace = false)
+{
        // Suppress "view full size"
-       if (intval(get_config('system','no_view_full_size'))) {
+       if (intval(Config::get('system', 'no_view_full_size'))) {
                $include_link = false;
        }
 
@@ -641,14 +684,13 @@ function scale_external_images($srctext, $include_link = true, $scale_replace =
        $s = htmlspecialchars_decode($srctext);
 
        $matches = null;
-       $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism',$s,$matches,PREG_SET_ORDER);
+       $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER);
        if ($c) {
-               require_once('include/Photo.php');
                foreach ($matches as $mtch) {
                        logger('scale_external_image: ' . $mtch[1]);
 
-                       $hostname = str_replace('www.','',substr(App::get_baseurl(),strpos(App::get_baseurl(),'://')+3));
-                       if (stristr($mtch[1],$hostname)) {
+                       $hostname = str_replace('www.', '', substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3));
+                       if (stristr($mtch[1], $hostname)) {
                                continue;
                        }
 
@@ -668,24 +710,27 @@ function scale_external_images($srctext, $include_link = true, $scale_replace =
                        }
 
                        // guess mimetype from headers or filename
-                       $type = guess_image_type($mtch[1],true);
+                       $type = Photo::guessImageType($mtch[1], true);
 
                        if ($i) {
                                $ph = new Photo($i, $type);
-                               if ($ph->is_valid()) {
+                               if ($ph->isValid()) {
                                        $orig_width = $ph->getWidth();
                                        $orig_height = $ph->getHeight();
 
                                        if ($orig_width > 640 || $orig_height > 640) {
-
                                                $ph->scaleImage(640);
                                                $new_width = $ph->getWidth();
                                                $new_height = $ph->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]'
+                                               $s = str_replace(
+                                                       $mtch[0],
+                                                       '[img=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/img]'
                                                        . "\n" . (($include_link)
                                                                ? '[url=' . $mtch[1] . ']' . t('view full size') . '[/url]' . "\n"
-                                                               : ''),$s);
+                                                               : ''),
+                                                       $s
+                                               );
                                                logger('scale_external_images: new string: ' . $s, LOGGER_DEBUG);
                                        }
                                }
@@ -694,51 +739,39 @@ function scale_external_images($srctext, $include_link = true, $scale_replace =
        }
 
        // replace the special char encoding
-       $s = htmlspecialchars($s,ENT_NOQUOTES,'UTF-8');
+       $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
        return $s;
 }
 
 
-function fix_contact_ssl_policy(&$contact,$new_policy) {
-
+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:')) {
+       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']);
+               $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:')) {
+       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']);
+               $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) {
-               q("UPDATE `contact` SET
-                       `url` = '%s',
-                       `request` = '%s',
-                       `notify` = '%s',
-                       `poll` = '%s',
-                       `confirm` = '%s',
-                       `poco` = '%s'
-                       WHERE `id` = %d LIMIT 1",
-                       dbesc($contact['url']),
-                       dbesc($contact['request']),
-                       dbesc($contact['notify']),
-                       dbesc($contact['poll']),
-                       dbesc($contact['confirm']),
-                       dbesc($contact['poco']),
-                       intval($contact['id'])
-               );
+               $fields = array('url' => $contact['url'], 'request' => $contact['request'],
+                               'notify' => $contact['notify'], 'poll' => $contact['poll'],
+                               'confirm' => $contact['confirm'], 'poco' => $contact['poco']);
+               dba::update('contact', $fields, array('id' => $contact['id']));
        }
 }
 
@@ -756,13 +789,17 @@ function strip_tracking_query_params($url)
                parse_str($query, $querydata);
 
                if (is_array($querydata)) {
-                       foreach ($querydata AS $param => $value) {
-                               if (in_array($param, array("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"))) {
-
+                       foreach ($querydata as $param => $value) {
+                               if (in_array(
+                                       $param,
+                                       array(
+                                               "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);
 
@@ -797,18 +834,20 @@ function strip_tracking_query_params($url)
  *
  * @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
+ * @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) {
+function original_url($url, $depth = 1, $fetchbody = false)
+{
        $a = get_app();
 
        $url = strip_tracking_query_params($url);
 
-       if ($depth > 10)
+       if ($depth > 10) {
                return($url);
+       }
 
        $url = trim($url, "'");
 
@@ -833,25 +872,30 @@ function original_url($url, $depth = 1, $fetchbody = false) {
        if ($http_code == 0)
                return($url);
 
-       if ((($curl_info['http_code'] == "301") OR ($curl_info['http_code'] == "302"))
-               AND (($curl_info['redirect_url'] != "") OR ($curl_info['location'] != ""))) {
-               if ($curl_info['redirect_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
+               } 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)
+       if (!$fetchbody) {
                return(original_url($url, ++$depth, true));
+       }
 
        // if the file is too large then exit
-       if ($curl_info["download_content_length"] > 1000000)
+       if ($curl_info["download_content_length"] > 1000000) {
                return($url);
+       }
 
        // if it isn't a HTML file then exit
-       if (($curl_info["content_type"] != "") AND !strstr(strtolower($curl_info["content_type"]),"html"))
+       if (($curl_info["content_type"] != "") && !strstr(strtolower($curl_info["content_type"]), "html")) {
                return($url);
+       }
 
        $stamp1 = microtime(true);
 
@@ -868,8 +912,9 @@ function original_url($url, $depth = 1, $fetchbody = false) {
 
        $a->save_timestamp($stamp1, "network");
 
-       if (trim($body) == "")
+       if (trim($body) == "") {
                return($url);
+       }
 
        // Check for redirect in meta elements
        $doc = new DOMDocument();
@@ -880,31 +925,36 @@ function original_url($url, $depth = 1, $fetchbody = false) {
        $list = $xpath->query("//meta[@content]");
        foreach ($list as $node) {
                $attr = array();
-               if ($node->attributes->length)
-                       foreach ($node->attributes as $attribute)
+               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);
                        $content = "";
-                       foreach ($pathinfo AS $value)
-                               if (substr(strtolower($value), 0, 4) == "url=")
+                       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');
+function short_link($url)
+{
+       require_once 'library/slinky.php';
        $slinky = new Slinky($url);
-       $yourls_url = get_config('yourls','url1');
+       $yourls_url = Config::get('yourls', 'url1');
        if ($yourls_url) {
-               $yourls_username = get_config('yourls','username1');
-               $yourls_password = get_config('yourls', 'password1');
-               $yourls_ssl = get_config('yourls', 'ssl1');
+               $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);
@@ -929,7 +979,8 @@ function short_link($url) {
  *
  * @param array $x The input content
  */
-function json_return_and_die($x) {
+function json_return_and_die($x)
+{
        header("content-type: application/json");
        echo json_encode($x);
        killme();
@@ -942,10 +993,11 @@ function json_return_and_die($x) {
  * @param string $url2
  * @return string The matching part
  */
-function matching_url($url1, $url2) {
-
-       if (($url1 == "") OR ($url2 == ""))
+function matching_url($url1, $url2)
+{
+       if (($url1 == "") || ($url2 == "")) {
                return "";
+       }
 
        $url1 = normalise_link($url1);
        $url2 = normalise_link($url2);
@@ -953,22 +1005,27 @@ function matching_url($url1, $url2) {
        $parts1 = parse_url($url1);
        $parts2 = parse_url($url2);
 
-       if (!isset($parts1["host"]) OR !isset($parts2["host"]))
+       if (!isset($parts1["host"]) || !isset($parts2["host"])) {
                return "";
+       }
 
-       if ($parts1["scheme"] != $parts2["scheme"])
+       if ($parts1["scheme"] != $parts2["scheme"]) {
                return "";
+       }
 
-       if ($parts1["host"] != $parts2["host"])
+       if ($parts1["host"] != $parts2["host"]) {
                return "";
+       }
 
-       if ($parts1["port"] != $parts2["port"])
+       if ($parts1["port"] != $parts2["port"]) {
                return "";
+       }
 
        $match = $parts1["scheme"]."://".$parts1["host"];
 
-       if ($parts1["port"])
+       if ($parts1["port"]) {
                $match .= ":".$parts1["port"];
+       }
 
        $pathparts1 = explode("/", $parts1["path"]);
        $pathparts2 = explode("/", $parts2["path"]);
@@ -979,12 +1036,43 @@ function matching_url($url1, $url2) {
                $path1 = $pathparts1[$i];
                $path2 = $pathparts2[$i];
 
-               if ($path1 == $path2)
+               if ($path1 == $path2) {
                        $path .= $path1."/";
-
-       } while (($path1 == $path2) AND ($i++ <= count($pathparts1)));
+               }
+       } 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 : '');
+}