-const char filters_rcs[] = "$Id: filters.c,v 1.144 2011/07/30 15:15:25 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.155 2011/11/06 11:36:42 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
#include "urlmatch.h"
#include "loaders.h"
+#ifdef HAVE_STRTOK
+/* Only used for locks */
+#include "jcc.h"
+#endif /* def HAVE_STRTOK */
+
#ifdef _WIN32
#include "win32.h"
#endif
}
if (0 == strcmpic(redirect_mode, "check-decoded-url"))
- {
- log_error(LOG_LEVEL_REDIRECTS, "Decoding \"%s\" if necessary.", subject);
+ {
+ log_error(LOG_LEVEL_REDIRECTS,
+ "Checking \"%s\" for encoded redirects.", subject);
+
+#if defined(MUTEX_LOCKS_AVAILABLE) && defined(HAVE_STRTOK)
+ /*
+ * Check each parameter in the URL separately.
+ * Sectionize the URL at "?" and "&",
+ * then URL-decode each component,
+ * and look for a URL in the decoded result.
+ * Keep the last one we spot.
+ */
+ char *found = NULL;
+
+ privoxy_mutex_lock(&strtok_mutex);
+ char *token = strtok(subject, "?&");
+ while (token)
+ {
+ char *dtoken = url_decode(token);
+ if (NULL == dtoken)
+ {
+ log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", token);
+ continue;
+ }
+ char *http_url = strstr(dtoken, "http://");
+ char *https_url = strstr(dtoken, "https://");
+ char *last_url = (http_url && https_url
+ ? (http_url < https_url ? http_url : https_url)
+ : (http_url ? http_url : https_url));
+ if (last_url)
+ {
+ freez(found);
+ found = strdup(last_url);
+ if (found == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Out of memory while searching for redirects.");
+ privoxy_mutex_unlock(&strtok_mutex);
+ return NULL;
+ }
+ }
+ freez(dtoken);
+ token = strtok(NULL, "?&");
+ }
+ privoxy_mutex_unlock(&strtok_mutex);
+ freez(subject);
+
+ return found;
+#else
new_url = url_decode(subject);
if (new_url != NULL)
{
{
log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", subject);
}
+#endif /* defined(MUTEX_LOCKS_AVAILABLE) && defined(HAVE_STRTOK) */
}
- log_error(LOG_LEVEL_REDIRECTS, "Checking \"%s\" for redirects.", subject);
+ /* Else, just look for a URL inside this one, without decoding anything. */
+
+ log_error(LOG_LEVEL_REDIRECTS,
+ "Checking \"%s\" for unencoded redirects.", subject);
/*
* Find the last URL encoded in the request
/* Did any redirect action trigger? */
if (new_url)
{
+ if (url_requires_percent_encoding(new_url))
+ {
+ char *encoded_url;
+ log_error(LOG_LEVEL_REDIRECTS, "Percent-encoding redirect URL: %N",
+ strlen(new_url), new_url);
+ encoded_url = percent_encode_url(new_url);
+ freez(new_url);
+ if (encoded_url == NULL)
+ {
+ return cgi_error_memory();
+ }
+ new_url = encoded_url;
+ }
+
if (0 == strcmpic(new_url, csp->http->url))
{
log_error(LOG_LEVEL_ERROR,
return cgi_error_memory();
}
- if ( enlist_unique_header(rsp->headers, "Location", new_url)
- || (NULL == (rsp->status = strdup("302 Local Redirect from Privoxy"))) )
+ if (enlist_unique_header(rsp->headers, "Location", new_url)
+ || (NULL == (rsp->status = strdup("302 Local Redirect from Privoxy"))))
{
freez(new_url);
free_http_response(rsp);