Skip to content

Commit

Permalink
Release V0.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
rockdaboot committed May 26, 2014
2 parents 32b2232 + 2ce72b5 commit d51a73d
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 145 deletions.
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Copyright (C) 2014 Tim Ruehsen

26.05.2014 Release V0.2.2
* changed code to C89
* added a few test cases
* build static library by default

25.04.2014 Hotfix release V0.2.1
* Updated to the latest Publix Suffix List

Expand Down
10 changes: 6 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

AC_INIT([libpsl], [0.2.1], [[email protected]], [libpsl], [http://github.com/rockdaboot/libpsl])
AC_INIT([libpsl], [0.2.2], [[email protected]], [libpsl], [http://github.com/rockdaboot/libpsl])
AC_PREREQ([2.59])
AM_INIT_AUTOMAKE([1.10 -Wall no-define])

Expand All @@ -8,7 +8,9 @@ AM_INIT_AUTOMAKE([1.10 -Wall no-define])
# the library.
AC_CONFIG_HEADERS([config.h])
AC_PROG_CXX
LT_INIT([disable-static])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
#LT_INIT([disable-static])
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

Expand Down Expand Up @@ -61,8 +63,8 @@ AS_IF([ test "$enable_man" != no ], [
# 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.
# 6. If any interfaces have been removed or changed since the last public release, then set age to 0.
AC_SUBST([LIBPSL_SO_VERSION], [0:2:0])
AC_SUBST([LIBPSL_API_VERSION], [0.2.1])
AC_SUBST([LIBPSL_SO_VERSION], [0:3:0])
AC_SUBST([LIBPSL_API_VERSION], [0.2.2])

# Check for idn2
AC_CHECK_PROG(HAVE_IDN2, idn2, yes, AC_MSG_ERROR(Cannot find required tool 'idn2'.))
Expand Down
24 changes: 14 additions & 10 deletions include/libpsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,42 +41,46 @@ extern "C" {

typedef struct _psl_ctx_st psl_ctx_t;

/* frees PSL context */
void
psl_free(psl_ctx_t *psl);
/* loads PSL data from file */
psl_ctx_t *
psl_load_file(const char *fname);
/* loads PSL data from FILE pointer */
psl_ctx_t *
psl_load_fp(FILE *fp);
/* retrieves builtin PSL data */
const psl_ctx_t *
psl_builtin(void);
// checks wether domain is a public suffix or not
/* checks wether domain is a public suffix or not */
int
psl_is_public_suffix(const psl_ctx_t *psl, const char *domain);
// checks wether cookie_domain is acceptable for domain or not
/* checks wether cookie_domain is acceptable for domain or not */
int
psl_is_cookie_domain_acceptable(const psl_ctx_t *psl, const char *hostname, const char *cookie_domain);
// returns the longest unregistrable domain within 'domain' or NULL if none found
/* returns the longest unregistrable domain within 'domain' or NULL if none found */
const char *
psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain);
// 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 *
psl_registrable_domain(const psl_ctx_t *psl, const char *domain);
// does not include exceptions
/* does not include exceptions */
int
psl_suffix_count(const psl_ctx_t *psl);
// just counts exceptions
/* just counts exceptions */
int
psl_suffix_exception_count(const psl_ctx_t *psl);
// returns compilation time
/* returns compilation time */
time_t
psl_builtin_compile_time(void);
// returns mtime of PSL source file
/* returns mtime of PSL source file */
time_t
psl_builtin_file_time(void);
// returns SHA1 checksum (hex-encoded, lowercase) of PSL source file
/* returns SHA1 checksum (hex-encoded, lowercase) of PSL source file */
const char *
psl_builtin_sha1sum(void);
// returns file name of PSL source file
/* returns file name of PSL source file */
const char *
psl_builtin_filename(void);

Expand Down
93 changes: 49 additions & 44 deletions src/psl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*
*/

// need _GNU_SOURCE for qsort_r()
/* need _GNU_SOURCE for qsort_r() */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
Expand Down Expand Up @@ -73,19 +73,19 @@ typedef struct {
unsigned short
length;
unsigned char
nlabels, // number of labels
wildcard; // this is a wildcard rule (e.g. *.sapporo.jp)
nlabels, /* number of labels */
wildcard; /* this is a wildcard rule (e.g. *.sapporo.jp) */
} _psl_entry_t;

// stripped down version libmget vector routines
/* stripped down version libmget vector routines */
typedef struct {
int
(*cmp)(const _psl_entry_t *, const _psl_entry_t *); // comparison function
(*cmp)(const _psl_entry_t *, const _psl_entry_t *); /* comparison function */
_psl_entry_t
**entry; // pointer to array of pointers to elements
**entry; /* pointer to array of pointers to elements */
int
max, // allocated elements
cur; // number of elements in use
max, /* allocated elements */
cur; /* number of elements in use */
} _psl_vector_t;

struct _psl_ctx_st {
Expand All @@ -94,10 +94,10 @@ struct _psl_ctx_st {
*suffix_exceptions;
};

// include the PSL data compiled by 'psl2c'
/* include the PSL data compiled by 'psl2c' */
#include "suffixes.c"

// 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
_builtin_psl;

Expand Down Expand Up @@ -140,14 +140,14 @@ static _psl_entry_t *_vector_get(const _psl_vector_t *v, int pos)
return v->entry[pos];
}

// the entries must be sorted by
/* the entries must be sorted by */
static int _vector_find(const _psl_vector_t *v, const _psl_entry_t *elem)
{
if (v) {
int l, r, m;
int res;

// binary search for element (exact match)
/* binary search for element (exact match) */
for (l = 0, r = v->cur - 1; l <= r;) {
m = (l + r) / 2;
if ((res = v->cmp(elem, v->entry[m])) > 0) l = m + 1;
Expand All @@ -156,7 +156,7 @@ static int _vector_find(const _psl_vector_t *v, const _psl_entry_t *elem)
}
}

return -1; // not found
return -1; /* not found */
}

static int _vector_add(_psl_vector_t *v, const _psl_entry_t *elem)
Expand Down Expand Up @@ -188,22 +188,21 @@ static void _vector_sort(_psl_vector_t *v)
qsort_r(v->entry, v->cur, sizeof(_psl_vector_t *), _compare, v);
}

static inline int _vector_size(_psl_vector_t *v)
static int _vector_size(_psl_vector_t *v)
{
return v ? v->cur : 0;
}

// by this kind of sorting, we can easily see if a domain matches or not

/* by this kind of sorting, we can easily see if a domain matches or not */
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
return n; /* most labels first */

if ((n = s1->length - s2->length))
return n; // shorter rules first
return n; /* shorter rules first */

return strcmp(s1->label, s2->label ? s2->label : s2->label_buf);
}
Expand All @@ -217,14 +216,14 @@ static int _suffix_init(_psl_entry_t *suffix, const char *rule, size_t length)

if (length >= sizeof(suffix->label_buf) - 1) {
suffix->nlabels = 0;
// fprintf(stderr, _("Suffix rule too long (%zd, ignored): %s\n"), length, rule);
/* fprintf(stderr, _("Suffix rule too long (%zd, ignored): %s\n"), length, rule); */
return -1;
}

if (*rule == '*') {
if (*++rule != '.') {
suffix->nlabels = 0;
// fprintf(stderr, _("Unsupported kind of rule (ignored): %s\n"), rule);
/* fprintf(stderr, _("Unsupported kind of rule (ignored): %s\n"), rule); */
return -2;
}
rule++;
Expand Down Expand Up @@ -273,7 +272,7 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
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.length = strlen(suffix.label);
suffix.wildcard = 0;
Expand All @@ -283,7 +282,7 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
if (*p == '.')
suffix.nlabels++;

// if domain has enough labels, it is public
/* if domain has enough labels, it is public */
if (psl == &_builtin_psl)
rule = &suffixes[0];
else
Expand All @@ -298,10 +297,10 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
rule = _vector_get(psl->suffixes, _vector_find(psl->suffixes, &suffix));

if (rule) {
// definitely a match, no matter if the found rule is a wildcard or not
/* definitely a match, no matter if the found rule is a wildcard or not */
return 1;
} else if (suffix.nlabels == 1) {
// unknown TLD, this is the prevailing '*' match
/* unknown TLD, this is the prevailing '*' match */
return 1;
}

Expand All @@ -320,17 +319,17 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)

if (rule) {
if (rule->wildcard) {
// now that we matched a wildcard, we have to check for an exception
/* now that we matched a wildcard, we have to check for an exception */
suffix.label = label_bak;
suffix.length = length_bak;
suffix.nlabels++;

if (psl == &_builtin_psl) {
if (bsearch(&suffix, suffix_exceptions, countof(suffix_exceptions), sizeof(suffix_exceptions[0]), (int(*)(const void *, const void *))_suffix_compare))
return 0; // found an exception, so 'domain' is not a public suffix
return 0; /* found an exception, so 'domain' is not a public suffix */
} else {
if (_vector_get(psl->suffix_exceptions, _vector_find(psl->suffix_exceptions, &suffix)) != 0)
return 0; // found an exception, so 'domain' is not a public suffix
return 0; /* found an exception, so 'domain' is not a public suffix */
}

return 1;
Expand Down Expand Up @@ -362,14 +361,16 @@ const char *psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain)
if (!psl || !domain)
return NULL;

// We check from left to right to catch special PSL entries like 'forgot.his.name':
// 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
/*
* We check from left to right to catch special PSL entries like 'forgot.his.name':
* 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
*/

while (!psl_is_public_suffix(psl, domain)) {
if ((domain = strchr(domain, '.')))
domain++;
else
break; // prevent endless loop if psl_is_public_suffix() is broken.
break; /* prevent endless loop if psl_is_public_suffix() is broken. */
}

return domain;
Expand Down Expand Up @@ -398,15 +399,17 @@ const char *psl_registrable_domain(const psl_ctx_t *psl, const char *domain)
if (!psl || !domain || *domain == '.')
return NULL;

// We check from left to right to catch special PSL entries like 'forgot.his.name':
// 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
/*
* We check from left to right to catch special PSL entries like 'forgot.his.name':
* 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
*/

while (!psl_is_public_suffix(psl, domain)) {
if ((p = strchr(domain, '.'))) {
regdom = domain;
domain = p + 1;
} else
break; // prevent endless loop if psl_is_public_suffix() is broken.
break; /* prevent endless loop if psl_is_public_suffix() is broken. */
}

return regdom;
Expand Down Expand Up @@ -473,24 +476,26 @@ psl_ctx_t *psl_load_fp(FILE *fp)
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.
/*
* 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
while (isspace(*linep)) linep++; /* ignore leading whitespace */
if (!*linep) continue; /* skip empty lines */

if (*linep == '/' && linep[1] == '/')
continue; // skip comments
continue; /* skip comments */

// parse suffix rule
/* parse suffix rule */
for (p = linep; *linep && !isspace(*linep);) linep++;
*linep = 0;

if (*p == '!') {
// add to exceptions
/* add to exceptions */
if (_suffix_init(&suffix, p + 1, linep - p - 1) == 0)
suffixp = _vector_get(psl->suffix_exceptions, _vector_add(psl->suffix_exceptions, &suffix));
else
Expand All @@ -503,7 +508,7 @@ psl_ctx_t *psl_load_fp(FILE *fp)
}

if (suffixp)
suffixp->label = suffixp->label_buf; // set label to changed address
suffixp->label = suffixp->label_buf; /* set label to changed address */

nsuffixes++;;
}
Expand Down Expand Up @@ -697,17 +702,17 @@ int psl_is_cookie_domain_acceptable(const psl_ctx_t *psl, const char *hostname,
cookie_domain++;

if (!strcmp(hostname, cookie_domain))
return 1; // an exact match is acceptable (and pretty common)
return 1; /* an exact match is acceptable (and pretty common) */

cookie_domain_length = strlen(cookie_domain);
hostname_length = strlen(hostname);

if (cookie_domain_length >= hostname_length)
return 0; // cookie_domain is too long
return 0; /* cookie_domain is too long */

p = hostname + hostname_length - cookie_domain_length;
if (!strcmp(p, cookie_domain) && p[-1] == '.') {
// OK, cookie_domain matches, but it must be longer than the longest public suffix in 'hostname'
/* OK, cookie_domain matches, but it must be longer than the longest public suffix in 'hostname' */

if (!(p = psl_unregistrable_domain(psl, hostname)))
return 1;
Expand Down
Loading

0 comments on commit d51a73d

Please sign in to comment.