* Converts error_directory squid.conf option into an optional override.
Providing backward compatibility with older configurations and local
customizations.
* Adds error_default_language to administratively set the backup
language presented by Squid.
* Fixes design of previously broken hard-coded failover language.
WAS: default to FreeBSD error install location. Hidden by
error_directory being required.
NOW: failover to build-time configured errors/ directory 'English'
templates.
* Adds --enable-auto-locale configure option to enable the following.
* Adds logic to locate visitors most-preferred of available languages
and present a tailored error page as their reply.
AC_PROG_CXX
AC_CANONICAL_HOST
+dnl Make location configure settings available to the code
+AC_DEFINE_UNQUOTED([DEFAULT_SQUID_CONFIG_DIR], "${sysconfdir}" , [Location of Configuration files] )
+AC_DEFINE_UNQUOTED([DEFAULT_SQUID_DATA_DIR], "${datadir}" , [Location of other data files] )
use_loadable_modules=1
AC_MSG_CHECKING(whether to use loadable modules)
fi
])
-dnl Select Default Error language
-AC_ARG_ENABLE(default-err-language,
-[ --enable-default-err-language=lang
- Select default language for Error pages (see
- errors directory) ],
-[
- if test -d $srcdir/errors/$enableval; then
- ERR_DEFAULT_LANGUAGE=$enableval
- else
- echo "ERROR! Unknown language $enableval, see errors/ directory"
- exit 1
- fi
-],[ERR_DEFAULT_LANGUAGE="English"])
-AC_SUBST(ERR_DEFAULT_LANGUAGE)
-
-dnl Select languages to be installed
-AC_ARG_ENABLE(err-languages,
-[ --enable-err-languages=\"lang1 lang2..\"
- Select languages to be installed. (All will be
- installed by default) ],
-[
- for l in $enableval; do
- if test -d $srcdir/errors/$l; then :; else
- echo "ERROR! Unknown language $$l, see errors/"
- exit 1
- fi
- done
- ERR_LANGUAGES=$enableval
-],[
- ERR_LANGUAGES=
- for l in $srcdir/errors/*; do
- if test -f $l/ERR_ACCESS_DENIED; then
- ERR_LANGUAGES="$ERR_LANGUAGES `basename $l`"
- fi
- done
-])
-AC_SUBST(ERR_LANGUAGES)
-
dnl Size of COSS memory buffer
AC_ARG_WITH(coss-membuf-size,
[ --with-coss-membuf-size COSS membuf size (default 1048576 bytes) ],
AC_SUBST(DO_TRANSLATE)
+dnl Squid now has limited locale handling ...
+dnl on error pages
+AC_ARG_ENABLE(auto-locale,
+[ --enable-auto-locale This enables squid to lookup translated error pages
+ based on the clients request headers. Without it squid
+ is limited to a single language set in squid.conf],
+[ if test "$enableval" = "yes" ; then
+ echo "Enabling Multi-Language Support"
+ AC_DEFINE(USE_ERR_LOCALES,1,[Use multi-language support on error pages])
+ else
+ echo "Disabling Multi-Language Support"
+ AC_DEFINE(USE_ERR_LOCALES,0,[Use multi-language support on error pages])
+ fi
+])
+
+
dnl Need the debugging version of malloc if available
XTRA_OBJS=''
if test "$ac_cv_lib_malloc_main" = "yes" ; then
DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf
DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf
DEFAULT_MIME_TABLE = $(sysconfdir)/mime.conf
-DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@
+DEFAULT_ERROR_DIR = $(datadir)/errors
SUBSTITUTE=sed "\
s%@DEFAULT_CONFIG_FILE@%$(DEFAULT_CONFIG_FILE)%g;\
\r
<itemize>\r
<item>IPv6 Support\r
+ <item>Error Page Localization\r
</itemize>\r
\r
Most user-facing changes are reflected in squid.conf (see below).\r
with the RADIUS server. A new helper will be needed for IPv6 RADIUS protocol.\r
\r
\r
+<sect2>Error Page Localization\r
+<p>\r
+The error pages presented by squid may now be localized per-request to match the visitors local preferred language.\r
+\r
+<p>Squid needs to be build with the --enable-auto-locale option. And the error_directory option in squid.conf needs to be removed.\r
+\r
+<p>For best coverage of languages, using the latest language pack of error files is recommended.\r
+Updates can be downloaded from <url url="http://www.squid-cahch.org/Versions/langpack/" name="www.squid-cache.org/Versions/langpack/">\r
+\r
+<p>The squid developers are interested in making squid available in a wide variety of languages.\r
+ Contributions of new languages is encouraged.\r
+ Details at <url url="http://wiki.squid-cache.org/Translations" named="The Squid wiki">\r
+\r
+\r
<sect1>Changes to squid.conf\r
<p>\r
There have been changes to Squid's configuration file since Squid-3.0.\r
include /path/to/file1 /path/to/file2\r
</verb>\r
\r
+ <tag>error_default_language</tag>\r
+ <p>New option to replace the old configure option --enable-default-err-language\r
+ <verb>\r
+ Set the default language which squid will send error pages in\r
+ if no existing translation matches the clients language\r
+ preferences.\r
+\r
+ If unset (default) generic English will be used.\r
+ </verb>\r
+\r
+\r
</descrip>\r
\r
<sect2>Changes to existing tags<label id="modifiedtags">\r
<p>option 'transparent' is being deprecated in favour of 'intercept' which more clearly identifies what the option does.\r
For now option 'tproxy' remains with old behaviour meaning fully-invisible proxy using TPROXY support.</p>\r
\r
+ <tag>error_directory</tag>\r
+ <p>Now an optiona entry in squid.conf. If present it will force all visitors to receive the error pages\r
+ contained in the directory it points at. If absent error page localization will be given a chance.\r
+ <verb>\r
+ If you wish to create your own versions of the default\r
+ error files to customize them to suit your company copy\r
+ the error/template files to another directory and point\r
+ this tag at them.\r
+\r
+ WARNING: This option will disable multi-language support\r
+ on error pages if used.\r
+\r
+ The squid developers are interested in making squid available in\r
+ a wide variety of languages. If you are making translations for a\r
+ language that Squid does not currently provide please consider\r
+ contributing your translation back to the project.\r
+ http://wiki.squid-cache.org/Translations\r
+\r
+ The squid developers working on translations are happy to supply drop-in\r
+ translated error files in exchange for any new language contributions.\r
+ </verb>\r
+\r
</descrip>\r
\r
\r
but please report the bugs anyway.\r
</p>\r
\r
+ <tag>--enable-auto-locale</tag>\r
+ <p>Enable error page localization for visitors.</p>\r
+\r
</descrip>\r
</p>\r
\r
<descrip>\r
<tag>--enable-linux-tproxy</tag>\r
<p>Replaced by --enable-linux-tproxy2 to make way for differences in TPROXY v2 and v4 support.</p>\r
-\r
+ <tag>--enable-default-err-language</tag>\r
+ <p>Replaced by error_default_language squid.conf option</p>\r
+ <tag>--enable-err-languages</tag>\r
+ <p>Removed.</p>\r
</descrip>\r
\r
</article>\r
# Legacy language contributions...
#
-INSTALL_LANGUAGES = @ERR_LANGUAGES@
LANGUAGES = \
Armenian \
Azerbaijani \
Ukrainian-utf8
install-data-local:
- @for l in $(INSTALL_LANGUAGES); do \
+ @for l in $(LANGUAGES); do \
$(mkinstalldirs) $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l && \
for f in $(srcdir)/$$l/ERR_*; do \
echo "$(INSTALL_DATA) $$f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l"; \
done
uninstall-local:
- @ for l in $(INSTALL_LANGUAGES); do \
+ @ for l in $(LANGUAGES); do \
for f in $(srcdir)/$$l/ERR_*; do \
rm -f $(DESTDIR)$(DEFAULT_ERROR_DIR)/$$l/`basename $$f`; \
done; \
DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'`
DEFAULT_DISKD = $(libexecdir)/`echo diskd | sed '$(transform);s/$$/$(EXEEXT)/'`
DEFAULT_ICON_DIR = $(datadir)/icons
-DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@
+DEFAULT_ERROR_DIR = $(datadir)/errors
DEFAULT_MIB_PATH = $(datadir)/mib.txt
DEFAULT_HOSTS = @OPT_DEFAULT_HOSTS@
## FIXME: generate a sed command file from configure. Then this doesn't
-## depend on the Makefile.
+## depend on the Makefile.
cf.data: cf.data.pre Makefile
sed "\
s%@DEFAULT_HTTP_PORT@%$(DEFAULT_HTTP_PORT)%g;\
requirePathnameExists("Icon Directory", Config.icons.directory);
- requirePathnameExists("Error Directory", Config.errorDirectory);
+ if(Config.errorDirectory)
+ requirePathnameExists("Error Directory", Config.errorDirectory);
#if HTTP_VIOLATIONS
NAME: error_directory
TYPE: string
LOC: Config.errorDirectory
-DEFAULT: @DEFAULT_ERROR_DIR@
+DEFAULT: none
DOC_START
If you wish to create your own versions of the default
- (English) error files, either to customize them to suit your
- language or company copy the template English files to another
- directory and point this tag at them.
+ error files to customize them to suit your company copy
+ the error/template files to another directory and point
+ this tag at them.
+
+ WARNING: This option will disable multi-language support
+ on error pages if used.
The squid developers are interested in making squid available in
a wide variety of languages. If you are making translations for a
- langauge that Squid does not currently provide please consider
+ language that Squid does not currently provide please consider
contributing your translation back to the project.
+ http://wiki.squid-cache.org/Translations
+
+ The squid developers working on translations are happy to supply drop-in
+ translated error files in exchange for any new language contributions.
+DOC_END
+
+NAME: error_default_language
+IFDEF: USE_ERR_LOCALES
+TYPE: string
+LOC: Config.errorDefaultLanguage
+DEFAULT: none
+DOC_START
+ Set the default language which squid will send error pages in
+ if no existing translation matches the clients language
+ preferences.
+
+ If unset (default) generic English will be used.
+
+ The squid developers are interested in making squid available in
+ a wide variety of languages. If you are interested in making
+ translations for any language see the squid wiki for details.
+ http://wiki.squid-cache.org/Translations
DOC_END
NAME: err_html_text
DOC_START
Usage: deny_info err_page_name acl
or deny_info http://... acl
- Example: deny_info ERR_CUSTOM_ACCESS_DENIED bad_guys
+ or deny_info TCP_RESET acl
This can be used to return a ERR_ page for requests which
do not pass the 'http_access' rules. Squid remembers the last
- When none of the http_access lines matches. It's then the last
acl processed on the last http_access line.
- You may use ERR_ pages that come with Squid or create your own pages
- and put them into the configured errors/ directory.
+ NP: If providing your own custom error pages with error_directory
+ you may also specify them by your custom file name:
+ Example: deny_info ERR_CUSTOM_ACCESS_DENIED bad_guys
Alternatively you can specify an error URL. The browsers will
get redirected (302) to the specified URL. %s in the redirection
*/
#define N_COUNT_HOUR_HIST (86400 * 3) / (60 * COUNT_INTERVAL)
-/* were to look for errors if config path fails */
-#ifndef DEFAULT_SQUID_ERROR_DIR
-#define DEFAULT_SQUID_ERROR_DIR "/usr/local/squid/etc/errors"
-#endif
-
/* handy to determine the #elements in a static array */
#define countof(arr) (sizeof(arr)/sizeof(*arr))
*/
+#ifndef DEFAULT_SQUID_ERROR_DIR
+/** Where to look for errors if config path fails.
+ \note Please use ./configure --datadir=/path instead of patching
+ */
+#define DEFAULT_SQUID_ERROR_DIR DEFAULT_SQUID_DATA_DIR"/errors"
+#endif
+
/// \ingroup ErrorPageInternal
CBDATA_CLASS_INIT(ErrorState);
/// \ingroup ErrorPageInternal
static int error_page_count = 0;
-static char *errorTryLoadText(const char *page_name, const char *dir);
+static char *errorTryLoadText(const char *page_name, const char *dir, bool silent = false);
static char *errorLoadText(const char *page_name);
static const char *errorFindHardText(err_type type);
static ErrorDynamicPageInfo *errorDynamicPageInfoCreate(int id, const char *page_name);
for (i = ERR_NONE, ++i; i < error_page_count; ++i) {
safe_free(error_text[i]);
- /* hard-coded ? */
- if ((text = errorFindHardText(i)))
+ if ((text = errorFindHardText(i))) {
+ /**\par
+ * Index any hard-coded error text into defaults.
+ */
error_text[i] = xstrdup(text);
- else if (i < ERR_MAX) {
- /* precompiled ? */
+
+ } else if (i < ERR_MAX) {
+ /**\par
+ * Index precompiled fixed template files from one of two sources:
+ * (a) default language translation directory (error_default_language)
+ * (b) admin specified custom directory (error_directory)
+ */
error_text[i] = errorLoadText(err_type_str[i]);
+
} else {
- /* dynamic */
+ /** \par
+ * Index any unknown file names used by deny_info.
+ */
ErrorDynamicPageInfo *info = ErrorDynamicPages.items[i - ERR_MAX];
assert(info && info->id == i && info->page_name);
if (strchr(info->page_name, ':') == NULL) {
- /* Not on redirected errors... */
+ /** But only if they are not redirection URL. */
error_text[i] = errorLoadText(info->page_name);
}
}
return NULL;
}
-
-/// \ingroup ErrorPageInternal
+/**
+ * \ingroup ErrorPageInternal
+ *
+ * Load into the in-memory error text Index a file probably available at:
+ * (a) admin specified custom directory (error_directory)
+ * (b) default language translation directory (error_default_language)
+ * (c) English sub-directory where errors should ALWAYS exist
+ */
static char *
errorLoadText(const char *page_name)
{
- /* test configured location */
- char *text = errorTryLoadText(page_name, Config.errorDirectory);
- /* test default location if failed */
+ char *text = NULL;
+
+ /** test error_directory configured location */
+ if(Config.errorDirectory)
+ text = errorTryLoadText(page_name, Config.errorDirectory);
+
+#if USE_ERR_LOCALES
+ /** test error_default_language location */
+ if(!text && Config.errorDefaultLanguage) {
+ char dir[256];
+ snprintf(dir,256,"%s/%s", DEFAULT_SQUID_ERROR_DIR, Config.errorDefaultLanguage);
+ text = errorTryLoadText(page_name, dir);
+ if(!text) {
+ debugs(1, DBG_CRITICAL, "Unable to load default language. Reset to English");
+ }
+ }
+#endif
- if (!text && strcmp(Config.errorDirectory, DEFAULT_SQUID_ERROR_DIR))
- text = errorTryLoadText(page_name, DEFAULT_SQUID_ERROR_DIR);
+ /* test default location if failed (templates == English translation base templates) */
+ if (!text)
+ text = errorTryLoadText(page_name, DEFAULT_SQUID_ERROR_DIR"/templates");
/* giving up if failed */
if (!text)
/// \ingroup ErrorPageInternal
static char *
-errorTryLoadText(const char *page_name, const char *dir)
+errorTryLoadText(const char *page_name, const char *dir, bool silent)
{
int fd;
char path[MAXPATHLEN];
fd = file_open(path, O_RDONLY | O_TEXT);
if (fd < 0) {
- debugs(4, 0, "errorTryLoadText: '" << path << "': " << xstrerror());
+ /* with dynamic locale negotiation we may see some failures before a success. */
+ if(!silent)
+ debugs(4, DBG_CRITICAL, HERE << "'" << path << "': " << xstrerror());
return NULL;
}
ErrorState::BuildContent()
{
MemBuf *content = new MemBuf;
- const char *m;
+ const char *m = NULL;
const char *p;
const char *t;
+
assert(page_id > ERR_NONE && page_id < error_page_count);
- content->init();
- m = error_text[page_id];
+
+#if USE_ERR_LOCALES
+ String hdr;
+ char dir[256];
+ int l = 0;
+
+ /** error_directory option in squid.conf overrides translations.
+ * Otherwise locate the Accept-Language header
+ */
+ if(!Config.errorDirectory && request->header.getList(HDR_ACCEPT_LANGUAGE, &hdr) ) {
+
+ const char *buf = hdr.buf(); // raw header string for parsing
+ int pos = 0; // current parsing position in header string
+ char *reset = NULL; // where to reset the p pointer for each new tag file
+ char *dt = NULL;
+
+ /* prep the directory path string to prevent snprintf ... */
+ l = strlen(DEFAULT_SQUID_ERROR_DIR);
+ memcpy(dir, DEFAULT_SQUID_ERROR_DIR, l);
+ dir[ l++ ] = '/';
+ reset = dt = dir + l;
+
+ debugs(4, 6, HERE << "Testing Header: '" << hdr << "'");
+
+ while( pos < hdr.size() ) {
+
+/*
+ * Header value format:
+ * - sequence of whitespace delimited tags
+ * - each tag may suffix with ';'.* which we can ignore.
+ * - IFF a tag contains only two characters we can wildcard ANY translations matching: <it> '-'? .*
+ * with preference given to an exact match.
+ */
+ while(pos < hdr.size() && buf[pos] != ';' && buf[pos] != ',' && !xisspace(buf[pos]) && dt < (dir+256) ) {
+ *dt++ = xtolower(buf[pos++]);
+ }
+ *dt++ = '\0'; // nul-terminated the filename content string before system use.
+
+ debugs(4, 9, HERE << "STATE: dt='" << dt << "', reset='" << reset << "', reset[1]='" << reset[1] << "', pos=" << pos << ", buf='" << &buf[pos] << "'");
+
+ /* if we found anything we might use, try it. */
+ if(*reset != '\0') {
+
+ debugs(4, 6, HERE << "Found language '" << reset << "', testing for available template in: '" << dir << "'");
+ m = errorTryLoadText( err_type_str[page_id], dir, false);
+
+ if(m) break; // FOUND IT!!
+
+#if HAVE_GLOB
+ if( (dt - reset) == 2) {
+ /* TODO glob the error directory for sub-dirs matching: <tag> '-*' */
+ /* use first result. */
+ debugs(4,2, HERE << "wildcard fallback errors not coded yet.");
+ }
+#endif
+ }
+
+ dt = reset; // reset for next tag testing. we replace the failed name instead of cloning.
+
+ // IFF we terminated the tag on ';' we need to skip the 'q=' bit to the next ',' or end.
+ while(pos < hdr.size() && buf[pos] != ',') pos++;
+ if(buf[pos] == ',') pos++;
+ }
+ }
+#endif /* USE_ERR_LOCALES */
+
+ /** \par
+ * If client-specific error templates are not enabled or available.
+ * fall back to the old style squid.conf settings.
+ */
+ if(!m) {
+ m = error_text[page_id];
+ debugs(4, 1, HERE << "No existing languages found. Fall back on default language.");
+ }
+
assert(m);
+ content->init();
while ((p = strchr(m, '%'))) {
content->append(m, p - m); /* copy */
int use_short_names;
} icons;
char *errorDirectory;
+#if USE_ERR_LOCALES
+ char *errorDefaultLanguage;
+#endif
struct
{