22d2b680a73ee00f4c37917f6e16ead11db556ef
galt
  Tue Sep 1 02:04:38 2020 -0700
Adding support for relative URL in redirect location in net.c and udc.c. refs#26138

diff --git src/lib/net.c src/lib/net.c
index 5a3ba76..f57e054 100644
--- src/lib/net.c
+++ src/lib/net.c
@@ -3,30 +3,31 @@
  * This file is copyright 2002 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 #include "common.h"
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/time.h>
 #include <pthread.h>
 #include "errAbort.h"
 #include "hash.h"
 #include "net.h"
 #include "linefile.h"
 #include "base64.h"
 #include "cheapcgi.h"
+#include "htmlPage.h"
 #include "https.h"
 #include "sqlNum.h"
 #include "obscure.h"
 #include "errCatch.h"
 
 /* Brought errno in to get more useful error messages */
 extern int errno;
 
 static int netStreamSocketFromAddrInfo(struct addrinfo *address)
 /* Create a socket from addrinfo structure.  
  * Complain and return something negative if can't. */
 {
 int sd = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
 if (sd < 0)
     warn("Couldn't make %s socket.", familyToString(address->ai_family));
@@ -1534,31 +1535,31 @@
 	*rangeStart = atoll(y); 
 	if (z[0] != '\0')
 	    *rangeEnd = atoll(z);
 	}    
     }
 
 }
 
 
 boolean netSkipHttpHeaderLinesWithRedirect(int sd, char *url, char **redirectedUrl)
 /* Skip http header lines. Return FALSE if there's a problem.
  * The input is a standard sd or fd descriptor.
  * This is meant to be able work even with a re-passable stream handle,
  * e.g. can pass it to the pipes routines, which means we can't
  * attach a linefile since filling its buffer reads in more than just the http header.
- * Handles 300, 301, 302, 303, 307, 308 http redirects by setting *redirectedUrl to
+ * Handles 301, 302, 307, 308 http redirects by setting *redirectedUrl to
  * the new location. */
 {
 char buf[8192];
 char *line = buf;
 int maxbuf = sizeof(buf);
 int i=0;
 char c = ' ';
 int nread = 0;
 char *sep = NULL;
 char *headerName = NULL;
 char *headerVal = NULL;
 boolean redirect = FALSE;
 boolean byteRangeUsed = (strstr(url,";byterange=") != NULL);
 ssize_t byteRangeStart = -1;
 ssize_t byteRangeEnd = -1;
@@ -1781,47 +1782,58 @@
 	    *redirectedSd = -1;
 	    *redirectedUrl = NULL;
 	    }
 	return TRUE;
 	}
     close(sd);
     if (success)
 	{
 	/* we have a new url to try */
 	++redirectCount;
 	if (redirectCount > 5)
 	    {
 	    warn("code 30x redirects: exceeded limit of 5 redirects, %s", newUrl);
 	    success = FALSE;
 	    }
-	else if (!startsWith("http://",newUrl) 
+	else 
+	    {
+	    // path may be relative
+	    if (!hasProtocol(newUrl))
+		{
+		char *newUrl2 = expandUrlOnBase(url, newUrl);
+		freeMem(newUrl);
+		newUrl = newUrl2;
+		}
+	    if (!startsWith("http://",newUrl) 
               && !startsWith("https://",newUrl))
 		{
 		warn("redirected to non-http(s): %s", newUrl);
 		success = FALSE;
 		}
 	    else
 		{
+		// transfer password and byteranges if any
 		newUrl = transferParamsToRedirectedUrl(url, newUrl);
 		sd = netUrlOpen(newUrl);
 		if (sd < 0)
 		    {
 		    warn("Couldn't open %s", newUrl);
 		    success = FALSE;
 		    }
 		}
 	    }
+	}
     if (redirectCount > 1)
 	freeMem(url);
     if (!success)
 	{  /* failure after 0 to 5 redirects */
 	if (redirectCount > 0)
 	    freeMem(newUrl);
 	return FALSE;
 	}
     url = newUrl;
     }
 return FALSE;
 }
 
 struct lineFile *netLineFileMayOpen(char *url)
 /* Return a lineFile attached to url. http skips header.