]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - lib/util.php
set the html sanitizer cache directory to ['cache']['dir'] from the config file;
[quix0rs-gnu-social.git] / lib / util.php
index 3f6e5e94ecf3645fa74b4b5e2c1fae0b58895f33..9c32d7443303252c03a1aaa22b7a6676f3c2015d 100644 (file)
@@ -264,6 +264,11 @@ function common_logged_in()
     return (!is_null(common_current_user()));
 }
 
+function common_local_referer()
+{
+    return parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) === common_config('site', 'server');
+}
+
 function common_have_session()
 {
     return (0 != strcmp(session_id(), ''));
@@ -354,7 +359,7 @@ function common_set_cookie($key, $value, $expiration=0)
                      $expiration,
                      $cookiepath,
                      $server,
-                     common_config('site', 'ssl')=='always');
+                     GNUsocial::useHTTPS());
 }
 
 define('REMEMBERME', 'rememberme');
@@ -575,12 +580,26 @@ function common_canonical_email($email)
     return $email;
 }
 
+function common_to_alphanumeric($str)
+{
+    $filtered = preg_replace('/[^A-Za-z0-9]\s*/', '', $str);
+    if (strlen($filtered) < 1) {
+        throw new Exception('Filtered string was zero-length.');
+    }
+    return $filtered;
+}
+
 function common_purify($html)
 {
     require_once INSTALLDIR.'/extlib/HTMLPurifier/HTMLPurifier.auto.php';
 
     $cfg = HTMLPurifier_Config::createDefault();
+    $cfg->set('Attr.AllowedRel', ['bookmark', 'directory', 'enclosure', 'home', 'license', 'nofollow', 'payment', 'tag']);  // http://microformats.org/wiki/rel
     $cfg->set('HTML.ForbiddenAttributes', array('style'));  // id, on* etc. are already filtered by default
+    $cfg->set('URI.AllowedSchemes', array_fill_keys(common_url_schemes(), true));
+    if (common_config('cache', 'dir')) {
+        $cfg->set('Cache.SerializerPath', common_config('cache', 'dir'));
+    }
 
     // Remove more elements than what the default filter removes, default in GNU social are remotely
     // linked resources such as img, video, audio
@@ -884,6 +903,7 @@ function common_render_text($text)
 define('_URL_SCHEME_COLON_DOUBLE_SLASH', 1);
 define('_URL_SCHEME_SINGLE_COLON', 2);
 define('_URL_SCHEME_NO_DOMAIN', 4);
+define('_URL_SCHEME_COLON_COORDINATES', 8);
 
 function common_url_schemes($filter=null)
 {
@@ -913,6 +933,7 @@ function common_url_schemes($filter=null)
                 'tel'       => _URL_SCHEME_SINGLE_COLON,
                 'xmpp'      => _URL_SCHEME_SINGLE_COLON,
                 'magnet'    => _URL_SCHEME_NO_DOMAIN,
+                'geo'       => _URL_SCHEME_COLON_COORDINATES,
                 ];
 
     return array_keys(
@@ -931,6 +952,13 @@ function common_url_schemes($filter=null)
  * @param mixed $arg: optional argument will be passed on to the callback
  */
 function common_replace_urls_callback($text, $callback, $arg = null) {
+    $geouri_labeltext_regex = '\pN\pL\-';
+    $geouri_mark_regex = '\-\_\.\!\~\*\\\'\(\)';    // the \\\' is really pretty
+    $geouri_unreserved_regex = '\pN\pL' . $geouri_mark_regex;
+    $geouri_punreserved_regex = '\[\]\:\&\+\$';
+    $geouri_pctencoded_regex = '(?:\%[0-9a-fA-F][0-9a-fA-F])';
+    $geouri_paramchar_regex = $geouri_unreserved_regex . $geouri_punreserved_regex; //FIXME: add $geouri_pctencoded_regex here so it works
+
     // Start off with a regex
     $regex = '#'.
     '(?:^|[\s\<\>\(\)\[\]\{\}\\\'\\\";]+)(?![\@\!\#])'.
@@ -951,8 +979,18 @@ function common_replace_urls_callback($text, $callback, $arg = null) {
                     ')'.
                 ')'.
             ')'.
+            '|(?:'.
+                '(?:' . implode('|', common_url_schemes(_URL_SCHEME_COLON_COORDINATES)) . '):'.
+                // There's an order that must be followed here too, if ;crs= is used, it must precede ;u=
+                // Also 'crsp' (;crs=$crsp) must match $geouri_labeltext_regex
+                // Also 'uval' (;u=$uval) must be a pnum: \-?[0-9]+
+                '(?:'.
+                    '(?:[0-9]+(?:\.[0-9]+)?(?:\,[0-9]+(?:\.[0-9]+)?){1,2})'.    // 1(.23)?(,4(.56)){1,2}
+                    '(?:\;(?:['.$geouri_labeltext_regex.']+)(?:\=['.$geouri_paramchar_regex.']+)*)*'.
+                ')'.
+            ')'.
             // URLs without domain name, like magnet:?xt=...
-            '|(?:(?:' . implode('|', common_url_schemes(_URL_SCHEME_NO_DOMAIN)) . '):)'.
+            '|(?:(?:' . implode('|', common_url_schemes(_URL_SCHEME_NO_DOMAIN)) . '):(?=\?))'.  // zero-length lookahead requires ? after :
             (common_config('linkify', 'bare_ipv4')   // Convert IPv4 addresses to hyperlinks
                 ? '|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
                 : '').
@@ -1324,9 +1362,7 @@ function common_local_url($action, $args=null, $params=null, $fragment=null, $ad
         $r = Router::get();
         $path = $r->build($action, $args, $params, $fragment);
 
-        $ssl = common_config('site', 'ssl') === 'always'
-                || GNUsocial::isHTTPS()
-                || common_is_sensitive($action);
+        $ssl = GNUsocial::useHTTPS();
 
         if (common_config('site','fancy')) {
             $url = common_path($path, $ssl, $addSession);
@@ -1342,35 +1378,11 @@ function common_local_url($action, $args=null, $params=null, $fragment=null, $ad
     return $url;
 }
 
-function common_is_sensitive($action)
-{
-    static $sensitive = array(
-        'login',
-        'register',
-        'passwordsettings',
-        'api',
-        'ApiOAuthRequestToken',
-        'ApiOAuthAccessToken',
-        'ApiOAuthAuthorize',
-        'ApiOAuthPin',
-        'showapplication'
-    );
-    $ssl = null;
-
-    if (Event::handle('SensitiveAction', array($action, &$ssl))) {
-        $ssl = in_array($action, $sensitive);
-    }
-
-    return $ssl;
-}
-
 function common_path($relative, $ssl=false, $addSession=true)
 {
     $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : '';
 
-    if (($ssl && (common_config('site', 'ssl') === 'sometimes'))
-        || GNUsocial::isHTTPS()
-        || common_config('site', 'ssl') === 'always') {
+    if ($ssl && GNUsocial::useHTTPS()) {
         $proto = 'https';
         if (is_string(common_config('site', 'sslserver')) &&
             mb_strlen(common_config('site', 'sslserver')) > 0) {
@@ -1396,6 +1408,74 @@ function common_path($relative, $ssl=false, $addSession=true)
     return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
 }
 
+// FIXME: Maybe this should also be able to handle non-fancy URLs with index.php?p=...
+function common_fake_local_fancy_url($url)
+{
+    /**
+     * This is a hacky fix to make URIs generated with "index.php/" match against
+     * locally stored URIs without that. So for example if the remote site is looking
+     * up the webfinger for some user and for some reason knows about https://some.example/user/1
+     * but we locally store and report only https://some.example/index.php/user/1 then they would
+     * dismiss the profile for not having an identified alias.
+     *
+     * There are various live instances where these issues occur, for various reasons.
+     * Most of them being users fiddling with configuration while already having
+     * started federating (distributing the URI to other servers) or maybe manually
+     * editing the local database.
+     */
+    if (!preg_match(
+                // [1] protocol part, we can only rewrite http/https anyway.
+                '/^(https?:\/\/)' .
+                // [2] site name.
+                // FIXME: Dunno how this acts if we're aliasing ourselves with a .onion domain etc.
+                '('.preg_quote(common_config('site', 'server'), '/').')' .
+                // [3] site path, or if that is empty just '/' (to retain the /)
+                '('.preg_quote(common_config('site', 'path') ?: '/', '/').')' .
+                // [4] + [5] extract index.php (+ possible leading double /) and the rest of the URL separately.
+                '(\/?index\.php\/)(.*)$/', $url, $matches)) {
+        // if preg_match failed to match
+        throw new Exception('No known change could be made to the URL.');
+    }
+
+    // now reconstruct the URL with everything except the "index.php/" part
+    $fancy_url = '';
+    foreach ([1,2,3,5] as $idx) {
+        $fancy_url .= $matches[$idx];
+    }
+    return $fancy_url;
+}
+
+// FIXME: Maybe this should also be able to handle non-fancy URLs with index.php?p=...
+function common_fake_local_nonfancy_url($url)
+{
+    /**
+     * This is a hacky fix to make URIs NOT generated with "index.php/" match against
+     * locally stored URIs WITH that. The reverse from the above.
+     *
+     * It will also "repair" index.php URLs with multiple / prepended. Like https://some.example///index.php/user/1
+     */
+    if (!preg_match(
+                // [1] protocol part, we can only rewrite http/https anyway.
+                '/^(https?:\/\/)' .
+                // [2] site name.
+                // FIXME: Dunno how this acts if we're aliasing ourselves with a .onion domain etc.
+                '('.preg_quote(common_config('site', 'server'), '/').')' .
+                // [3] site path, or if that is empty just '/' (to retain the /)
+                '('.preg_quote(common_config('site', 'path') ?: '/', '/').')' .
+                // [4] should be empty (might contain one or more / and then maybe also index.php). Will be overwritten.
+                // [5] will have the extracted actual URL part (besides site path)
+                '((?!index.php\/)\/*(?:index.php\/)?)(.*)$/', $url, $matches)) {
+        // if preg_match failed to match
+        throw new Exception('No known change could be made to the URL.');
+    }
+
+    $matches[4] = 'index.php/'; // inject the index.php/ rewritethingy
+
+    // remove the first element, which is the full matching string
+    array_shift($matches);
+    return implode($matches);
+}
+
 function common_inject_session($url, $serverpart = null)
 {
     if (!common_have_session()) {
@@ -1808,6 +1888,10 @@ function common_log_objstring(&$object)
 
 function common_valid_http_url($url, $secure=false)
 {
+    if (empty($url)) {
+        return false;
+    }
+
     // If $secure is true, only allow https URLs to pass
     // (if false, we use '?' in 'https?' to say the 's' is optional)
     $regex = $secure ? '/^https$/' : '/^https?$/';