[BUGFIX] Make php-intl work with older ICU versions 10/60710/3
authorBenni Mack <benni@typo3.org>
Tue, 7 May 2019 13:08:00 +0000 (15:08 +0200)
committerAndreas Fernandez <a.fernandez@scripting-base.de>
Wed, 8 May 2019 21:05:13 +0000 (23:05 +0200)
On old OS with ICU < 4.6, the constant INTL_IDNA_VARIANT_UTS46
is not available, even if php-intl is installed.

Therefore, a wrapper is created in HttpUtility to check
if the constant is available, then uses INTL_IDNA_VARIANT_UTS46
otherwise the 2003 version of the HttpUtility.

Also see the section about INTL_IDNA_VARIANT_UTS46 within
https://www.php.net/manual/en/intl.constants.php

Resolves: #87953
Releases: master, 9.5
Change-Id: I594c0ffd9afa115de595b0c027bf2474c3abfafb
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60710
Reviewed-by: Sven Juergens <typo3@blue-side.de>
Reviewed-by: Kevin Meckl <kevin.meckl@zdrei.com>
Reviewed-by: Timo Poppinga <timo.poppinga@zdrei.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Timo Poppinga <timo.poppinga@zdrei.com>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Classes/Mail/MailMessage.php
typo3/sysext/core/Classes/Routing/SiteMatcher.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/core/Classes/Utility/HttpUtility.php
typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php
typo3/sysext/linkvalidator/Classes/Linktype/ExternalLinktype.php

index a3b20ae..5f258f6 100644 (file)
@@ -55,6 +55,7 @@ use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
@@ -2604,7 +2605,7 @@ class DataHandler implements LoggerAwareInterface
                     break;
                 case 'domainname':
                     if (!preg_match('/^[a-z0-9.\\-]*$/i', $value)) {
-                        $value = (string)idn_to_ascii($value, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+                        $value = (string)HttpUtility::idn_to_ascii($value);
                     }
                     break;
                 case 'email':
index e14e094..39be762 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Mail;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MailUtility;
 
 /**
@@ -265,7 +266,7 @@ class MailMessage extends \Swift_Message
         }
         $domain = substr($email, $atPosition + 1);
         $local = substr($email, 0, $atPosition);
-        $domain = (string)idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+        $domain = (string)HttpUtility::idn_to_ascii($domain);
 
         return $local . '@' . $domain;
     }
index ffdd10a..332488d 100644 (file)
@@ -30,6 +30,7 @@ use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Site\PseudoSiteFinder;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
 
 /**
@@ -135,7 +136,7 @@ class SiteMatcher implements SingletonInterface
             $context = new RequestContext(
                 '',
                 $request->getMethod(),
-                idn_to_ascii($request->getUri()->getHost(), IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46),
+                HttpUtility::idn_to_ascii($request->getUri()->getHost()),
                 $request->getUri()->getScheme(),
                 // Ports are only necessary for URL generation in Symfony which is not used by TYPO3
                 80,
@@ -235,7 +236,7 @@ class SiteMatcher implements SingletonInterface
                     ['site' => $site, 'language' => $siteLanguage, 'tail' => ''],
                     array_filter(['tail' => '.*', 'port' => (string)$uri->getPort()]),
                     ['utf8' => true],
-                    idn_to_ascii($uri->getHost(), IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46) ?: '',
+                    HttpUtility::idn_to_ascii($uri->getHost()) ?: '',
                     $uri->getScheme()
                 );
                 $identifier = 'site_' . $site->getIdentifier() . '_' . $siteLanguage->getLanguageId();
index 2395f7a..33f656d 100644 (file)
@@ -867,7 +867,7 @@ class GeneralUtility
         $domain = substr($email, $atPosition + 1);
         $user = substr($email, 0, $atPosition);
         if (!preg_match('/^[a-z0-9.\\-]*$/i', $domain)) {
-            $domain = idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+            $domain = HttpUtility::idn_to_ascii($domain);
             if ($domain === false) {
                 return false;
             }
@@ -895,11 +895,11 @@ class GeneralUtility
         if ($atPosition !== false) {
             $domain = substr($value, $atPosition + 1);
             $local = substr($value, 0, $atPosition);
-            $domain = (string)idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+            $domain = (string)HttpUtility::idn_to_ascii($domain);
             // Return if no @ found or it is placed at the very beginning or end of the email
             return $local . '@' . $domain;
         }
-        return (string)idn_to_ascii($value, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+        return (string)HttpUtility::idn_to_ascii($value);
     }
 
     /**
@@ -982,7 +982,7 @@ class GeneralUtility
             return false;
         }
         if (isset($parsedUrl['host']) && !preg_match('/^[a-z0-9.\\-]*$/i', $parsedUrl['host'])) {
-            $host = idn_to_ascii($parsedUrl['host'], IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+            $host = HttpUtility::idn_to_ascii($parsedUrl['host']);
             if ($host === false) {
                 return false;
             }
index a137144..d6bef01 100644 (file)
@@ -178,4 +178,22 @@ class HttpUtility
 
         return $queryString && $prependCharacter ? $prependCharacter . $queryString : $queryString;
     }
+
+    /**
+     * Compatibility layer for PHP versions running ICU 4.4, as the constant INTL_IDNA_VARIANT_UTS46
+     * is only available as of ICU 4.6.
+     *
+     * Please note: Once PHP 7.4 is the minimum requirement, this method will vanish without further notice
+     * as it is recommended to use the native method instead, when working against a clean environment.
+     *
+     * @param string $domain the domain name to convert Punicode to ASCII.
+     * @return string|bool
+     */
+    public static function idn_to_ascii(string $domain)
+    {
+        if (defined('INTL_IDNA_VARIANT_UTS46')) {
+            return idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+        }
+        return idn_to_ascii($domain);
+    }
 }
index ca54c25..a009c0f 100644 (file)
@@ -469,7 +469,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
             $target = $target ?: $this->resolveTargetAttribute($conf, 'extTarget', false, $tsfe->extTarget);
             // Convert IDNA-like domain (if any)
             if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
-                $targetDomain = (string)idn_to_ascii($targetDomain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+                $targetDomain = HttpUtility::idn_to_ascii($targetDomain);
             }
             $url = $absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'] . $additionalQueryParams;
         } else {
index 908d5e6..b44aeea 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Linkvalidator\Linktype;
 use GuzzleHttp\Cookie\CookieJar;
 use TYPO3\CMS\Core\Http\RequestFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
 
 /**
  * This class provides Check External Links plugin implementation
@@ -207,6 +208,6 @@ class ExternalLinktype extends AbstractLinktype
      */
     protected function preprocessUrl(string $url): string
     {
-        return (string)idn_to_ascii($url, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
+        return (string)HttpUtility::idn_to_ascii($url);
     }
 }