Merge branch 'master' into debian

This commit is contained in:
Daniel Kahn Gillmor 2014-06-23 12:39:47 -04:00
commit df2e65b9d2
13 changed files with 784 additions and 418 deletions

View File

@ -3,8 +3,15 @@ compiler:
- gcc - gcc
- clang - clang
# Change this to your needs # Change this to your needs
script: ./autogen.sh && ./configure --enable-gtk-doc && make -j4 && make check -j4 && make distcheck script:
- ./autogen.sh
- ./configure && make -j4 && make check -j4
- ./configure --without-libicu && make clean && make -j4 && make check -j4
- ./configure --disable-builtin && make clean && make -j4 && make check -j4
- ./configure --disable-builtin --without-libicu && make clean && make -j4 && make check -j4
- ./configure --enable-gtk-doc && make -j4 && make check -j4
- make distcheck
before_install: before_install:
- apt-cache search libicu | grep icu - apt-cache search libicu | grep icu
- sudo apt-get -qq update - sudo apt-get -qq update
- sudo apt-get -q install autoconf automake autopoint libtool gtk-doc-tools gettext idn2 libidn2-0 libidn2-0-dev libicu-dev - sudo apt-get -q install autoconf automake autopoint libtool gtk-doc-tools gettext idn2 libidn2-0 libidn2-0-dev libicu48 libicu-dev

View File

@ -8,4 +8,6 @@ Please drop me a note if you feel you should have
been mentioned here. been mentioned here.
Tim Ruehsen (Implementation of libpsl) Tim Ruehsen (Implementation of libpsl)
Daniel Kahn Gillmor (Discussion, Ideas, Organization) Daniel Kahn Gillmor (Discussion, Ideas, Organization, Code)
Daniel Stenberg (Discussion, Ideas)
Darshit Shah (Patching Wget to work with libpsl)

9
NEWS
View File

@ -1,5 +1,14 @@
Copyright (C) 2014 Tim Ruehsen Copyright (C) 2014 Tim Ruehsen
23.06.2014 Release V0.4.0
* depend on libicu for punycode, utf-8 and lowercase conversions
* added function psl_str_to_utf8lower()
* fixed locale issues
* introducing psl_error_t for error codes + defines
* removed redundant code from psl2c.c
* updated docs
* psl utility reads from stdin if no argument specified
10.06.2014 Release V0.3.1 10.06.2014 Release V0.3.1
* link psl utility dynamically * link psl utility dynamically
* fix output of psl_filename() * fix output of psl_filename()

View File

@ -1,5 +1,5 @@
AC_INIT([libpsl], [0.3.1], [tim.ruehsen@gmx.de], [libpsl], [http://github.com/rockdaboot/libpsl]) AC_INIT([libpsl], [0.4.0], [tim.ruehsen@gmx.de], [libpsl], [http://github.com/rockdaboot/libpsl])
AC_PREREQ([2.59]) AC_PREREQ([2.59])
AM_INIT_AUTOMAKE([1.10 -Wall no-define]) AM_INIT_AUTOMAKE([1.10 -Wall no-define])
@ -62,10 +62,35 @@ AS_IF([ test "$enable_man" != no ], [
# 3. If the library source code has changed at all since the last update, then increment revision (c:r:a becomes c:r+1:a). # 3. If the library source code has changed at all since the last update, then increment revision (c:r:a becomes c:r+1:a).
# 4. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0. # 4. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# 5. If any interfaces have been added since the last public release, then increment age. # 5. If any interfaces have been added since the last public release, then increment age.
# 6. If any interfaces have been removed or changed since the last public release, then set age to 0. # 6. If any existing interfaces have been removed or changed since the last public release, then set age to 0.
AC_SUBST([LIBPSL_SO_VERSION], [1:1:1]) AC_SUBST([LIBPSL_SO_VERSION], [2:0:2])
AC_SUBST([LIBPSL_VERSION], $VERSION) AC_SUBST([LIBPSL_VERSION], $VERSION)
# Check for libicu
HAVE_LIBICU=no
AC_ARG_WITH(libicu,
AC_HELP_STRING([--without-libicu], [build libpsl without IDNA/Punycode support]),
[],
[
# using pkg-config won't work on older systems like Ubuntu 12.04 LTS Server Edition 64bit
OLDLIBS=$LIBS
LIBS="-licuuc $LIBS"
AC_MSG_CHECKING([for ICU unicode library])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <unicode/ustring.h>]],
[[u_strToUTF8(NULL, 0, NULL, NULL, 0, NULL);]])],
[HAVE_LIBICU=yes; AC_MSG_RESULT([yes]) AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])],
[LIBS=$OLDLIBS; AC_MSG_ERROR([no working ICU unicode library was found])])
# AC_SEARCH_LIBS(uidna_close, icuuc,
# [HAVE_LIBICU=yes; AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])],
# [AC_MSG_ERROR(*** libicu was not found. Aborting.)],
# -licudata )
# PKG_CHECK_MODULES(LIBICU, [icu-uc],
# [HAVE_LIBICU=yes; AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])])
])
# Check for enable/disable builtin PSL data # Check for enable/disable builtin PSL data
AC_ARG_ENABLE(builtin, AC_ARG_ENABLE(builtin,
AS_HELP_STRING([--disable-builtin], [do not compile PSL data into library]), AS_HELP_STRING([--disable-builtin], [do not compile PSL data into library]),
@ -74,10 +99,11 @@ AC_ARG_ENABLE(builtin,
], [ ], [
enable_builtin=yes enable_builtin=yes
AC_DEFINE([WITH_BUILTIN], [1], [compile PSL data into library]) AC_DEFINE([WITH_BUILTIN], [1], [compile PSL data into library])
AS_IF([test $HAVE_LIBICU != yes],
PKG_CHECK_MODULES(LIBICU, [icu-uc], [
[AC_DEFINE([WITH_LIBICU], [1], [generate PSL data with IDNA2008 UTS#46 punycode])], # Check for idn2 fallback to generate punycode
[AC_CHECK_PROG(HAVE_IDN2, idn2, yes, AC_MSG_ERROR(Cannot find required tool 'idn2'.))]) AC_CHECK_PROG(HAVE_IDN2, idn2, yes, AC_MSG_ERROR(Cannot find required tool 'idn2' as fallback.))
])
]) ])
AM_CONDITIONAL([WITH_BUILTIN], [test $enable_builtin = yes]) AM_CONDITIONAL([WITH_BUILTIN], [test $enable_builtin = yes])
@ -102,16 +128,14 @@ fi
# Check for custom PSL file # Check for custom PSL file
AC_ARG_WITH(psl-file, AC_ARG_WITH(psl-file,
AC_HELP_STRING([--with-psl-file=[PATH]], AC_HELP_STRING([--with-psl-file=[PATH]], [path to PSL file]),
[path to PSL file]),
PSL_FILE=$withval, PSL_FILE=$withval,
PSL_FILE="\$(top_srcdir)/data/effective_tld_names.dat") PSL_FILE="\$(top_srcdir)/data/effective_tld_names.dat")
AC_SUBST(PSL_FILE) AC_SUBST(PSL_FILE)
# Check for custom PSL test file # Check for custom PSL test file
AC_ARG_WITH(psl-testfile, AC_ARG_WITH(psl-testfile,
AC_HELP_STRING([--with-psl-testfile=[PATH]], AC_HELP_STRING([--with-psl-testfile=[PATH]], [path to PSL test file]),
[path to PSL test file]),
PSL_TESTFILE=$withval, PSL_TESTFILE=$withval,
PSL_TESTFILE="\$(top_srcdir)/data/test_psl.txt") PSL_TESTFILE="\$(top_srcdir)/data/test_psl.txt")
AC_SUBST(PSL_TESTFILE) AC_SUBST(PSL_TESTFILE)
@ -138,6 +162,7 @@ AC_MSG_NOTICE([Summary of build options:
Compiler: ${CC} Compiler: ${CC}
CFlags: ${CFLAGS} ${CPPFLAGS} CFlags: ${CFLAGS} ${CPPFLAGS}
LDFlags: ${LDFLAGS} LDFlags: ${LDFLAGS}
ICU: ${HAVE_LIBICU}
Builtin PSL: ${enable_builtin} Builtin PSL: ${enable_builtin}
PSL File: ${PSL_FILE} PSL File: ${PSL_FILE}
PSL Test File: ${PSL_TESTFILE} PSL Test File: ${PSL_TESTFILE}

View File

@ -180,6 +180,7 @@ ar
com.ar com.ar
edu.ar edu.ar
gob.ar gob.ar
gov.ar
int.ar int.ar
mil.ar mil.ar
net.ar net.ar
@ -222,7 +223,6 @@ edu.au
gov.au gov.au
asn.au asn.au
id.au id.au
csiro.au
// Historic 2LDs (closed to new registration, but sites still exist) // Historic 2LDs (closed to new registration, but sites still exist)
info.au info.au
conf.au conf.au
@ -245,7 +245,7 @@ sa.edu.au
tas.edu.au tas.edu.au
vic.edu.au vic.edu.au
wa.edu.au wa.edu.au
act.gov.au // act.gov.au Bug 984824 - Removed at request of Greg Tankard
// nsw.gov.au Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au> // nsw.gov.au Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au>
// nt.gov.au Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au> // nt.gov.au Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au>
qld.gov.au qld.gov.au
@ -292,6 +292,7 @@ rs.ba
// bb : http://en.wikipedia.org/wiki/.bb // bb : http://en.wikipedia.org/wiki/.bb
bb bb
biz.bb biz.bb
co.bb
com.bb com.bb
edu.bb edu.bb
gov.bb gov.bb
@ -299,6 +300,7 @@ info.bb
net.bb net.bb
org.bb org.bb
store.bb store.bb
tv.bb
// bd : http://en.wikipedia.org/wiki/.bd // bd : http://en.wikipedia.org/wiki/.bd
*.bd *.bd
@ -596,9 +598,12 @@ gob.cl
co.cl co.cl
mil.cl mil.cl
// cm : http://en.wikipedia.org/wiki/.cm // cm : http://en.wikipedia.org/wiki/.cm plus bug 981927
cm cm
co.cm
com.cm
gov.cm gov.cm
net.cm
// cn : http://en.wikipedia.org/wiki/.cn // cn : http://en.wikipedia.org/wiki/.cn
// Submitted by registry <tanyaling@cnnic.cn> 2008-06-11 // Submitted by registry <tanyaling@cnnic.cn> 2008-06-11
@ -5146,7 +5151,24 @@ com.nr
nu nu
// nz : http://en.wikipedia.org/wiki/.nz // nz : http://en.wikipedia.org/wiki/.nz
*.nz // Confirmed by registry <jay@nzrs.net.nz> 2014-05-19
nz
ac.nz
co.nz
cri.nz
geek.nz
gen.nz
govt.nz
health.nz
iwi.nz
kiwi.nz
maori.nz
mil.nz
māori.nz
net.nz
org.nz
parliament.nz
school.nz
// om : http://en.wikipedia.org/wiki/.om // om : http://en.wikipedia.org/wiki/.om
om om
@ -5613,7 +5635,6 @@ oryol.ru
palana.ru palana.ru
penza.ru penza.ru
perm.ru perm.ru
pskov.ru
ptz.ru ptz.ru
rnd.ru rnd.ru
ryazan.ru ryazan.ru
@ -6150,19 +6171,19 @@ com.ug
org.ug org.ug
// uk : http://en.wikipedia.org/wiki/.uk // uk : http://en.wikipedia.org/wiki/.uk
// Submitted by registry <noc@nominet.org.uk> 2012-10-02 // Submitted by registry <Michael.Daly@nominet.org.uk>
// and tweaked by us pending further consultation. uk
*.uk ac.uk
co.uk
gov.uk
ltd.uk
me.uk
net.uk
nhs.uk
org.uk
plc.uk
police.uk
*.sch.uk *.sch.uk
!bl.uk
!british-library.uk
!jet.uk
!mod.uk
!national-library-scotland.uk
!nel.uk
!nic.uk
!nls.uk
!parliament.uk
// us : http://en.wikipedia.org/wiki/.us // us : http://en.wikipedia.org/wiki/.us
us us
@ -6440,16 +6461,24 @@ edu.vc
// ve : https://registro.nic.ve/ // ve : https://registro.nic.ve/
// Confirmed by registry 2012-10-04 // Confirmed by registry 2012-10-04
// Updated 2014-05-20 - Bug 940478
ve ve
arts.ve
co.ve co.ve
com.ve com.ve
e12.ve e12.ve
edu.ve edu.ve
firm.ve
gob.ve
gov.ve gov.ve
info.ve info.ve
int.ve
mil.ve mil.ve
net.ve net.ve
org.ve org.ve
rec.ve
store.ve
tec.ve
web.ve web.ve
// vg : http://en.wikipedia.org/wiki/.vg // vg : http://en.wikipedia.org/wiki/.vg
@ -6482,8 +6511,12 @@ pro.vn
health.vn health.vn
// vu : http://en.wikipedia.org/wiki/.vu // vu : http://en.wikipedia.org/wiki/.vu
// list of 2nd level tlds ? // http://www.vunic.vu/
vu vu
com.vu
edu.vu
net.vu
org.vu
// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf // wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
wf wf
@ -6609,7 +6642,14 @@ yt
فلسطين فلسطين
// xn--90a3ac ("srb" Cyrillic) : RS // xn--90a3ac ("srb" Cyrillic) : RS
// http://www.rnids.rs/en/the-.срб-domain
срб срб
пр.срб
орг.срб
обр.срб
од.срб
упр.срб
ак.срб
// xn--p1ai ("rf" Russian-Cyrillic) : RU // xn--p1ai ("rf" Russian-Cyrillic) : RU
// http://www.cctld.ru/en/docs/rulesrf.php // http://www.cctld.ru/en/docs/rulesrf.php
@ -7654,6 +7694,299 @@ sca
// reise : 2014-03-13 dotreise GmbH // reise : 2014-03-13 dotreise GmbH
reise reise
// accountants : 2014-03-20 Knob Town, LLC
accountants
// clinic : 2014-03-20 Goose Park, LLC
clinic
// versicherung : 2014-03-20 dotversicherung-registry GmbH
versicherung
// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd.
top
// furniture : 2014-03-20 Lone Fields, LLC
furniture
// dental : 2014-03-20 Tin Birch, LLC
dental
// fund : 2014-03-20 John Castle, LLC
fund
// creditcard : 2014-03-20 Binky Frostbite, LLC
creditcard
// insure : 2014-03-20 Pioneer Willow, LLC
insure
// audio : 2014-03-20 Uniregistry, Corp.
audio
// claims : 2014-03-20 Black Corner, LLC
claims
// loans : 2014-03-20 June Woods, LLC
loans
// auction : 2014-03-20 Sand Galley, LLC
auction
// attorney : 2014-03-20 Victor North, LLC
attorney
// finance : 2014-03-20 Cotton Cypress, LLC
finance
// investments : 2014-03-20 Holly Glen, LLC
investments
// juegos : 2014-03-20 Uniregistry, Corp.
juegos
// dentist : 2014-03-20 Outer Lake, LLC
dentist
// lds : 2014-03-20 IRI Domain Management, LLC
lds
// lawyer : 2014-03-20 Atomic Station, LLC
lawyer
// surgery : 2014-03-20 Tin Avenue, LLC
surgery
// gratis : 2014-03-20 Pioneer Tigers, LLC
gratis
// software : 2014-03-20 Over Birch, LLC
software
// mortgage : 2014-03-20 Outer Gardens, LLC
mortgage
// republican : 2014-03-20 United TLD Holdco Ltd.
republican
// credit : 2014-03-20 Snow Shadow, LLC
credit
// tax : 2014-03-20 Storm Orchard, LLC
tax
// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
africa
// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
joburg
// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
durban
// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
capetown
// sap : 2014-03-27 SAP AG
sap
// datsun : 2014-03-27 NISSAN MOTOR CO., LTD.
datsun
// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD.
infiniti
// firmdale : 2014-03-27 Firmdale Holdings Limited
firmdale
// organic : 2014-03-27 Afilias Limited
organic
// nissan : 2014-03-27 NISSAN MOTOR CO., LTD.
nissan
// website : 2014-04-03 DotWebsite Inc.
website
// space : 2014-04-03 DotSpace Inc.
space
// schmidt : 2014-04-03 SALM S.A.S.
schmidt
// cuisinella : 2014-04-03 SALM S.A.S.
cuisinella
// samsung : 2014-04-03 SAMSUNG SDS CO., LTD
samsung
// crs : 2014-04-03 Federated Co operatives Limited
crs
// doosan : 2014-04-03 Doosan Corporation
doosan
// press : 2014-04-03 DotPress Inc.
press
// emerck : 2014-04-03 Merck KGaA
emerck
// erni : 2014-04-03 ERNI Group Holding AG
erni
// direct : 2014-04-10 Half Trail, LLC
direct
// yandex : 2014-04-10 YANDEX, LLC
yandex
// lotto : 2014-04-10 Afilias Limited
lotto
// toshiba : 2014-04-10 TOSHIBA Corporation
toshiba
// bauhaus : 2014-04-17 Werkhaus GmbH
bauhaus
// host : 2014-04-17 DotHost Inc.
host
// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA
ltda
// global : 2014-04-17 Dot GLOBAL AS
global
// abogado : 2014-04-24 Top Level Domain Holdings Limited
abogado
// place : 2014-04-24 Snow Galley, LLC
place
// tirol : 2014-04-24 punkt Tirol GmbH
tirol
// gmx : 2014-04-24 1&1 Mail & Media GmbH
gmx
// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
tatar
// scholarships : 2014-04-24 Scholarships.com, LLC
scholarships
// eurovision : 2014-04-24 European Broadcasting Union (EBU)
eurovision
// wedding : 2014-04-24 Top Level Domain Holdings Limited
wedding
// active : 2014-05-01 The Active Network, Inc
active
// madrid : 2014-05-01 Comunidad de Madrid
madrid
// youtube : 2014-05-01 Charleston Road Registry Inc.
youtube
// sharp : 2014-05-01 Sharp Corporation
sharp
// uol : 2014-05-01 UBN INTERNET LTDA.
uol
// physio : 2014-05-01 PhysBiz Pty Ltd
physio
// gmail : 2014-05-01 Charleston Road Registry Inc.
gmail
// channel : 2014-05-08 Charleston Road Registry Inc.
channel
// fly : 2014-05-08 Charleston Road Registry Inc.
fly
// zip : 2014-05-08 Charleston Road Registry Inc.
zip
// esq : 2014-05-08 Charleston Road Registry Inc.
esq
// rsvp : 2014-05-08 Charleston Road Registry Inc.
rsvp
// wales : 2014-05-08 Nominet UK
wales
// cymru : 2014-05-08 Nominet UK
cymru
// green : 2014-05-08 Afilias Limited
green
// lgbt : 2014-05-08 Afilias Limited
lgbt
// xn--hxt814e : 2014-05-15 Zodiac Libra Limited
网店
// cancerresearch : 2014-05-15 Australian Cancer Research Foundation
cancerresearch
// everbank : 2014-05-15 EverBank
everbank
// frl : 2014-05-15 FRLregistry B.V.
frl
// property : 2014-05-22 Uniregistry, Corp.
property
// forsale : 2014-05-22 Sea Oaks, LLC
forsale
// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal)
seat
// deals : 2014-05-22 Sand Sunset, LLC
deals
// nra : 2014-05-22 NRA Holdings Company, INC.
nra
// xn--fjq720a : 2014-05-22 Will Bloom, LLC
娱乐
// realtor : 2014-05-29 Real Estate Domains LLC
realtor
// bnpparibas : 2014-05-29 BNP Paribas
bnpparibas
// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
melbourne
// hosting : 2014-05-29 Uniregistry, Corp.
hosting
// yoga : 2014-05-29 Top Level Domain Holdings Limited
yoga
// city : 2014-05-29 Snow Sky, LLC
city
// bond : 2014-06-05 Bond University Limited
bond
// click : 2014-06-05 Uniregistry, Corp.
click
// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
cern
// ===END ICANN DOMAINS=== // ===END ICANN DOMAINS===
// ===BEGIN PRIVATE DOMAINS=== // ===BEGIN PRIVATE DOMAINS===
@ -7663,20 +7996,22 @@ reise
cloudfront.net cloudfront.net
// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ // Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/
// Submitted by Osman Surkatty <osmans@amazon.com> 2013-04-02 // Submitted by Osman Surkatty <osmans@amazon.com> 2014-05-20
compute.amazonaws.com
us-east-1.amazonaws.com
compute-1.amazonaws.com
z-1.compute-1.amazonaws.com
z-2.compute-1.amazonaws.com
ap-northeast-1.compute.amazonaws.com ap-northeast-1.compute.amazonaws.com
ap-southeast-1.compute.amazonaws.com ap-southeast-1.compute.amazonaws.com
ap-southeast-2.compute.amazonaws.com ap-southeast-2.compute.amazonaws.com
cn-north-1.compute.amazonaws.cn
compute.amazonaws.cn
compute.amazonaws.com
compute-1.amazonaws.com
eu-west-1.compute.amazonaws.com eu-west-1.compute.amazonaws.com
sa-east-1.compute.amazonaws.com sa-east-1.compute.amazonaws.com
us-east-1.amazonaws.com
us-gov-west-1.compute.amazonaws.com us-gov-west-1.compute.amazonaws.com
us-west-1.compute.amazonaws.com us-west-1.compute.amazonaws.com
us-west-2.compute.amazonaws.com us-west-2.compute.amazonaws.com
z-1.compute-1.amazonaws.com
z-2.compute-1.amazonaws.com
// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ // Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
// Submitted by Adam Stein <astein@amazon.com> 2013-04-02 // Submitted by Adam Stein <astein@amazon.com> 2013-04-02
@ -7719,6 +8054,7 @@ ar.com
br.com br.com
cn.com cn.com
com.de com.de
com.se
de.com de.com
eu.com eu.com
gb.com gb.com
@ -8074,6 +8410,10 @@ global.ssl.fastly.net
a.prod.fastly.net a.prod.fastly.net
global.prod.fastly.net global.prod.fastly.net
// Firebase, Inc.
// Submitted by Chris Raynor <chris@firebase.com> 2014-01-21
firebaseapp.com
// GitHub, Inc. // GitHub, Inc.
// Submitted by Ben Toews <btoews@github.com> 2014-02-06 // Submitted by Ben Toews <btoews@github.com> 2014-02-06
github.io github.io
@ -8153,10 +8493,18 @@ azurewebsites.net
azure-mobile.net azure-mobile.net
cloudapp.net cloudapp.net
// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/
// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net> 2014-02-02
nfshost.com
// NYC.mn : http://www.information.nyc.mn // NYC.mn : http://www.information.nyc.mn
// Submitted by Matthew Brown <mattbrown@nyc.mn> 2013-03-11 // Submitted by Matthew Brown <mattbrown@nyc.mn> 2013-03-11
nyc.mn nyc.mn
// One Fold Media : http://www.onefoldmedia.com/
// Submitted by Eddie Jones <eddie@onefoldmedia.com> 2014-06-10
nid.io
// Opera Software, A.S.A. // Opera Software, A.S.A.
// Submitted by Yngve Pettersen <yngve@opera.com> 2009-11-26 // Submitted by Yngve Pettersen <yngve@opera.com> 2009-11-26
operaunite.com operaunite.com

View File

@ -1,6 +1,7 @@
<SECTION> <SECTION>
<FILE>libpsl</FILE> <FILE>libpsl</FILE>
<TITLE>Public Suffix List functions</TITLE> <TITLE>Public Suffix List functions</TITLE>
psl_error_t
psl_ctx_t psl_ctx_t
psl_load_file psl_load_file
psl_load_fp psl_load_fp
@ -17,4 +18,5 @@ psl_builtin_sha1sum
psl_builtin_filename psl_builtin_filename
psl_is_cookie_domain_acceptable psl_is_cookie_domain_acceptable
psl_get_version psl_get_version
psl_str_to_utf8lower
</SECTION> </SECTION>

View File

@ -38,6 +38,27 @@
extern "C" { extern "C" {
#endif #endif
/**
* psl_error_t:
* @PSL_SUCCESS: Successful return.
* @PSL_ERR_INVALID_ARG: Invalid argument.
* @PSL_ERR_CONVERTER: Failed to open libicu utf-16 converter
* @PSL_ERR_TO_UTF16: Failed to convert to utf-16.
* @PSL_ERR_TO_LOWER: Failed to convert utf-16 to lowercase.
* @PSL_ERR_TO_UTF8: Failed to convert utf-16 to utf-8.
*
* Return codes for PSL functions.
* Negative return codes mean failure.
* Positive values are reserved for non-error return codes.
*/
typedef enum {
PSL_SUCCESS = 0,
PSL_ERR_INVALID_ARG = -1,
PSL_ERR_CONVERTER = -2, /* failed to open libicu utf-16 converter */
PSL_ERR_TO_UTF16 = -3, /* failed to convert to utf-16 */
PSL_ERR_TO_LOWER = -4, /* failed to convert utf-16 to lowercase */
PSL_ERR_TO_UTF8 = -5 /* failed to convert utf-16 to utf-8 */
} psl_error_t;
typedef struct _psl_ctx_st psl_ctx_t; typedef struct _psl_ctx_st psl_ctx_t;
@ -65,6 +86,9 @@ const char *
/* returns the shortest possible registrable domain part or NULL if domain is not registrable at all */ /* returns the shortest possible registrable domain part or NULL if domain is not registrable at all */
const char * const char *
psl_registrable_domain(const psl_ctx_t *psl, const char *domain); psl_registrable_domain(const psl_ctx_t *psl, const char *domain);
/* convert a string into lowercase UTF-8 */
int
psl_str_to_utf8lower(const char *str, const char *encoding, const char *locale, char **lower);
/* does not include exceptions */ /* does not include exceptions */
int int
psl_suffix_count(const psl_ctx_t *psl); psl_suffix_count(const psl_ctx_t *psl);

290
src/psl.c
View File

@ -49,9 +49,20 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <alloca.h>
#ifdef WITH_LIBICU
# include <unicode/uversion.h>
# include <unicode/ustring.h>
# include <unicode/uidna.h>
# include <unicode/ucnv.h>
#endif
#include <libpsl.h> #include <libpsl.h>
/* number of elements within an array */
#define countof(a) (sizeof(a)/sizeof(*(a)))
/** /**
* SECTION:libpsl * SECTION:libpsl
* @short_description: Public Suffix List library functions * @short_description: Public Suffix List library functions
@ -95,7 +106,17 @@ struct _psl_ctx_st {
}; };
/* include the PSL data compiled by 'psl2c' */ /* include the PSL data compiled by 'psl2c' */
#include "suffixes.c" #ifndef _LIBPSL_INCLUDED_BY_PSL2C
# include "suffixes.c"
#else
/* if this source file is included by psl2c.c, provide empty builtin data */
static _psl_entry_t suffixes[1];
static _psl_entry_t suffix_exceptions[1];
static time_t _psl_file_time;
static time_t _psl_compile_time;
static const char _psl_sha1_checksum[] = "";
static const char _psl_filename[] = "";
#endif
/* references to this PSL will result in lookups to built-in data */ /* references to this PSL will result in lookups to built-in data */
static const psl_ctx_t static const psl_ctx_t
@ -239,39 +260,19 @@ static int _suffix_init(_psl_entry_t *suffix, const char *rule, size_t length)
for (dst = suffix->label_buf, src = rule; *src;) { for (dst = suffix->label_buf, src = rule; *src;) {
if (*src == '.') if (*src == '.')
suffix->nlabels++; suffix->nlabels++;
*dst++ = tolower(*src++); *dst++ = *src++;
} }
*dst = 0; *dst = 0;
return 0; return 0;
} }
/** static int _psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
* psl_is_public_suffix:
* @psl: PSL context
* @domain: Domain string
*
* This function checks if @domain is a public suffix by the means of the
* [Mozilla Public Suffix List](http://publicsuffix.org).
*
* For cookie domain checking see psl_is_cookie_domain_acceptable().
*
* @psl is a context returned by either psl_load_file(), psl_load_fp() or
* psl_builtin().
*
* Returns: 1 if domain is a public suffix, 0 if not.
*
* Since: 0.1
*/
int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
{ {
_psl_entry_t suffix, *rule; _psl_entry_t suffix, *rule;
const char *p, *label_bak; const char *p, *label_bak;
unsigned short length_bak; unsigned short length_bak;
if (!psl || !domain)
return 1;
/* this function should be called without leading dots, just make sure */ /* this function should be called without leading dots, just make sure */
suffix.label = domain + (*domain == '.'); suffix.label = domain + (*domain == '.');
suffix.length = strlen(suffix.label); suffix.length = strlen(suffix.label);
@ -340,6 +341,34 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
return 0; return 0;
} }
/**
* psl_is_public_suffix:
* @psl: PSL context
* @domain: Domain string
*
* This function checks if @domain is a public suffix by the means of the
* [Mozilla Public Suffix List](http://publicsuffix.org).
*
* For cookie domain checking see psl_is_cookie_domain_acceptable().
*
* International @domain names have to be either in lowercase UTF-8 or in ASCII form (punycode).
* Other encodings result in unexpected behavior.
*
* @psl is a context returned by either psl_load_file(), psl_load_fp() or
* psl_builtin().
*
* Returns: 1 if domain is a public suffix, 0 if not.
*
* Since: 0.1
*/
int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
{
if (!psl || !domain)
return 1;
return _psl_is_public_suffix(psl, domain);
}
/** /**
* psl_unregistrable_domain: * psl_unregistrable_domain:
* @psl: PSL context * @psl: PSL context
@ -348,6 +377,9 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
* This function finds the longest publix suffix part of @domain by the means * This function finds the longest publix suffix part of @domain by the means
* of the [Mozilla Public Suffix List](http://publicsuffix.org). * of the [Mozilla Public Suffix List](http://publicsuffix.org).
* *
* International @domain names have to be either in lowercase UTF-8 or in ASCII form (punycode).
* Other encodings result in unexpected behavior.
*
* @psl is a context returned by either psl_load_file(), psl_load_fp() or * @psl is a context returned by either psl_load_file(), psl_load_fp() or
* psl_builtin(). * psl_builtin().
* *
@ -366,7 +398,7 @@ const char *psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain)
* 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not. * 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
*/ */
while (!psl_is_public_suffix(psl, domain)) { while (!_psl_is_public_suffix(psl, domain)) {
if ((domain = strchr(domain, '.'))) if ((domain = strchr(domain, '.')))
domain++; domain++;
else else
@ -384,6 +416,9 @@ const char *psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain)
* This function finds the shortest private suffix part of @domain by the means * This function finds the shortest private suffix part of @domain by the means
* of the [Mozilla Public Suffix List](http://publicsuffix.org). * of the [Mozilla Public Suffix List](http://publicsuffix.org).
* *
* International @domain names have to be either in lowercase UTF-8 or in ASCII form (punycode).
* Other encodings result in unexpected behavior.
*
* @psl is a context returned by either psl_load_file(), psl_load_fp() or * @psl is a context returned by either psl_load_file(), psl_load_fp() or
* psl_builtin(). * psl_builtin().
* *
@ -404,7 +439,7 @@ const char *psl_registrable_domain(const psl_ctx_t *psl, const char *domain)
* 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not. * 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
*/ */
while (!psl_is_public_suffix(psl, domain)) { while (!_psl_is_public_suffix(psl, domain)) {
if ((p = strchr(domain, '.'))) { if ((p = strchr(domain, '.'))) {
regdom = domain; regdom = domain;
domain = p + 1; domain = p + 1;
@ -415,6 +450,51 @@ const char *psl_registrable_domain(const psl_ctx_t *psl, const char *domain)
return regdom; return regdom;
} }
static int _str_is_ascii(const char *s)
{
while (*s > 0) s++;
return !*s;
}
#ifdef WITH_LIBICU
static void _add_punycode_if_needed(UIDNA *idna, _psl_vector_t *v, _psl_entry_t *e)
{
if (_str_is_ascii(e->label_buf))
return;
/* IDNA2008 UTS#46 punycode conversion */
if (idna) {
_psl_entry_t suffix, *suffixp;
char lookupname[128] = "";
UErrorCode status = 0;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UChar utf16_dst[128], utf16_src[128];
int32_t utf16_src_length;
u_strFromUTF8(utf16_src, sizeof(utf16_src)/sizeof(utf16_src[0]), &utf16_src_length, e->label_buf, -1, &status);
if (U_SUCCESS(status)) {
int32_t dst_length = uidna_nameToASCII(idna, utf16_src, utf16_src_length, utf16_dst, sizeof(utf16_dst)/sizeof(utf16_dst[0]), &info, &status);
if (U_SUCCESS(status)) {
u_strToUTF8(lookupname, sizeof(lookupname), NULL, utf16_dst, dst_length, &status);
if (U_SUCCESS(status)) {
if (strcmp(e->label_buf, lookupname)) {
/* fprintf(stderr, "libicu '%s' -> '%s'\n", e->label_buf, lookupname); */
_suffix_init(&suffix, lookupname, strlen(lookupname));
suffix.wildcard = e->wildcard;
suffixp = _vector_get(v, _vector_add(v, &suffix));
suffixp->label = suffixp->label_buf; /* set label to changed address */
} /* else ignore */
} /* else
fprintf(stderr, "Failed to convert UTF-16 to UTF-8 (status %d)\n", status); */
} /* else
fprintf(stderr, "Failed to convert to ASCII (status %d)\n", status); */
} /* else
fprintf(stderr, "Failed to convert UTF-8 to UTF-16 (status %d)\n", status); */
}
}
#endif
/** /**
* psl_load_file: * psl_load_file:
* @fname: Name of PSL file * @fname: Name of PSL file
@ -422,13 +502,7 @@ const char *psl_registrable_domain(const psl_ctx_t *psl, const char *domain)
* This function loads the public suffixes file named @fname. * This function loads the public suffixes file named @fname.
* To free the allocated resources, call psl_free(). * To free the allocated resources, call psl_free().
* *
* If you want to use punycode representations for functions like psl_is_public_suffix(), * The suffixes are expected to be lowercase UTF-8 encoded if they are international.
* these have to exist as entries within @fname. This is a design decision to not pull in
* dependencies for UTF-8 case-handling and IDNA libraries.
*
* On the contrary, the builtin data already contains punycode entries.
*
* Have a look into psl2c.c for example code on how to convert UTF-8 to lowercase and to punycode.
* *
* Returns: Pointer to a PSL context or %NULL on failure. * Returns: Pointer to a PSL context or %NULL on failure.
* *
@ -457,7 +531,7 @@ psl_ctx_t *psl_load_file(const char *fname)
* This function loads the public suffixes from a FILE pointer. * This function loads the public suffixes from a FILE pointer.
* To free the allocated resources, call psl_free(). * To free the allocated resources, call psl_free().
* *
* Have a look at psl_load_fp() for punycode considerations. * The suffixes are expected to be lowercase UTF-8 encoded if they are international.
* *
* Returns: Pointer to a PSL context or %NULL on failure. * Returns: Pointer to a PSL context or %NULL on failure.
* *
@ -467,8 +541,11 @@ psl_ctx_t *psl_load_fp(FILE *fp)
{ {
psl_ctx_t *psl; psl_ctx_t *psl;
_psl_entry_t suffix, *suffixp; _psl_entry_t suffix, *suffixp;
int nsuffixes = 0;
char buf[256], *linep, *p; char buf[256], *linep, *p;
#ifdef WITH_LIBICU
UIDNA *idna;
UErrorCode status = 0;
#endif
if (!fp) if (!fp)
return NULL; return NULL;
@ -476,6 +553,10 @@ psl_ctx_t *psl_load_fp(FILE *fp)
if (!(psl = calloc(1, sizeof(psl_ctx_t)))) if (!(psl = calloc(1, sizeof(psl_ctx_t))))
return NULL; return NULL;
#ifdef WITH_LIBICU
idna = uidna_openUTS46(UIDNA_USE_STD3_RULES, &status);
#endif
/* /*
* as of 02.11.2012, the list at http://publicsuffix.org/list/ contains ~6000 rules and 40 exceptions. * as of 02.11.2012, the list at http://publicsuffix.org/list/ contains ~6000 rules and 40 exceptions.
* as of 19.02.2014, the list at http://publicsuffix.org/list/ contains ~6500 rules and 19 exceptions. * as of 19.02.2014, the list at http://publicsuffix.org/list/ contains ~6500 rules and 19 exceptions.
@ -496,26 +577,33 @@ psl_ctx_t *psl_load_fp(FILE *fp)
if (*p == '!') { if (*p == '!') {
/* add to exceptions */ /* add to exceptions */
if (_suffix_init(&suffix, p + 1, linep - p - 1) == 0) if (_suffix_init(&suffix, p + 1, linep - p - 1) == 0) {
suffixp = _vector_get(psl->suffix_exceptions, _vector_add(psl->suffix_exceptions, &suffix)); suffixp = _vector_get(psl->suffix_exceptions, _vector_add(psl->suffix_exceptions, &suffix));
else
suffixp = NULL;
} else {
if (_suffix_init(&suffix, p, linep - p) == 0)
suffixp = _vector_get(psl->suffixes, _vector_add(psl->suffixes, &suffix));
else
suffixp = NULL;
}
if (suffixp)
suffixp->label = suffixp->label_buf; /* set label to changed address */ suffixp->label = suffixp->label_buf; /* set label to changed address */
#ifdef WITH_LIBICU
nsuffixes++;; _add_punycode_if_needed(idna, psl->suffix_exceptions, suffixp);
#endif
}
} else {
/* add to suffixes */
if (_suffix_init(&suffix, p, linep - p) == 0) {
suffixp = _vector_get(psl->suffixes, _vector_add(psl->suffixes, &suffix));
suffixp->label = suffixp->label_buf; /* set label to changed address */
#ifdef WITH_LIBICU
_add_punycode_if_needed(idna, psl->suffixes, suffixp);
#endif
}
}
} }
_vector_sort(psl->suffix_exceptions); _vector_sort(psl->suffix_exceptions);
_vector_sort(psl->suffixes); _vector_sort(psl->suffixes);
#ifdef WITH_LIBICU
if (idna)
uidna_close(idna);
#endif
return psl; return psl;
} }
@ -685,7 +773,13 @@ const char *psl_builtin_filename(void)
**/ **/
const char *psl_get_version (void) const char *psl_get_version (void)
{ {
return PACKAGE_VERSION; return PACKAGE_VERSION
#ifdef WITH_LIBICU
" (+libicu/" U_ICU_VERSION ")"
#else
" (limited IDNA support)"
#endif
;
} }
/** /**
@ -697,6 +791,9 @@ const char *psl_get_version (void)
* This helper function checks whether @cookie_domain is an acceptable cookie domain value for the request * This helper function checks whether @cookie_domain is an acceptable cookie domain value for the request
* @hostname. * @hostname.
* *
* For international domain names both, @hostname and @cookie_domain, have to be either in lowercase UTF-8
* or in ASCII form (punycode). Other encodings or mixing UTF-8 and punycode result in unexpected behavior.
*
* Examples: * Examples:
* 1. Cookie domain 'example.com' would be acceptable for hostname 'www.example.com', * 1. Cookie domain 'example.com' would be acceptable for hostname 'www.example.com',
* but '.com' or 'com' would NOT be acceptable since 'com' is a public suffix. * but '.com' or 'com' would NOT be acceptable since 'com' is a public suffix.
@ -741,3 +838,100 @@ int psl_is_cookie_domain_acceptable(const psl_ctx_t *psl, const char *hostname,
return 0; return 0;
} }
/**
* psl_str_to_utf8lower:
* @str: string to convert
* @encoding: charset encoding of @str, e.g. 'iso-8859-1' or %NULL
* @locale: locale of @str for to lowercase conversion, e.g. 'de' or %NULL
* @lower: return value containing the converted string
*
* This helper function converts a string to lowercase UTF-8 representation.
* Lowercase UTF-8 is needed as input to the domain checking functions.
*
* @lower is %NULL on error.
* The return value 'lower' must be freed after usage.
*
* Returns: psl_error_t value.
* PSL_SUCCESS: Success
* PSL_ERR_INVALID_ARG: @str is a %NULL value.
* PSL_ERR_CONVERTER: Failed to open the unicode converter with name @encoding
* PSL_ERR_TO_UTF16: Failed to convert @str to unicode
* PSL_ERR_TO_LOWER: Failed to convert unicode to lowercase
* PSL_ERR_TO_UTF8: Failed to convert unicode to UTF-8
*
* Since: 0.4
*/
psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const char *locale, char **lower)
{
int ret = PSL_ERR_INVALID_ARG;
if (lower)
*lower = NULL;
if (!str)
return PSL_ERR_INVALID_ARG;
/* shortcut to avoid costly conversion */
if (_str_is_ascii(str)) {
if (lower) {
char *p;
*lower = strdup(str);
/* convert ASCII string to lowercase */
for (p = *lower; *p; p++)
if (isupper(*p))
*p = tolower(*p);
}
return PSL_SUCCESS;
}
#ifdef WITH_LIBICU
do {
size_t str_length = strlen(str);
UErrorCode status = 0;
UChar *utf16_dst, *utf16_lower;
int32_t utf16_dst_length;
char *utf8_lower;
UConverter *uconv;
/* C89 allocation */
utf16_dst = alloca(sizeof(UChar) * (str_length * 2 + 1));
utf16_lower = alloca(sizeof(UChar) * (str_length * 2 + 1));
utf8_lower = alloca(str_length * 2 + 1);
uconv = ucnv_open(encoding, &status);
if (U_SUCCESS(status)) {
utf16_dst_length = ucnv_toUChars(uconv, utf16_dst, str_length * 2 + 1, str, str_length, &status);
ucnv_close(uconv);
if (U_SUCCESS(status)) {
int32_t utf16_lower_length = u_strToLower(utf16_lower, str_length * 2 + 1, utf16_dst, utf16_dst_length, locale, &status);
if (U_SUCCESS(status)) {
u_strToUTF8(utf8_lower, str_length * 8 + 1, NULL, utf16_lower, utf16_lower_length, &status);
if (U_SUCCESS(status)) {
if (lower)
*lower = strdup(utf8_lower);
ret = PSL_SUCCESS;
} else {
ret = PSL_ERR_TO_UTF8;
/* fprintf(stderr, "Failed to convert UTF-16 to UTF-8 (status %d)\n", status); */
}
} else {
ret = PSL_ERR_TO_LOWER;
/* fprintf(stderr, "Failed to convert UTF-16 to lowercase (status %d)\n", status); */
}
} else {
ret = PSL_ERR_TO_UTF16;
/* fprintf(stderr, "Failed to convert string to UTF-16 (status %d)\n", status); */
}
} else {
ret = PSL_ERR_CONVERTER;
/* fprintf(stderr, "Failed to open converter for '%s' (status %d)\n", encoding, status); */
}
} while (0);
#endif
return ret;
}

View File

@ -39,235 +39,14 @@
#include <ctype.h> #include <ctype.h>
#include <sys/stat.h> #include <sys/stat.h>
/*
#ifdef WITH_LIBIDN2
# include <idn2.h>
#endif
*/
#ifdef WITH_LIBICU
# include <unicode/uversion.h>
# include <unicode/ustring.h>
# include <unicode/uidna.h>
#endif
#ifdef WITH_BUILTIN #ifdef WITH_BUILTIN
#include <libpsl.h> #include <libpsl.h>
typedef struct { /* here we include the library source code to have access to internal functions and data structures */
char #define _LIBPSL_INCLUDED_BY_PSL2C
label_buf[48]; # include "psl.c"
const char * #undef _LIBPSL_INCLUDED_BY_PSL2C
label;
unsigned short
length;
unsigned char
nlabels, /* number of labels */
wildcard; /* this is a wildcard rule (e.g. *.sapporo.jp) */
} _psl_entry_t;
/* stripped down version libmget vector routines */
typedef struct {
int
(*cmp)(const _psl_entry_t *, const _psl_entry_t *); /* comparison function */
_psl_entry_t
**entry; /* pointer to array of pointers to elements */
int
max, /* allocated elements */
cur; /* number of elements in use */
} _psl_vector_t;
struct _psl_ctx_st {
_psl_vector_t
*suffixes,
*suffix_exceptions;
};
static _psl_vector_t *_vector_alloc(int max, int (*cmp)(const _psl_entry_t *, const _psl_entry_t *))
{
_psl_vector_t *v;
if (!(v = calloc(1, sizeof(_psl_vector_t))))
return NULL;
if (!(v->entry = malloc(max * sizeof(_psl_entry_t *)))) {
free(v);
return NULL;
}
v->max = max;
v->cmp = cmp;
return v;
}
static void _vector_free(_psl_vector_t **v)
{
if (v && *v) {
if ((*v)->entry) {
int it;
for (it = 0; it < (*v)->cur; it++)
free((*v)->entry[it]);
free((*v)->entry);
}
free(*v);
}
}
static _psl_entry_t *_vector_get(const _psl_vector_t *v, int pos)
{
if (pos < 0 || !v || pos >= v->cur) return NULL;
return v->entry[pos];
}
static int _vector_add(_psl_vector_t *v, const _psl_entry_t *elem)
{
if (v) {
void *elemp;
elemp = malloc(sizeof(_psl_entry_t));
memcpy(elemp, elem, sizeof(_psl_entry_t));
if (v->max == v->cur)
v->entry = realloc(v->entry, (v->max *= 2) * sizeof(_psl_entry_t *));
v->entry[v->cur++] = elemp;
return v->cur - 1;
}
return -1;
}
static int _compare(const void *p1, const void *p2, void *v)
{
return ((_psl_vector_t *)v)->cmp(*((_psl_entry_t **)p1), *((_psl_entry_t **)p2));
}
static void _vector_sort(_psl_vector_t *v)
{
if (v && v->cmp)
qsort_r(v->entry, v->cur, sizeof(_psl_vector_t *), _compare, v);
}
/* by this kind of sorting, we can easily see if a domain matches or not (match = supercookie !) */
static int _suffix_compare(const _psl_entry_t *s1, const _psl_entry_t *s2)
{
int n;
if ((n = s2->nlabels - s1->nlabels))
return n; /* most labels first */
if ((n = s1->length - s2->length))
return n; /* shorter rules first */
return strcmp(s1->label, s2->label);
}
static void _suffix_init(_psl_entry_t *suffix, const char *rule, size_t length)
{
const char *src;
char *dst;
suffix->label = suffix->label_buf;
if (length >= sizeof(suffix->label_buf) - 1) {
suffix->nlabels = 0;
fprintf(stderr, "Suffix rule too long (%d, ignored): %s\n", (int) length, rule);
return;
}
if (*rule == '*') {
if (*++rule != '.') {
suffix->nlabels = 0;
fprintf(stderr, "Unsupported kind of rule (ignored): %s\n", rule);
return;
}
rule++;
suffix->wildcard = 1;
suffix->length = (unsigned char)length - 2;
} else {
suffix->wildcard = 0;
suffix->length = (unsigned char)length;
}
suffix->nlabels = 1;
for (dst = suffix->label_buf, src = rule; *src;) {
if (*src == '.')
suffix->nlabels++;
*dst++ = tolower(*src++);
}
*dst = 0;
}
psl_ctx_t *psl_load_file(const char *fname)
{
FILE *fp;
psl_ctx_t *psl = NULL;
if ((fp = fopen(fname, "r"))) {
psl = psl_load_fp(fp);
fclose(fp);
}
return psl;
}
psl_ctx_t *psl_load_fp(FILE *fp)
{
psl_ctx_t *psl;
_psl_entry_t suffix, *suffixp;
int nsuffixes = 0;
char buf[256], *linep, *p;
if (!fp)
return NULL;
if (!(psl = calloc(1, sizeof(psl_ctx_t))))
return NULL;
/*
* as of 02.11.2012, the list at http://publicsuffix.org/list/ contains ~6000 rules and 40 exceptions.
* as of 19.02.2014, the list at http://publicsuffix.org/list/ contains ~6500 rules and 19 exceptions.
*/
psl->suffixes = _vector_alloc(8*1024, _suffix_compare);
psl->suffix_exceptions = _vector_alloc(64, _suffix_compare);
while ((linep = fgets(buf, sizeof(buf), fp))) {
while (isspace(*linep)) linep++; /* ignore leading whitespace */
if (!*linep) continue; /* skip empty lines */
if (*linep == '/' && linep[1] == '/')
continue; /* skip comments */
/* parse suffix rule */
for (p = linep; *linep && !isspace(*linep);) linep++;
*linep = 0;
if (*p == '!') {
/* add to exceptions */
_suffix_init(&suffix, p + 1, linep - p - 1);
suffixp = _vector_get(psl->suffix_exceptions, _vector_add(psl->suffix_exceptions, &suffix));
} else {
_suffix_init(&suffix, p, linep - p);
suffixp = _vector_get(psl->suffixes, _vector_add(psl->suffixes, &suffix));
}
if (suffixp)
suffixp->label = suffixp->label_buf; /* set label to changed address */
nsuffixes++;;
}
_vector_sort(psl->suffix_exceptions);
_vector_sort(psl->suffixes);
return psl;
}
static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char *varname) static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char *varname)
{ {
@ -283,8 +62,8 @@ static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char *
fprintf(fpout, "/* automatically generated by psl2c (punycode generated with libicu/%s) */\n", version); fprintf(fpout, "/* automatically generated by psl2c (punycode generated with libicu/%s) */\n", version);
} while (0); } while (0);
#else #else
fprintf(fpout, "/* automatically generated by psl2c (punycode generated with idn2) */\n"); fprintf(fpout, "/* automatically generated by psl2c (without punycode support) */\n");
#endif #endif /* WITH_LIBICU */
fprintf(fpout, "static _psl_entry_t %s[] = {\n", varname); fprintf(fpout, "static _psl_entry_t %s[] = {\n", varname);
@ -298,15 +77,7 @@ static void _print_psl_entries(FILE *fpout, const _psl_vector_t *v, const char *
fprintf(fpout, "};\n"); fprintf(fpout, "};\n");
} }
void psl_free(psl_ctx_t *psl) #ifndef WITH_LIBICU
{
if (psl) {
_vector_free(&psl->suffixes);
_vector_free(&psl->suffix_exceptions);
free(psl);
}
}
static int _str_needs_encoding(const char *s) static int _str_needs_encoding(const char *s)
{ {
while (*s > 0) s++; while (*s > 0) s++;
@ -326,60 +97,6 @@ static void _add_punycode_if_needed(_psl_vector_t *v)
_psl_entry_t suffix, *suffixp; _psl_entry_t suffix, *suffixp;
char lookupname[64] = ""; char lookupname[64] = "";
/* the following lines will have GPL3+ license issues */
/* char *asc = NULL;
int rc;
if ((rc = idn2_lookup_u8((uint8_t *)e->label_buf, (uint8_t **)&asc, 0)) == IDN2_OK) {
// fprintf(stderr, "idn2 '%s' -> '%s'\n", e->label_buf, asc);
_suffix_init(&suffix, asc, strlen(asc));
suffix.wildcard = e->wildcard;
suffixp = _vector_get(v, _vector_add(v, &suffix));
suffixp->label = suffixp->e_label_buf; // set label to changed address
} else
fprintf(stderr, "toASCII(%s) failed (%d): %s\n", e->label_buf, rc, idn2_strerror(rc));
*/
#ifdef WITH_LIBICU
UIDNA *idna;
UErrorCode status = 0;
/* IDNA2003 punycode conversion */
/* destLen = uidna_toASCII(e->label_buf, (int32_t) strlen(e->label_buf), lookupname, (int32_t) sizeof(lookupname),
UIDNA_DEFAULT, NULL, &status);
*/
/* IDNA2008 UTS#46 punycode conversion */
if ((idna = uidna_openUTS46(UIDNA_USE_STD3_RULES, &status))) {
UChar utf16_dst[64], utf16_src[64];
int32_t utf16_src_length;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
u_strFromUTF8(utf16_src, sizeof(utf16_src)/sizeof(utf16_src[0]), &utf16_src_length, e->label_buf, (int32_t) strlen(e->label_buf), &status);
if (U_SUCCESS(status)) {
int32_t dst_length = uidna_nameToASCII(idna, utf16_src, utf16_src_length, utf16_dst, sizeof(utf16_dst)/sizeof(utf16_dst[0]), &info, &status);
if (U_SUCCESS(status)) {
u_strToUTF8(lookupname, (int32_t) sizeof(lookupname), NULL, utf16_dst, dst_length, &status);
if (U_SUCCESS(status)) {
if (strcmp(e->label_buf, lookupname)) {
/* fprintf(stderr, "libicu '%s' -> '%s'\n", e->label_buf, lookupname); */
_suffix_init(&suffix, lookupname, strlen(lookupname));
suffix.wildcard = e->wildcard;
suffixp = _vector_get(v, _vector_add(v, &suffix));
suffixp->label = suffixp->label_buf; /* set label to changed address */
} /* else ignore */
} else
fprintf(stderr, "Failed to convert UTF-16 to UTF-8 (status %d)\n", status);
} else
fprintf(stderr, "Failed to convert to ASCII (status %d)\n", status);
} else
fprintf(stderr, "Failed to convert UTF-8 to UTF-16 (status %d)\n", status);
uidna_close(idna);
} else
fprintf(stderr, "Failed to get UTS46 IDNA handle\n");
#else
/* this is much slower than the libidn2 API but should have no license issues */ /* this is much slower than the libidn2 API but should have no license issues */
FILE *pp; FILE *pp;
char cmd[16 + sizeof(e->label_buf)]; char cmd[16 + sizeof(e->label_buf)];
@ -395,12 +112,13 @@ static void _add_punycode_if_needed(_psl_vector_t *v)
pclose(pp); pclose(pp);
} else } else
fprintf(stderr, "Failed to call popen(%s, \"r\")\n", cmd); fprintf(stderr, "Failed to call popen(%s, \"r\")\n", cmd);
#endif
} }
} }
_vector_sort(v); _vector_sort(v);
} }
#endif /* ! WITH_LIBICU */
#endif /* WITH_BUILTIN */ #endif /* WITH_BUILTIN */
int main(int argc, const char **argv) int main(int argc, const char **argv)
@ -413,7 +131,7 @@ int main(int argc, const char **argv)
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: psl2c <infile> <outfile>\n"); fprintf(stderr, "Usage: psl2c <infile> <outfile>\n");
fprintf(stderr, " <infile> is the 'effective_tld_names.dat' (aka Public Suffix List)\n"); fprintf(stderr, " <infile> is the 'effective_tld_names.dat' (aka Public Suffix List), lowercase UTF-8 encoded\n");
fprintf(stderr, " <outfile> is the the C filename to be generated from <infile>\n"); fprintf(stderr, " <outfile> is the the C filename to be generated from <infile>\n");
return 1; return 1;
} }
@ -428,8 +146,12 @@ int main(int argc, const char **argv)
size_t cmdsize = 16 + strlen(argv[1]); size_t cmdsize = 16 + strlen(argv[1]);
char *cmd = alloca(cmdsize), checksum[64] = ""; char *cmd = alloca(cmdsize), checksum[64] = "";
#ifndef WITH_LIBICU
/* If libicu is not configured, we still need to have punycode in our built-in data. */
/* Else the test suite fails. */
_add_punycode_if_needed(psl->suffixes); _add_punycode_if_needed(psl->suffixes);
_add_punycode_if_needed(psl->suffix_exceptions); _add_punycode_if_needed(psl->suffix_exceptions);
#endif
_print_psl_entries(fpout, psl->suffixes, "suffixes"); _print_psl_entries(fpout, psl->suffixes, "suffixes");
_print_psl_entries(fpout, psl->suffix_exceptions, "suffix_exceptions"); _print_psl_entries(fpout, psl->suffix_exceptions, "suffix_exceptions");
@ -458,8 +180,8 @@ int main(int argc, const char **argv)
psl_free(psl); psl_free(psl);
#else #else
if ((fpout = fopen(argv[2], "w"))) { if ((fpout = fopen(argv[2], "w"))) {
fprintf(fpout, "static _psl_entry_t suffixes[0];\n"); fprintf(fpout, "static _psl_entry_t suffixes[1];\n");
fprintf(fpout, "static _psl_entry_t suffix_exceptions[0];\n"); fprintf(fpout, "static _psl_entry_t suffix_exceptions[1];\n");
fprintf(fpout, "static time_t _psl_file_time;\n"); fprintf(fpout, "static time_t _psl_file_time;\n");
fprintf(fpout, "static time_t _psl_compile_time;\n"); fprintf(fpout, "static time_t _psl_compile_time;\n");
fprintf(fpout, "static const char _psl_sha1_checksum[] = \"\";\n"); fprintf(fpout, "static const char _psl_sha1_checksum[] = \"\";\n");

View File

@ -47,8 +47,8 @@ static int
static void test_psl(void) static void test_psl(void)
{ {
/* punycode generation: idn 商标 */ /* punycode generation: idn ?? */
/* octal code generation: echo -n "商标" | od -b */ /* octal code generation: echo -n "??" | od -b */
static const struct test_data { static const struct test_data {
const char const char
*domain; *domain;
@ -65,7 +65,7 @@ static void test_psl(void)
{ "abc.www.ck", 0 }, { "abc.www.ck", 0 },
{ "xxx.ck", 1 }, { "xxx.ck", 1 },
{ "www.xxx.ck", 0 }, { "www.xxx.ck", 0 },
{ "\345\225\206\346\240\207", 1 }, /* xn--czr694b oder 商标 */ { "\345\225\206\346\240\207", 1 }, /* xn--czr694b oder ?? */
{ "www.\345\225\206\346\240\207", 0 }, { "www.\345\225\206\346\240\207", 0 },
{ "xn--czr694b", 1 }, { "xn--czr694b", 1 },
{ "www.xn--czr694b", 0 }, { "www.xn--czr694b", 0 },

View File

@ -47,8 +47,8 @@ static int
static void test_psl(void) static void test_psl(void)
{ {
/* punycode generation: idn 商标 */ /* punycode generation: idn ?? */
/* octal code generation: echo -n "商标" | od -b */ /* octal code generation: echo -n "??" | od -b */
static const struct test_data { static const struct test_data {
const char const char
*domain; *domain;
@ -65,7 +65,7 @@ static void test_psl(void)
{ "abc.www.ck", 0 }, { "abc.www.ck", 0 },
{ "xxx.ck", 1 }, { "xxx.ck", 1 },
{ "www.xxx.ck", 0 }, { "www.xxx.ck", 0 },
{ "\345\225\206\346\240\207", 1 }, /* xn--czr694b oder 商标 */ { "\345\225\206\346\240\207", 1 }, /* xn--czr694b or ?? */
{ "www.\345\225\206\346\240\207", 0 }, { "www.\345\225\206\346\240\207", 0 },
/* some special test follow ('name' and 'forgot.his.name' are public, but e.g. his.name is not) */ /* some special test follow ('name' and 'forgot.his.name' are public, but e.g. his.name is not) */
{ "name", 1 }, { "name", 1 },

View File

@ -38,6 +38,11 @@
#include <ctype.h> #include <ctype.h>
#include <alloca.h> #include <alloca.h>
#ifdef WITH_LIBICU
# include <unicode/uversion.h>
# include <unicode/ustring.h>
#endif
#include <libpsl.h> #include <libpsl.h>
static int static int
@ -47,32 +52,11 @@ static int
static void test(const psl_ctx_t *psl, const char *domain, const char *expected_result) static void test(const psl_ctx_t *psl, const char *domain, const char *expected_result)
{ {
const char *result; const char *result;
char lookupname[128]; char *lower;
/* check if there might be some utf-8 characters */ /* our test data is fixed to UTF-8 (english), so provide it here */
if (domain) { if (psl_str_to_utf8lower(domain, "utf-8", "en", &lower) == PSL_SUCCESS)
int utf8; domain = lower;
const char *p;
for (p = domain, utf8 = 0; *p && !utf8; p++)
if (*p < 0)
utf8 = 1;
/* if we found utf-8, make sure to convert domain correctly to lowercase */
/* does it work, if we are not in a utf-8 env ? */
if (utf8) {
FILE *pp;
size_t cmdsize = 48 + strlen(domain);
char *cmd = alloca(cmdsize);
snprintf(cmd, cmdsize, "echo -n '%s' | sed -e 's/./\\L\\0/g'", domain);
if ((pp = popen(cmd, "r"))) {
if (fscanf(pp, "%127s", lookupname) >= 1)
domain = lookupname;
pclose(pp);
}
}
}
result = psl_registrable_domain(psl, domain); result = psl_registrable_domain(psl, domain);
@ -83,13 +67,15 @@ static void test(const psl_ctx_t *psl, const char *domain, const char *expected_
printf("psl_registrable_domain(%s)=%s (expected %s)\n", printf("psl_registrable_domain(%s)=%s (expected %s)\n",
domain, result ? result : "NULL", expected_result ? expected_result : "NULL"); domain, result ? result : "NULL", expected_result ? expected_result : "NULL");
} }
free(lower);
} }
static void test_psl(void) static void test_psl(void)
{ {
FILE *fp; FILE *fp;
const psl_ctx_t *psl; const psl_ctx_t *psl;
char buf[256], domain[128], expected_regdom[128], *p; char buf[256], domain[128], expected_regdom[128];
psl = psl_builtin(); psl = psl_builtin();
@ -105,7 +91,9 @@ static void test_psl(void)
test(NULL, "com", NULL); test(NULL, "com", NULL);
/* Norwegian with uppercase oe */ /* Norwegian with uppercase oe */
#ifdef WITH_LIBICU
test(psl, "www.\303\230yer.no", "www.\303\270yer.no"); test(psl, "www.\303\230yer.no", "www.\303\270yer.no");
#endif
/* Norwegian with lowercase oe */ /* Norwegian with lowercase oe */
test(psl, "www.\303\270yer.no", "www.\303\270yer.no"); test(psl, "www.\303\270yer.no", "www.\303\270yer.no");
@ -126,11 +114,6 @@ static void test_psl(void)
continue; continue;
} }
/* we have to lowercase the domain - the PSL API just takes lowercase */
for (p = domain; *p; p++)
if (*p > 0 && isupper(*p))
*p = tolower(*p);
if (!strcmp(expected_regdom, "null")) if (!strcmp(expected_regdom, "null"))
test(psl, domain, NULL); test(psl, domain, NULL);
else else

View File

@ -32,8 +32,16 @@
# include <config.h> # include <config.h>
#endif #endif
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#ifdef WITH_LIBICU
# include <unicode/uloc.h>
# include <unicode/ucnv.h>
#endif
#include <libpsl.h> #include <libpsl.h>
static void usage(int err, FILE* f) static void usage(int err, FILE* f)
@ -71,6 +79,10 @@ int main(int argc, const char *const *argv)
const char *const *arg, *psl_file = NULL, *cookie_domain = NULL; const char *const *arg, *psl_file = NULL, *cookie_domain = NULL;
psl_ctx_t *psl = (psl_ctx_t *) psl_builtin(); psl_ctx_t *psl = (psl_ctx_t *) psl_builtin();
/* set current locale according to the environment variables */
#include <locale.h>
setlocale(LC_ALL, "");
for (arg = argv + 1; arg < argv + argc; arg++) { for (arg = argv + 1; arg < argv + argc; arg++) {
if (!strncmp(*arg, "--", 2)) { if (!strncmp(*arg, "--", 2)) {
if (!strcmp(*arg, "--is-public-suffix")) if (!strcmp(*arg, "--is-public-suffix"))
@ -135,8 +147,41 @@ int main(int argc, const char *const *argv)
exit(2); exit(2);
} }
if (arg >= argv + argc) { if (arg >= argv + argc) {
fprintf(stderr, "No domains given - aborting\n"); char buf[256], *domain, *lower;
exit(3); size_t len;
psl_error_t rc;
/* read URLs from STDIN */
while (fgets(buf, sizeof(buf), stdin)) {
for (domain = buf; isspace(*domain); domain++); /* skip leading spaces */
if (*domain == '#' || !*domain) continue; /* skip empty lines and comments */
for (len = strlen(domain); len && isspace(domain[len - 1]); len--); /* skip trailing spaces */
domain[len] = 0;
if ((rc = psl_str_to_utf8lower(domain, NULL, NULL, &lower)) != PSL_SUCCESS)
fprintf(stderr, "%s: Failed to convert to lowercase UTF-8 (%d)\n", domain, rc);
else if (mode == 1)
printf("%s: %d (%s)\n", domain, psl_is_public_suffix(psl, lower), lower);
else if (mode == 2)
printf("%s: %s\n", domain, psl_unregistrable_domain(psl, lower));
else if (mode == 3)
printf("%s: %s\n", domain, psl_registrable_domain(psl, lower));
else if (mode == 4) {
char *cookie_domain_lower;
if ((rc = psl_str_to_utf8lower(domain, NULL, NULL, &cookie_domain_lower)) != PSL_SUCCESS)
fprintf(stderr, "%s: Failed to convert cookie domain '%s' to lowercase UTF-8 (%d)\n", domain, cookie_domain, rc);
else
printf("%s: %d\n", domain, psl_is_cookie_domain_acceptable(psl, lower, cookie_domain));
free(cookie_domain_lower);
}
free(lower);
}
psl_free(psl);
exit(0);
} }
} }
@ -172,6 +217,11 @@ int main(int argc, const char *const *argv)
printf("builtin compile time: %ld (%s)\n", psl_builtin_compile_time(), time2str(psl_builtin_compile_time())); printf("builtin compile time: %ld (%s)\n", psl_builtin_compile_time(), time2str(psl_builtin_compile_time()));
printf("builtin file time: %ld (%s)\n", psl_builtin_file_time(), time2str(psl_builtin_file_time())); printf("builtin file time: %ld (%s)\n", psl_builtin_file_time(), time2str(psl_builtin_file_time()));
printf("builtin SHA1 file hash: %s\n", psl_builtin_sha1sum()); printf("builtin SHA1 file hash: %s\n", psl_builtin_sha1sum());
#ifdef WITH_LIBICU
printf("uloc_getDefault=%s\n", uloc_getDefault());
printf("ucnv_getDefaultName=%s\n", ucnv_getDefaultName());
#endif
} else } else
printf("No builtin PSL data available\n"); printf("No builtin PSL data available\n");
} }