http: Split HTTP redirect and cookie clear logic into helper functions
authorKevin Cernekee <cernekee@gmail.com>
Sat, 27 Oct 2012 17:55:27 +0000 (10:55 -0700)
committerKevin Cernekee <cernekee@gmail.com>
Sat, 27 Oct 2012 20:10:00 +0000 (13:10 -0700)
This makes openconnect_obtain_cookie() shorter, and easier to follow.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
http.c

diff --git a/http.c b/http.c
index 38fc9a5..1df6488 100644 (file)
--- a/http.c
+++ b/http.c
@@ -591,6 +591,104 @@ int internal_parse_url(char *url, char **res_proto, char **res_host,
        return 0;
 }
 
+static void clear_cookies(struct openconnect_info *vpninfo)
+{
+       struct vpn_option *opt, *next;
+
+       for (opt = vpninfo->cookies; opt; opt = next) {
+               next = opt->next;
+
+               free(opt->option);
+               free(opt->value);
+               free(opt);
+       }
+       vpninfo->cookies = NULL;
+}
+
+/* Return value:
+ *  < 0, on error
+ *  = 0, on success (go ahead and retry with the latest vpninfo->{hostname,urlpath,port,...})
+ */
+static int handle_redirect(struct openconnect_info *vpninfo)
+{
+       if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
+               /* New host. Tear down the existing connection and make a new one */
+               char *host;
+               int port;
+               int ret;
+
+               free(vpninfo->urlpath);
+               vpninfo->urlpath = NULL;
+
+               ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
+               if (ret) {
+                       vpn_progress(vpninfo, PRG_ERR,
+                                    _("Failed to parse redirected URL '%s': %s\n"),
+                                    vpninfo->redirect_url, strerror(-ret));
+                       free(vpninfo->redirect_url);
+                       vpninfo->redirect_url = NULL;
+                       return ret;
+               }
+
+               if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
+                       free(vpninfo->hostname);
+                       vpninfo->hostname = host;
+                       vpninfo->port = port;
+
+                       /* Kill the existing connection, and a new one will happen */
+                       free(vpninfo->peer_addr);
+                       vpninfo->peer_addr = NULL;
+                       openconnect_close_https(vpninfo, 0);
+                       clear_cookies(vpninfo);
+               } else
+                       free(host);
+
+               free(vpninfo->redirect_url);
+               vpninfo->redirect_url = NULL;
+
+               return 0;
+       } else if (strstr(vpninfo->redirect_url, "://")) {
+               vpn_progress(vpninfo, PRG_ERR,
+                            _("Cannot follow redirection to non-https URL '%s'\n"),
+                            vpninfo->redirect_url);
+               free(vpninfo->redirect_url);
+               vpninfo->redirect_url = NULL;
+               return -EINVAL;
+       } else if (vpninfo->redirect_url[0] == '/') {
+               /* Absolute redirect within same host */
+               free(vpninfo->urlpath);
+               vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
+               free(vpninfo->redirect_url);
+               vpninfo->redirect_url = NULL;
+               return 0;
+       } else {
+               char *lastslash = NULL;
+               if (vpninfo->urlpath)
+                       lastslash = strrchr(vpninfo->urlpath, '/');
+               if (!lastslash) {
+                       free(vpninfo->urlpath);
+                       vpninfo->urlpath = vpninfo->redirect_url;
+                       vpninfo->redirect_url = NULL;
+               } else {
+                       char *oldurl = vpninfo->urlpath;
+                       *lastslash = 0;
+                       vpninfo->urlpath = NULL;
+                       if (asprintf(&vpninfo->urlpath, "%s/%s",
+                                    oldurl, vpninfo->redirect_url) == -1) {
+                               int err = -errno;
+                               vpn_progress(vpninfo, PRG_ERR,
+                                            _("Allocating new path for relative redirect failed: %s\n"),
+                                            strerror(-err));
+                               return err;
+                       }
+                       free(oldurl);
+                       free(vpninfo->redirect_url);
+                       vpninfo->redirect_url = NULL;
+               }
+               return 0;
+       }
+}
+
 /* Return value:
  *  < 0, on error
  *  > 0, no cookie (user cancel)
@@ -598,7 +696,7 @@ int internal_parse_url(char *url, char **res_proto, char **res_host,
  */
 int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
 {
-       struct vpn_option *opt, *next;
+       struct vpn_option *opt;
        char buf[MAX_BUF_LEN];
        char *form_buf = NULL;
        int result, buflen;
@@ -676,92 +774,11 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
 
        if (result != 200 && vpninfo->redirect_url) {
        redirect:
-               if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
-                       /* New host. Tear down the existing connection and make a new one */
-                       char *host;
-                       int port;
-                       int ret;
-
-                       free(vpninfo->urlpath);
-                       vpninfo->urlpath = NULL;
-
-                       ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
-                       if (ret) {
-                               vpn_progress(vpninfo, PRG_ERR,
-                                            _("Failed to parse redirected URL '%s': %s\n"),
-                                            vpninfo->redirect_url, strerror(-ret));
-                               free(vpninfo->redirect_url);
-                               vpninfo->redirect_url = NULL;
-                               free(form_buf);
-                               return ret;
-                       }
-
-                       if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
-                               free(vpninfo->hostname);
-                               vpninfo->hostname = host;
-                               vpninfo->port = port;
-
-                               /* Kill the existing connection, and a new one will happen */
-                               free(vpninfo->peer_addr);
-                               vpninfo->peer_addr = NULL;
-                               openconnect_close_https(vpninfo, 0);
-
-                               for (opt = vpninfo->cookies; opt; opt = next) {
-                                       next = opt->next;
-
-                                       free(opt->option);
-                                       free(opt->value);
-                                       free(opt);
-                               }
-                               vpninfo->cookies = NULL;
-                       } else
-                               free(host);
-
-                       free(vpninfo->redirect_url);
-                       vpninfo->redirect_url = NULL;
-
+               result = handle_redirect(vpninfo);
+               if (result == 0)
                        goto retry;
-               } else if (strstr(vpninfo->redirect_url, "://")) {
-                       vpn_progress(vpninfo, PRG_ERR,
-                                    _("Cannot follow redirection to non-https URL '%s'\n"),
-                                    vpninfo->redirect_url);
-                       free(vpninfo->redirect_url);
-                       vpninfo->redirect_url = NULL;
-                       free(form_buf);
-                       return -EINVAL;
-               } else if (vpninfo->redirect_url[0] == '/') {
-                       /* Absolute redirect within same host */
-                       free(vpninfo->urlpath);
-                       vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
-                       free(vpninfo->redirect_url);
-                       vpninfo->redirect_url = NULL;
-                       goto retry;
-               } else {
-                       char *lastslash = NULL;
-                       if (vpninfo->urlpath)
-                               lastslash = strrchr(vpninfo->urlpath, '/');
-                       if (!lastslash) {
-                               free(vpninfo->urlpath);
-                               vpninfo->urlpath = vpninfo->redirect_url;
-                               vpninfo->redirect_url = NULL;
-                       } else {
-                               char *oldurl = vpninfo->urlpath;
-                               *lastslash = 0;
-                               vpninfo->urlpath = NULL;
-                               if (asprintf(&vpninfo->urlpath, "%s/%s",
-                                            oldurl, vpninfo->redirect_url) == -1) {
-                                       int err = -errno;
-                                       vpn_progress(vpninfo, PRG_ERR,
-                                                    _("Allocating new path for relative redirect failed: %s\n"),
-                                                    strerror(-err));
-                                       return err;
-                               }
-                               free(oldurl);
-                               free(vpninfo->redirect_url);
-                               vpninfo->redirect_url = NULL;
-                       }
-                       goto retry;
-               }
+               free(form_buf);
+               return result;
        }
        if (!form_buf || result != 200) {
                vpn_progress(vpninfo, PRG_ERR,