emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master b909718: * idna.el (idna-decode-string-internal): I


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] master b909718: * idna.el (idna-decode-string-internal): Implement decoding.
Date: Mon, 28 Dec 2015 03:15:27 +0000

branch: master
commit b9097188f7a6dbfd408a1fe8c6df80526d3bd944
Author: Lars Ingebrigtsen <address@hidden>
Commit: Lars Ingebrigtsen <address@hidden>

    * idna.el (idna-decode-string-internal): Implement decoding.
---
 lisp/net/idna.el |   66 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/lisp/net/idna.el b/lisp/net/idna.el
index dfaf711..052a9f6 100644
--- a/lisp/net/idna.el
+++ b/lisp/net/idna.el
@@ -30,6 +30,9 @@
 (require 'seq)
 
 (defun idna-encode-string (string)
+  "Encode STRING according to the IDNA/punycode algorithm.
+This is used to encode non-ASCII domain names.
+For instance, \"bücher\" => \"xn--bcher-kva\"."
   (let ((ascii (seq-filter (lambda (char)
                              (< char 128))
                            string)))
@@ -37,6 +40,13 @@
         string
       (concat "xn--" ascii "-" (idna-encode-complex (length ascii) string)))))
 
+(defun idna-decode-string (string)
+  "Decode an IDNA/punycode-encoded string.
+For instance \"xn--bcher-kva\" => \"bücher\"."
+  (if (string-match "\\`xn--.*-" string)
+      (idna-decode-string-internal (substring string 4))
+    string))
+
 (defconst idna-initial-n 128)
 (defconst idna-initial-bias 72)
 (defconst idna-base 36)
@@ -47,12 +57,12 @@
 
 (defun idna-decode-digit (cp)
   (cond
-   ((< (- cp 48) 10)
-    (- cp 22))
-   ((< (- cp 65) 26)
-    (- cp 65))
-   ((< (- cp 97) 26)
-    (- cp 97))
+   ((<= cp ?9)
+    (- cp ?0))
+   ((<= cp ?Z)
+    (- cp ?A))
+   ((<= cp ?z)
+    (- cp ?a))
    (t
     idna-base)))
 
@@ -119,6 +129,50 @@
       (cl-incf n))
     (nreverse result)))
 
+(defun idna-decode-string-internal (string)
+  (with-temp-buffer
+    (insert string)
+    (goto-char (point-max))
+    (if (not (search-backward "-" nil t))
+        (error "Invalid IDNA string")
+      ;; The encoded chars are after the final dash.
+      (let ((encoded (buffer-substring (1+ (point)) (point-max)))
+            (ic 0)
+            (i 0)
+            (bias idna-initial-bias)
+            (n idna-initial-n)
+            out)
+        (delete-region (point) (point-max))
+        (while (< ic (length encoded))
+          (let ((old-i i)
+                (w 1)
+                (k idna-base)
+                digit t1)
+            (cl-loop do (progn
+                          (setq digit (idna-decode-digit (aref encoded ic)))
+                          (cl-incf ic)
+                          (cl-incf i (* digit w))
+                          (setq t1 (cond
+                                    ((<= k bias)
+                                     idna-tmin)
+                                    ((>= k (+ bias idna-tmax))
+                                     idna-tmax)
+                                    (t
+                                     (- k bias)))))
+                     while (>= digit t1)
+                     do (setq w (* w (- idna-base t1))
+                              k (+ k idna-base)))
+            (setq out (1+ (buffer-size)))
+            (setq bias (idna-adapt (- i old-i) out (= old-i 0))))
+
+          (setq n (+ n (/ i out))
+                i (mod i out))
+          (goto-char (point-min))
+          (forward-char i)
+          (insert (format "%c" n))
+          (cl-incf i))))
+    (buffer-string)))
+
 (provide 'idna)
 
 ;;; shr.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]