Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.331
diff -u -r1.331 curl.h
--- include/curl/curl.h	15 Oct 2007 18:32:01 -0000	1.331
+++ include/curl/curl.h	19 Oct 2007 10:51:23 -0000
@@ -427,6 +427,19 @@
   CURL_LAST /* never use! */
 } CURLcode;
 
+typedef CURLcode(*curl_url_check_callback)(
+    char *,     /* original URL */
+    char **,    /* fixed URL, set to original if it's ok */
+    void *      /* whatever the user passed */
+);
+
+typedef CURLcode(*curl_cookie_check_callback)(
+    char *,     /* original Set-Cookie header */
+    char **,    /* Fixed cookie, set to original
+               if nothing should be changed. */
+    void *      /* whatever the user passed */
+);
+
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
@@ -1159,6 +1172,22 @@
   /* POST volatile input fields. */
   CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
 
+  /* Function which is called before given url is used.
+     Designed to have an ability to change current url. The function
+     must be matching curl_url_check_callback proto. */
+  CINIT(URLCHECKFUNCTION, FUNCTIONPOINT, 10161),
+  /* Pointer to whatever data, which will be passed as a third
+     argument to the function passed with url_check_callback. */
+  CINIT(URLCHECKDATA, OBJECTPOINT, 10162),
+
+  /* Function which is called before given cookie is added.
+     Designed to have an ability to change current cookie. The function
+     must be matching curl_cookie_check_callback proto. */
+  CINIT(COOKIECHECKFUNCTION, FUNCTIONPOINT, 10163),
+  /* Pointer to whatever data, which will be passed as a third
+   * argument to the fnction passed with cookie_check_callback. */
+  CINIT(COOKIECHECKDATA, OBJECTPOINT, 10164),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
Index: lib/transfer.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/transfer.c,v
retrieving revision 1.370
diff -u -r1.370 transfer.c
--- lib/transfer.c	15 Oct 2007 18:32:01 -0000	1.370
+++ lib/transfer.c	19 Oct 2007 10:51:26 -0000
@@ -1049,16 +1049,35 @@
 #if !defined(CURL_DISABLE_COOKIES)
             else if(data->cookies &&
                     checkprefix("Set-Cookie:", k->p)) {
+              char * fixed_cookie = NULL;
+              if (data->set.check_cookie_func) {
+                CURLcode code = data->set.check_cookie_func(
+                  k->p, &fixed_cookie, data->set.check_cookie_data);
+                if (code != CURLE_OK) {
+                  /*
+                   * FIXME: ensure we don't have to
+                   * make any clean-ups here
+                   */
+                  return code;
+                }
+                assert(fixed_cookie != NULL);
+                assert(checkprefix("Set-Cookie:", fixed_cookie));
+              } else {
+                fixed_cookie = k->p;
+              }
               Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                               CURL_LOCK_ACCESS_SINGLE);
               Curl_cookie_add(data,
-                              data->cookies, TRUE, k->p+11,
+                              data->cookies, TRUE, fixed_cookie+11,
                               /* If there is a custom-set Host: name, use it
                                  here, or else use real peer host name. */
                               conn->allocptr.cookiehost?
                               conn->allocptr.cookiehost:conn->host.name,
                               data->reqdata.path);
               Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+              if (fixed_cookie != k->p) {
+                  free(fixed_cookie);
+              }
             }
 #endif
             else if(checkprefix("Last-Modified:", k->p) &&
@@ -2046,6 +2065,23 @@
     data->set.followlocation++; /* count location-followers */
   }
 
+  if (data->set.check_url_func) {
+    char *fixed_url = NULL;
+    CURLcode code = data->set.check_url_func(
+      newurl, &fixed_url, data->set.check_url_data);
+    if (code != CURLE_OK) {
+      return code;
+    }
+    assert(fixed_url != NULL);
+    if (fixed_url != newurl) {
+      if (data->change.url_alloc) {
+        free(newurl);
+      }
+      newurl = fixed_url;
+      data->change.url_alloc = TRUE;
+    }
+  }
+
   if(data->set.http_auto_referer) {
     /* We are asked to automatically set the previous URL as the
        referer when we get the next URL. We pick the ->url field,
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.664
diff -u -r1.664 url.c
--- lib/url.c	18 Oct 2007 10:54:49 -0000	1.664
+++ lib/url.c	19 Oct 2007 10:51:34 -0000
@@ -676,6 +676,13 @@
     data->set.in  = stdin;  /* default input from stdin */
     data->set.err  = stderr;  /* default stderr to stderr */
 
+    /* by default don't perform any url checking. */
+    data->set.check_url_func = NULL;
+    data->set.check_url_data = NULL;
+    /* and cookie checking */
+    data->set.check_cookie_func = NULL;
+    data->set.check_cookie_data = NULL;
+
     /* use fwrite as default function to store output */
     data->set.fwrite_func = (curl_write_callback)fwrite;
 
@@ -2038,6 +2045,34 @@
     data->set.new_directory_perms = va_arg(param, long);
     break;
 
+  case CURLOPT_URLCHECKFUNCTION:
+    /*
+     * Custom pointer to pass the url check callback function.
+     */
+    data->set.check_url_func = (void *)va_arg(param, void *);
+    break;
+
+  case CURLOPT_URLCHECKDATA:
+    /*
+     * Set user data to url check function.
+     */
+    data->set.check_url_data = (void *)va_arg(param, void *);
+    break;
+
+  case CURLOPT_COOKIECHECKFUNCTION:
+    /*
+     * Custom pointer to pass the url check callback function.
+     */
+    data->set.check_cookie_func = (void *)va_arg(param, void *);
+    break;
+
+  case CURLOPT_COOKIECHECKDATA:
+    /*
+     * Set user data to url check function.
+     */
+    data->set.check_cookie_data = (void *)va_arg(param, void *);
+    break;
+
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_FAILED_INIT; /* correct this */
@@ -3442,6 +3477,23 @@
   if(!data->change.url)
     return CURLE_URL_MALFORMAT;
 
+  if (data->set.check_url_func) {
+    char *fixed_url = NULL;
+    CURLcode code = data->set.check_url_func(
+      data->change.url, &fixed_url, data->set.check_url_data);
+    if (code != CURLE_OK) {
+      return code;
+    }
+    assert(fixed_url != NULL);
+    if (fixed_url != data->change.url) {
+      if (data->change.url_alloc) {
+        free(data->change.url);
+      }
+      data->change.url = fixed_url;
+      data->change.url_alloc = TRUE;
+    }
+  }
+
   /* First, split up the current URL in parts so that we can use the
      parts for checking against the already present connections. In order
      to not have to modify everything at once, we allocate a temporary
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.352
diff -u -r1.352 urldata.h
--- lib/urldata.h	15 Oct 2007 18:32:01 -0000	1.352
+++ lib/urldata.h	19 Oct 2007 10:51:35 -0000
@@ -1353,6 +1353,16 @@
   /* function to convert from UTF-8 encoding: */
   curl_conv_callback convfromutf8;
 
+  /* function to check urls before they are actually used */
+  curl_url_check_callback check_url_func;
+  /* user defined data passed together with check_url_func */
+  void *check_url_data;
+
+  /* function to check cookies before they are added */
+  curl_cookie_check_callback check_cookie_func;
+  /* user defined data passed together with check_cookie_func */
+  void *check_cookie_data;
+
   void *progress_client; /* pointer to pass to the progress callback */
   void *ioctl_client;   /* pointer to pass to the ioctl callback */
   long timeout;         /* in milliseconds, 0 means no timeout */

