X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Firi.c;h=dcab3ea1533fc2ea9e9d3429a134a9b9471060ee;hp=1f421d43f9cc3856cabb9ea944f05eb0f4112efc;hb=38a7829dcb4eb5dba28dbf0f05c6a80fea9217f8;hpb=169a16fc7ddb348cc4f0a5ebd149f754b5042478 diff --git a/src/iri.c b/src/iri.c index 1f421d43..dcab3ea1 100644 --- a/src/iri.c +++ b/src/iri.c @@ -1,5 +1,5 @@ /* IRI related functions. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GNU Wget. @@ -31,7 +31,6 @@ as that of the covered work. */ #include #include -#include #include #include #include @@ -39,25 +38,12 @@ as that of the covered work. */ #include #include "utils.h" -#include "iri.h" -/* Note: locale encoding is kept in options struct (opt.locale) */ - -/* Hold the encoding used for the current fetch */ -char *remote; - -/* Hold the encoding for the future found links */ -char *current; - -/* Will/Is the current URL encoded in utf8 ? */ -bool utf8_encode; +/* RFC3987 section 3.1 mandates STD3 ASCII RULES */ +#define IDNA_FLAGS IDNA_USE_STD3_ASCII_RULES -/* Force no utf8 encoding for url_parse () */ -bool ugly_no_encode; - -static iconv_t locale2utf8; +/* Note: locale encoding is kept in options struct (opt.locale) */ -static bool open_locale_to_utf8 (void); static bool do_conversion (iconv_t cd, char *in, size_t inlen, char **out); @@ -114,7 +100,7 @@ check_encoding_name (char *encoding) { if (!c_isascii (*s) || c_isspace (*s)) { - logprintf (LOG_VERBOSE, "Encoding %s isn't valid\n", quote (encoding)); + logprintf (LOG_VERBOSE, _("Encoding %s isn't valid\n"), quote (encoding)); return false; } @@ -124,54 +110,40 @@ check_encoding_name (char *encoding) return true; } -/* Try opening an iconv_t descriptor for conversion from locale to UTF-8 */ -static bool -open_locale_to_utf8 (void) -{ - if (locale2utf8) - return true; - - /* sXXXav : That shouldn't happen, just in case */ - if (!opt.locale) - { - logprintf (LOG_VERBOSE, "open_locale_to_utf8: locale is unset\n"); - opt.locale = find_locale (); - } - - if (!opt.locale) - return false; - - locale2utf8 = iconv_open ("UTF-8", opt.locale); - if (locale2utf8 != (iconv_t)(-1)) - return true; - - logprintf (LOG_VERBOSE, "Conversion from %s to %s isn't supported\n", - quote (opt.locale), quote ("UTF-8")); - locale2utf8 = NULL; - return false; -} - /* Try converting string str from locale to UTF-8. Return a new string on success, or str on error or if conversion isn't needed. */ const char * locale_to_utf8 (const char *str) { + iconv_t l2u; char *new; - if (!strcasecmp (opt.locale, "utf-8")) - return str; + /* That shouldn't happen, just in case */ + if (!opt.locale) + { + logprintf (LOG_VERBOSE, _("locale_to_utf8: locale is unset\n")); + opt.locale = find_locale (); + } - if (!open_locale_to_utf8 ()) + if (!opt.locale || !strcasecmp (opt.locale, "utf-8")) return str; - if (do_conversion (locale2utf8, (char *) str, strlen ((char *) str), &new)) + l2u = iconv_open ("UTF-8", opt.locale); + if (l2u != (iconv_t)(-1)) + { + logprintf (LOG_VERBOSE, _("Conversion from %s to %s isn't supported\n"), + quote (opt.locale), quote ("UTF-8")); + return str; + } + + if (do_conversion (l2u, (char *) str, strlen ((char *) str), &new)) return (const char *) new; return str; } /* Do the conversion according to the passed conversion descriptor cd. *out - will containes the transcoded string on success. *out content is + will contain the transcoded string on success. *out content is unspecified otherwise. */ static bool do_conversion (iconv_t cd, char *in, size_t inlen, char **out) @@ -200,7 +172,7 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out) { if (!invalid) logprintf (LOG_VERBOSE, - "Incomplete or invalide multibyte sequence encountered\n"); + _("Incomplete or invalid multibyte sequence encountered\n")); invalid++; **out = *in; @@ -225,7 +197,7 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out) } else /* Weird, we got an unspecified error */ { - logprintf (LOG_VERBOSE, "Unhandled errno %d\n", errno); + logprintf (LOG_VERBOSE, _("Unhandled errno %d\n"), errno); break; } } @@ -236,29 +208,25 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out) /* Try to "ASCII encode" UTF-8 host. Return the new domain on success or NULL on error. */ char * -idn_encode (char *host, bool utf8_encoded) +idn_encode (struct iri *i, char *host) { char *new; int ret; - /* Encode to UTF-8 if not done using current remote */ - if (!utf8_encoded) + /* Encode to UTF-8 if not done */ + if (!i->utf8_encode) { - if (!remote_to_utf8 ((const char *) host, (const char **) &new)) - { - /* Nothing to encode or an error occured */ - return NULL; - } - + if (!remote_to_utf8 (i, (const char *) host, (const char **) &new)) + return NULL; /* Nothing to encode or an error occured */ host = new; } /* toASCII UTF-8 NULL terminated string */ - ret = idna_to_ascii_8z (host, &new, 0); + ret = idna_to_ascii_8z (host, &new, IDNA_FLAGS); if (ret != IDNA_SUCCESS) { /* sXXXav : free new when needed ! */ - logprintf (LOG_VERBOSE, "idn_encode failed (%d): %s\n", ret, + logprintf (LOG_VERBOSE, _("idn_encode failed (%d): %s\n"), ret, quote (idna_strerror (ret))); return NULL; } @@ -274,10 +242,10 @@ idn_decode (char *host) char *new; int ret; - ret = idna_to_unicode_8zlz (host, &new, 0); + ret = idna_to_unicode_8zlz (host, &new, IDNA_FLAGS); if (ret != IDNA_SUCCESS) { - logprintf (LOG_VERBOSE, "idn_decode failed (%d): %s\n", ret, + logprintf (LOG_VERBOSE, _("idn_decode failed (%d): %s\n"), ret, quote (idna_strerror (ret))); return NULL; } @@ -288,20 +256,30 @@ idn_decode (char *host) /* Try to transcode string str from remote encoding to UTF-8. On success, *new contains the transcoded string. *new content is unspecified otherwise. */ bool -remote_to_utf8 (const char *str, const char **new) +remote_to_utf8 (struct iri *iri, const char *str, const char **new) { - char *r; iconv_t cd; bool ret = false; - if (opt.encoding_remote) - r = opt.encoding_remote; - else if (current) - r = current; - else + if (!iri->uri_encoding) return false; - cd = iconv_open ("UTF-8", r); + /* When `i->uri_encoding' == "UTF-8" there is nothing to convert. But we must + test for non-ASCII symbols for correct hostname processing in `idn_encode' + function. */ + if (!strcmp (iri->uri_encoding, "UTF-8")) + { + const char *p = str; + for (p = str; *p; p++) + if (*p < 0) + { + *new = strdup (str); + return true; + } + return false; + } + + cd = iconv_open ("UTF-8", iri->uri_encoding); if (cd == (iconv_t)(-1)) return false; @@ -320,72 +298,71 @@ remote_to_utf8 (const char *str, const char **new) return ret; } -char *get_remote_charset (void) +/* Allocate a new iri structure and return a pointer to it. */ +struct iri * +iri_new (void) { - return remote; + struct iri *i = xmalloc (sizeof *i); + i->uri_encoding = opt.encoding_remote ? xstrdup (opt.encoding_remote) : NULL; + i->content_encoding = NULL; + i->orig_url = NULL; + i->utf8_encode = opt.enable_iri; + return i; } -char *get_current_charset (void) +struct iri *iri_dup (const struct iri *src) { - return current; -} - -void set_current_charset (char *charset) -{ - /*printf("[ current = `%s'\n", charset);*/ - if (current) - xfree (current); - - current = charset ? xstrdup (charset) : NULL; -} - -void set_current_as_locale (void) -{ - /*printf("[ current = locale = `%s'\n", opt.locale);*/ - if (current) - xfree (current); - - /* sXXXav : assert opt.locale NULL ? */ - current = xstrdup (opt.locale); + struct iri *i = xmalloc (sizeof *i); + i->uri_encoding = src->uri_encoding ? xstrdup (src->uri_encoding) : NULL; + i->content_encoding = (src->content_encoding ? + xstrdup (src->content_encoding) : NULL); + i->orig_url = src->orig_url ? xstrdup (src->orig_url) : NULL; + i->utf8_encode = src->utf8_encode; + return i; } +/* Completely free an iri structure. */ void -set_remote_charset (char *charset) +iri_free (struct iri *i) { - /*printf("[ remote = `%s'\n", charset);*/ - if (remote) - xfree (remote); - - remote = charset ? xstrdup (charset) : NULL; + xfree_null (i->uri_encoding); + xfree_null (i->content_encoding); + xfree_null (i->orig_url); + xfree (i); } +/* Set uri_encoding of struct iri i. If a remote encoding was specified, use + it unless force is true. */ void -set_remote_as_current (void) +set_uri_encoding (struct iri *i, char *charset, bool force) { - /*printf("[ remote = current = `%s'\n", current);*/ - if (remote) - xfree (remote); - - remote = current ? xstrdup (current) : NULL; -} - -void reset_utf8_encode (void) -{ - set_utf8_encode (opt.enable_iri); -} + DEBUGP (("URI encoding = %s\n", charset ? quote (charset) : "None")); + if (!force && opt.encoding_remote) + return; + if (i->uri_encoding) + { + if (charset && !strcasecmp (i->uri_encoding, charset)) + return; + xfree (i->uri_encoding); + } -void set_utf8_encode (bool encode) -{ - utf8_encode = encode; + i->uri_encoding = charset ? xstrdup (charset) : NULL; } -bool get_utf8_encode (void) +/* Set content_encoding of struct iri i. */ +void +set_content_encoding (struct iri *i, char *charset) { - return (!ugly_no_encode && utf8_encode); -} + DEBUGP (("URI content encoding = %s\n", charset ? quote (charset) : "None")); + if (opt.encoding_remote) + return; + if (i->content_encoding) + { + if (charset && !strcasecmp (i->content_encoding, charset)) + return; + xfree (i->content_encoding); + } -void set_ugly_no_encode (bool ugly) -{ - ugly_no_encode = ugly; + i->content_encoding = charset ? xstrdup (charset) : NULL; }