Support IDNA - internationalized domain names
authorChristian Weiske <cweiske@cweiske.de>
Mon, 11 Jul 2016 05:52:54 +0000 (07:52 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Mon, 11 Jul 2016 05:52:54 +0000 (07:52 +0200)
src/phancap/Options.php
www/index.php
www/setup.php

index 47cf2d1..2cfec7e 100644 (file)
@@ -116,6 +116,8 @@ class Options
     public $values = array();
 
     /**
+     * Configuration object
+     *
      * @var Config
      */
     protected $config;
@@ -350,6 +352,33 @@ class Options
         if (!isset($parts['host'])) {
             throw new \InvalidArgumentException('URL host missing');
         }
+
+        $rebuild = false;
+        if (strlen(preg_replace('#[[:ascii:]]#', '', $parts['host']))) {
+            //non-ascii characters in the host name
+            $host = idn_to_ascii($parts['host']);
+            if ($host === false) {
+                //incoming URL was not UTF-8 but some ISO dialect
+                $host = idn_to_ascii(utf8_encode($parts['host']));
+                if ($host === false) {
+                    throw new \InvalidArgumentException(
+                        'Strange characters in host name'
+                    );
+                }
+            }
+            $parts['host'] = $host;
+            $rebuild = true;
+        }
+        if (strlen(preg_replace('#[[:ascii:]]#', '', $parts['path']))) {
+            //non-ascii characters in the path
+            $parts['path'] = str_replace('%2F', '/', urlencode($parts['path']));
+            $rebuild = true;
+        }
+
+        if ($rebuild) {
+            $url = static::http_build_url($parts);
+        }
+
         return $url;
     }
 
@@ -366,5 +395,36 @@ class Options
         $this->options['smaxage']['default'] = $this->config->screenshotMaxAge;
         $this->options['smaxage']['min']     = $this->config->screenshotMinAge;
     }
+
+    /**
+     * Re-build an URL parts array generated by parse_url()
+     *
+     * @param string $parts Array of URL parts
+     *
+     * @return string URL
+     */
+    protected static function http_build_url($parts)
+    {
+        $scheme   = isset($parts['scheme'])
+            ? $parts['scheme'] . '://' : '';
+        $host     = isset($parts['host'])
+            ? $parts['host'] : '';
+        $port     = isset($parts['port'])
+            ? ':' . $parts['port'] : '';
+        $user     = isset($parts['user'])
+            ? $parts['user'] : '';
+        $pass     = isset($parts['pass'])
+
+            ? ':' . $parts['pass']  : '';
+        $pass     = ($user || $pass)
+            ? "$pass@" : '';
+        $path     = isset($parts['path'])
+            ? $parts['path'] : '';
+        $query    = isset($parts['query'])
+            ? '?' . $parts['query'] : '';
+        $fragment = isset($parts['fragment'])
+            ? '#' . $parts['fragment'] : '';
+        return "$scheme$user$pass$host$port$path$query$fragment";
+    }
 }
 ?>
index 2f4c0de..7347517 100644 (file)
@@ -34,7 +34,7 @@ try {
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
   <title>phancap</title>
-
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
   <link rel="stylesheet" href="css/bootstrap.min.css"/>
   <link rel="stylesheet" href="css/bootstrap-theme.min.css"/>
   <link rel="stylesheet" href="css/phancap.css"/>
index 10f23fc..7772bad 100644 (file)
@@ -82,11 +82,18 @@ foreach ($adapter as $classpart) {
     }
 }
 
+if (!function_exists('idn_to_ascii')) {
+    $messages[][] = array(
+        'err', 'Function "idn_to_ascii" is not available'
+    );
+}
+
 $out = <<<HTM
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
   <title>phancap setup check</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
   <link rel="stylesheet" href="css/bootstrap.min.css"/>
   <link rel="stylesheet" href="css/bootstrap-theme.min.css"/>
   <link rel="stylesheet" href="css/phancap.css"/>