1
0
Fork 0

- added minimal wrapping of libidn2;

- added library checks (libidn2 and libssl) to configure scripts;
- removed commented reference to quri.
This commit is contained in:
cage 2020-12-12 14:47:22 +01:00
parent 2205ab5152
commit 5f8c9d422e
8 changed files with 240 additions and 4 deletions

View File

@ -75,7 +75,8 @@
** Foreign (C language) library
- libssl
- libssl (TLS socket)
- linidn2 (i18n domain name aka idna)
* Install

View File

@ -119,7 +119,8 @@ Table of Contents
3.3 Foreign (C language) library
────────────────────────────────
• libssl
• libssl (TLS socket)
• linidn2 (i18n domain name aka idna)
4 Install
@ -266,7 +267,7 @@ Table of Contents
Any help is appreciated. If you intend to contribute please point your
browser to the [issue tracker] or file a [pull request].
But, please take a minute to read the file <file:./CONTRIBUTING.org>
But, please take a minute to read the file <./CONTRIBUTING.org>
[issue tracker] <https://notabug.org/cage/tinmop/issues>

89
configure vendored
View File

@ -6127,6 +6127,95 @@ $as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for idn2_to_ascii_8z in -lidn2" >&5
$as_echo_n "checking for idn2_to_ascii_8z in -lidn2... " >&6; }
if ${ac_cv_lib_idn2_idn2_to_ascii_8z+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lidn2 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char idn2_to_ascii_8z ();
int
main ()
{
return idn2_to_ascii_8z ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_idn2_idn2_to_ascii_8z=yes
else
ac_cv_lib_idn2_idn2_to_ascii_8z=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_idn2_idn2_to_ascii_8z" >&5
$as_echo "$ac_cv_lib_idn2_idn2_to_ascii_8z" >&6; }
if test "x$ac_cv_lib_idn2_idn2_to_ascii_8z" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBIDN2 1
_ACEOF
LIBS="-lidn2 $LIBS"
else
as_fn_error $? "Can not this function find libidn2." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_get_version in -lssl" >&5
$as_echo_n "checking for SSL_get_version in -lssl... " >&6; }
if ${ac_cv_lib_ssl_SSL_get_version+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lssl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char SSL_get_version ();
int
main ()
{
return SSL_get_version ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ssl_SSL_get_version=yes
else
ac_cv_lib_ssl_SSL_get_version=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_get_version" >&5
$as_echo "$ac_cv_lib_ssl_SSL_get_version" >&6; }
if test "x$ac_cv_lib_ssl_SSL_get_version" = xyes; then :
as_fn_error $? "Can not find libssl." "$LINENO" 5
fi
# Extract the first word of "sbcl", so it can be a program name with args.
set dummy sbcl; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5

View File

@ -21,6 +21,10 @@ AM_INIT_AUTOMAKE([-Wall foreign])
AM_GNU_GETTEXT([external])
AC_CHECK_LIB([idn2], [idn2_to_ascii_8z], [], AC_MSG_ERROR([Can not this function find libidn2.]))
AC_CHECK_LIB([ssl], [SSL_get_version], AC_MSG_ERROR([Can not find libssl.]))
AC_PATH_PROG([LISP_COMPILER],[sbcl],[no])
if test "$LISP_COMPILER" = "no" ; then

44
src/grovel-idn.lisp Normal file
View File

@ -0,0 +1,44 @@
(in-package :idn)
(include "idn2.h")
(cenum (idn2-rc :define-constants t)
((:ok "IDN2_OK"))
((:malloc "IDN2_MALLOC"))
((:no-codeset "IDN2_NO_CODESET"))
((:iconv-fail "IDN2_ICONV_FAIL"))
((:encoding-error "IDN2_ENCODING_ERROR"))
((:nfc "IDN2_NFC"))
((:punycode-bad-input "IDN2_PUNYCODE_BAD_INPUT"))
((:punycode-big-output "IDN2_PUNYCODE_BIG_OUTPUT"))
((:punycode-overflow "IDN2_PUNYCODE_OVERFLOW"))
((:too-big-domain "IDN2_TOO_BIG_DOMAIN"))
((:too-big-label "IDN2_TOO_BIG_LABEL"))
((:invalid-alabel "IDN2_INVALID_ALABEL"))
((:ualabel-mismatch "IDN2_UALABEL_MISMATCH"))
((:invalid-flags "IDN2_INVALID_FLAGS"))
((:not-nfc "IDN2_NOT_NFC"))
((:2hyphen "IDN2_2HYPHEN"))
((:hyphen-startend "IDN2_HYPHEN_STARTEND"))
((:leading-combining "IDN2_LEADING_COMBINING"))
((:disallowed "IDN2_DISALLOWED"))
((:contextj "IDN2_CONTEXTJ"))
((:contextj-no-rule "IDN2_CONTEXTJ_NO_RULE"))
((:contexto "IDN2_CONTEXTO"))
((:contexto-no-rule "IDN2_CONTEXTO_NO_RULE"))
((:unassigned "IDN2_UNASSIGNED"))
((:bidi "IDN2_BIDI"))
((:dot-in-label "IDN2_DOT_IN_LABEL"))
((:invalid-transitional "IDN2_INVALID_TRANSITIONAL"))
((:invalid-nontransitional "IDN2_INVALID_NONTRANSITIONAL"))
((:alabel-roundtrip-failed "IDN2_ALABEL_ROUNDTRIP_FAILED")))
(cenum (flags :define-constants t)
((:nfc-input "IDN2_NFC_INPUT"))
((:alabel-roundtrip "IDN2_ALABEL_ROUNDTRIP"))
((:transitional "IDN2_TRANSITIONAL"))
((:nontransitional "IDN2_NONTRANSITIONAL"))
((:allow-unassigned "IDN2_ALLOW_UNASSIGNED"))
((:use-std3-ascii-rules "IDN2_USE_STD3_ASCII_RULES"))
((:no-tr46 "IDN2_NO_TR46"))
((:no-alabel-roundtrip "IDN2_NO_ALABEL_ROUNDTRIP")))

89
src/idn.lisp Normal file
View File

@ -0,0 +1,89 @@
(in-package :idn)
(cffi:define-foreign-library libidn2
(:unix (:or "libidn2.so.0" "libidn2.so"))
(t (:default "libmagic")))
(cffi:use-foreign-library libidn2)
;; int idn2_to_ascii_8z (const char * input, char ** output, int flags)
(cffi:defcfun (idn2-to-ascii-8z "idn2_to_ascii_8z")
:int
(input :pointer)
(output :pointer)
(flags :int))
;; int idn2_to_unicode_8z8z (const char *input, char **output, int flags)
(cffi:defcfun (idn2-to-unicode-8z8z "idn2_to_unicode_8z8z")
:int
(input :pointer)
(output :pointer)
(flags :int)) ; unused
(define-condition punycode-conversion-error (error)
((host
:initarg :host
:reader host)
(error-code
:initarg :error-code
:reader error-code))
(:report (lambda (condition stream)
(format stream
"error converting ~a to ASCII (code: ~a)"
(host condition)
(error-code condition))))
(:documentation "Error conversion unicode -> ASCII"))
(defun ->ascii-default-flags ()
(logior (cffi:foreign-enum-value 'flags :nontransitional)
(cffi:foreign-enum-value 'flags :nfc-input)))
(defun unicode->ascii (host &optional (flags (->ascii-default-flags)))
(labels ((deref (ptr** index)
(cffi:mem-aref (cffi:mem-aref ptr** :pointer)
:char index)))
(cffi:with-foreign-string (input host)
(cffi:with-foreign-object (buf* :unsigned-char)
(cffi:with-foreign-object (buf** :pointer)
(setf (cffi:mem-ref buf** :pointer) buf*)
(let ((results (idn2-to-ascii-8z input buf** flags)))
(unwind-protect
(if (= (cffi:foreign-enum-value 'idn2-rc :ok)
results)
(with-output-to-string (punycode)
(loop for i from 0 while (/= (deref buf** i)
0)
do
(let ((octect (deref buf** i)))
(write-char (code-char octect) punycode))))
(error 'punycode-conversion-error
:host host
:error-code (cffi:foreign-enum-keyword 'idn2-rc results)))
(cffi:foreign-free (cffi:mem-aref buf** :pointer)))))))))
(defun ascii->unicode (host)
(labels ((deref (ptr** index)
(cffi:mem-aref (cffi:mem-aref ptr** :pointer)
:char index)))
(cffi:with-foreign-string (input host)
(cffi:with-foreign-object (buf* :unsigned-char)
(cffi:with-foreign-object (buf** :pointer)
(setf (cffi:mem-ref buf** :pointer) buf*)
(let ((results (idn2-to-unicode-8z8z input buf** 0)))
(unwind-protect
(if (= (cffi:foreign-enum-value 'idn2-rc :ok)
results)
(let ((octects (misc:make-array-frame 0 0 '(unsigned-byte 8))))
(loop for i from 0 while (/= (deref buf** i)
0)
do
(vector-push-extend (logand (deref buf** i) 255)
octects))
(babel:octets-to-string octects))
(error 'punycode-conversion-error
:host host
:error-code (cffi:foreign-enum-keyword 'idn2-rc results)))
(cffi:foreign-free (cffi:mem-aref buf** :pointer)))))))))

View File

@ -14,6 +14,12 @@
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(defpackage :idn
(:use :cl)
(:export
:unicode->ascii
:ascii->unicode))
(defpackage :config
(:use :cl)
(:export

View File

@ -21,6 +21,7 @@
:version "0.3.2"
:pathname "src"
:serial t
:defsystem-depends-on ("cffi-grovel")
:depends-on (:alexandria
:cl-ppcre
:tooter
@ -49,10 +50,11 @@
:drakma
:usocket
:babel
; :quri
:percent-encoding
:uiop)
:components ((:file "package")
(:cffi-grovel-file "grovel-idn")
(:file "idn")
(:file "config")
(:file "constants")
(:file "conditions")