47#include <malloc/malloc.h>
49#if !defined(MO_DARWIN) && !defined(MO_FREEBSD)
58#define strncasecmp _strnicmp
365 for(uint32_t idx(0); idx <
tld->f_tags_count; ++idx)
373 str = tld_file_string(
g_tld_file, tag->f_tag_name, &l);
379 && memcmp(str,
"category", l) == 0)
381 str = tld_file_string(
g_tld_file, tag->f_tag_value, &l);
388 && memcmp(str,
"country", l) == 0)
390 str = tld_file_string(
g_tld_file, tag->f_tag_value, &l);
413 return (c >=
'0' && c <=
'9')
414 || (c >=
'A' && c <=
'F')
415 || (c >=
'a' && c <=
'f');
499static int cmp(
const char *a,
int l,
const char *b,
int n)
510 while(l > 0 && n > 0)
569static int search(
int i,
int j,
char const * domain,
int n)
571 int auto_match = -1, p, r;
584 if(
static_cast<uint32_t
>(i) >
static_cast<uint32_t
>(j))
590 <<
") is larger than j ("
592 <<
") which is not expected in search()."
602 if(
static_cast<uint32_t
>(i) >=
g_tld_file->f_descriptions_count
603 ||
static_cast<uint32_t
>(j) >
g_tld_file->f_descriptions_count)
611 <<
") is too large, max is "
631 if(l == 1 && name[0] ==
'*')
651std::cerr <<
"--- name offset: " <<
tld->f_tld <<
" --- ptr: " <<
reinterpret_cast<void const *
>(name) <<
", cmp(\"" << std::string(name, l) <<
"\", \"" << std::string(domain, n) <<
"\") == " << r <<
"\n";
654 if(l == 1 && name[0] ==
'*')
658 <<
"fatal error: found an asterisk within an array of sub-domains at "
665 r =
cmp(name, l, domain, n);
667std::cerr <<
"--- name offset: " <<
tld->f_tld <<
" --- cmp(\"" << std::string(name, l) <<
"\", \"" << std::string(domain, n) <<
"\") == " << r <<
"\n";
710 info->
f_tld = (
const char *) 0;
712 info->f_tld_index = -1;
746 enum tld_file_error err;
750 if(filename ==
nullptr)
754 err = tld_file_load(
"/var/lib/libtld/tlds.tld", &
g_tld_file);
755 if(err == TLD_FILE_ERROR_NONE)
763 filename =
"/usr/share/libtld/tlds.tld";
768 if(err == TLD_FILE_ERROR_NONE)
777 std::stringstream in;
780 if(err == TLD_FILE_ERROR_NONE)
786 return err == TLD_FILE_ERROR_CANNOT_OPEN_FILE
904 if(
g_tld_file->f_header->f_tld_max_level > std::size(state->f_offset))
909 if(state->f_depth == 0
910 && state->f_offset[0] == 0)
914 state->f_offset[0] =
g_tld_file->f_header->f_tld_start_offset;
919 if(state->f_offset[0] >=
g_tld_file->f_header->f_tld_end_offset)
926 char * domain(state->f_domain +
sizeof(state->f_domain));
929 for(
int d(0); d <= state->f_depth; ++d)
934 char const * name = tld_file_string(
g_tld_file,
tld->f_tld, &length);
944 && name[length - 2] ==
'%'
945 && is_hex(name[length - 1])
946 && is_hex(name[length - 0]))
950 c = h2d(name[length - 1]) * 16 + h2d(name[length - 0]);
958 if(domain < state->f_domain)
968 if(domain < state->f_domain)
975 info->
f_tld = state->f_domain;
976 info->
f_offset = domain - state->f_domain;
977 info->f_tld_index = state->f_offset[state->f_depth];
979 tags_to_info(
tld, info);
983 if(
tld->f_start_offset != 65535)
986 state->f_offset[state->f_depth] =
tld->f_start_offset;
990 ++state->f_offset[state->f_depth];
991 while(state->f_depth > 0)
994 if(state->f_offset[state->f_depth] < parent->
f_end_offset)
999 ++state->f_offset[state->f_depth];
1115 char const * end = uri;
1117 int level = 0, max_level, start_level, i, r, p, offset;
1123 if(uri ==
nullptr || uri[0] ==
'\0')
1135 max_level =
g_tld_file->f_header->f_tld_max_level;
1136 std::vector<const char *> level_ptr(max_level);
1137 for(
char const * previous_start(end); *end !=
'\0'; ++end)
1141 if(end - previous_start > LIBTLD_MAXIMUM_LABEL_LENGTH)
1145 if(level >= max_level)
1150 for(i = 1; i < max_level; ++i)
1152 level_ptr[i - 1] = level_ptr[i];
1154 level_ptr[max_level - 1] = end;
1158 level_ptr[level] = end;
1161 if(level >= 2 && level_ptr[level - 2] + 1 == level_ptr[level - 1])
1166 previous_start = end + 1;
1169 if(end - uri > LIBTLD_MAXIMUM_URI_LENGTH)
1180 start_level = level;
1184 level_ptr[level] + 1, (
int) (end - level_ptr[level] - 1));
1192 for(p = r; level > 0; --level, p = r)
1199 if(
tld->f_start_offset == USHRT_MAX)
1204 level_ptr[level - 1] + 1,
1205 static_cast<int>(level_ptr[level] - level_ptr[level - 1] - 1));
1212 offset = (int) (level_ptr[level] - uri);
1225 static_cast<int>(level_ptr[0] - uri));
1239 info->f_tld_index = p;
1251 p =
tld->f_exception_apply_to;
1257 level = start_level -
tld->f_exception_level;
1258 offset =
static_cast<int>(level_ptr[level] - uri);
1269 tags_to_info(
tld, info);
1271 info->
f_tld = level_ptr[level];
1321 const char *p, *q, *username, *password, *host, *port, *n, *a, *query_string;
1323 int protocol_length, length, valid, c, i, j, anchor;
1329 if(uri ==
nullptr || uri[0] ==
'\0')
1335 for(p = uri; *uri !=
'\0' && *uri !=
':'; ++uri)
1337 if((*uri <
'a' || *uri >
'z')
1338 && (*uri <
'A' || *uri >
'Z')
1339 && (*uri <
'0' || *uri >
'9')
1346 protocol_length = (int) (uri - p);
1348 for(q = protocols; *q !=
'\0';)
1350 if(q[0] ==
'*' && (q[1] ==
'\0' || q[1] ==
','))
1355 if(tolower(*q) == c)
1357 if(strncasecmp(p, q, protocol_length) == 0
1358 && (q[protocol_length] ==
'\0' || q[protocol_length] ==
','))
1365 for(; *q !=
'\0' && *q !=
','; ++q);
1366 for(; *q ==
','; ++q);
1372 if(uri[1] !=
'/' || uri[2] !=
'/')
1381 for(; *uri !=
'/' && *uri !=
'\0'; ++uri)
1383 if((
unsigned char) *uri <
' ')
1390 if(username !=
nullptr)
1398 else if((*uri & 0x80) != 0)
1406 else if(*uri ==
' ' || *uri ==
'+')
1411 else if(*uri ==
'%')
1417 if(((uri[1] <
'2' || uri[1] >
'9')
1418 && (uri[1] <
'a' || uri[1] >
'f')
1419 && (uri[1] <
'A' || uri[1] >
'F'))
1420 || ((uri[2] <
'0' || uri[2] >
'9')
1421 && (uri[2] <
'a' || uri[2] >
'f')
1422 && (uri[2] <
'A' || uri[2] >
'F')))
1426 if(uri[1] ==
'2' && uri[2] ==
'0')
1440 if(username !=
nullptr)
1442 password = username;
1443 for(; *password !=
'@' && *password !=
':'; ++password);
1444 if(*password ==
':')
1446 if((host - 1) - (password + 1) <= 0)
1452 if(password - username - 1 <= 0)
1458 for(port = host; *port !=
':' && port < uri; ++port);
1466 for(n = port + 1; *n >=
'0' && *n <=
'9'; ++n);
1467 if(n != uri || n == port + 1)
1476 query_string =
nullptr;
1478 for(a = uri; *a !=
'\0'; ++a)
1480 if((
unsigned char) *a <
' ')
1486 else if(*a ==
'+' || *a ==
' ')
1499 if(query_string !=
nullptr)
1506 query_string = a + 1;
1509 else if(*a ==
'&' && anchor == 0)
1511 if(query_string ==
nullptr)
1521 query_string = a + 1;
1525 if(query_string !=
nullptr && a - query_string == 0)
1533 query_string =
nullptr;
1542 if(((a[1] <
'2' || a[1] >
'9')
1543 && (a[1] <
'a' || a[1] >
'f')
1544 && (a[1] <
'A' || a[1] >
'F'))
1545 || ((a[2] <
'0' || a[2] >
'9')
1546 && (a[2] <
'a' || a[2] >
'f')
1547 && (a[2] <
'A' || a[2] >
'F')))
1564 else if((*a & 0x80) != 0)
1589 length = (int) (port - host);
1590 if(length >= (
int) (
sizeof(domain) /
sizeof(domain[0])))
1606 for(i = 0, j = 0; i < length; ++i, ++j)
1610 domain[j] = (char) (h2d(host[i + 1]) * 16 + h2d(host[i + 2]));
1615 domain[j] = host[i];
1620 result =
tld(domain, info);
1621 if(info->
f_tld !=
nullptr)
1679 return reinterpret_cast<uint32_t
const *
>(tld_static_tlds)[1] + 8;
1683int tld_tag_count(
struct tld_info *info)
1688 || info->f_tld_index < 0)
1699 return tld->f_tags_count;
1714 tag->f_name =
nullptr;
1715 tag->f_name_length = 0;
1716 tag->f_value =
nullptr;
1717 tag->f_value_length = 0;
1724 if(info->f_tld_index < 0)
1741 file_tag = tld_file_tag(
g_tld_file,
tld->f_tags + tag_idx * 2);
1742 if(file_tag ==
nullptr)
1747 tag->f_name = tld_file_string(
g_tld_file, file_tag->f_tag_name, &l);
1748 tag->f_name_length = l;
1750 tag->f_value = tld_file_string(
g_tld_file, file_tag->f_tag_value, &l);
1751 tag->f_value_length = l;
1753 if(tag->f_name ==
nullptr
1754 || tag->f_value ==
nullptr)
[internal] The description of one TLD.
uint16_t f_end_offset
The last offset of a list of TLDs.
Set of information returned by the tld() function.
enum tld_category f_category
The category of the TLD.
enum tld_status f_status
The status of the TLD.
int f_offset
The offset to the TLD in the URI string you supplied.
char f_country[48]
The country where this TLD is used.
const char * f_tld
Pointer to the TLD in the URI string you supplied.
const char * tld_version()
Return the version of the library.
static struct tld_file * g_tld_file
The TLD file currently loaded or NULL.
enum tld_result tld(char const *const uri, struct tld_info *info)
Get information about the TLD for the specified URI.
static enum tld_result tld_load_tlds_if_not_loaded()
Load the TLDs if not yet loaded.
static int cmp(const char *a, int l, const char *b, int n)
Compare two strings, one of which is limited by length.
void tld_clear_info(struct tld_info *info)
Clear the info structure.
const struct tld_file * tld_get_tlds()
Return a pointer to the current list of TLDs.
static int search(int i, int j, char const *domain, int n)
Search for the specified domain.
enum tld_result tld_next_tld(struct tld_enumeration_state *state, struct tld_info *info)
Read the next TLD and return its info.
enum tld_result tld_check_uri(const char *uri, struct tld_info *info, const char *protocols, int flags)
Check that a URI is valid.
uint32_t tld_get_static_tlds_buffer_size()
Get the size of the TLDs static buffer.
void tld_free_tlds()
Clear the allocated TLD file.
enum tld_result tld_load_tlds(char const *filename, int fallback)
Load a TLDs file as the file to be used by the tld() function.
The public header of the libtld library.
#define VALID_URI_NO_SPACES
Whether to check that the URI do not include any spaces.
#define LIBTLD_VERSION
The version of the library as a string.
@ TLD_CATEGORY_UNDEFINED
The TLD was not found.
#define VALID_URI_ASCII_ONLY
Whether to check that the URI only includes ASCII.
LIBTLD_EXPORT enum tld_category tld_word_to_category(const char *word, int n)
This is for backward compatibility.
@ TLD_RESULT_SUCCESS
Success! The TLD of the specified URI is valid.
@ TLD_RESULT_NO_TLD
The input URI has no TLD defined.
@ TLD_RESULT_INVALID
The TLD was found, but it is marked as invalid.
@ TLD_RESULT_BAD_URI
The URI includes characters that are not accepted by the function.
@ TLD_RESULT_NOT_FOUND
The URI has a TLD that could not be determined.
@ TLD_RESULT_NULL
The input URI is empty.
@ TLD_STATUS_EXCEPTION
Special status to indicate an exception which is not directly a TLD.
@ TLD_STATUS_UNDEFINED
Special status to indicate we did not find the TLD.
@ TLD_STATUS_VALID
The TLD is currently valid.
Declaration of the static TLDs file.
Declaration of the TLD file structures.