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/udc.c src/lib/udc.c
index a67b1dc..746879d 100644
--- src/lib/udc.c
+++ src/lib/udc.c
@@ -22,30 +22,31 @@
  *    
  * The bitmap file contains time stamp and size data as well as an array with one bit
  * for each block of the file that has been fetched.  Currently the block size is 8K. */
 
 #include <sys/file.h>
 #include <sys/mman.h>
 #include "common.h"
 #include "hash.h"
 #include "obscure.h"
 #include "bits.h"
 #include "linefile.h"
 #include "portable.h"
 #include "sig.h"
 #include "net.h"
 #include "cheapcgi.h"
+#include "htmlPage.h"
 #include "udc.h"
 #include "hex.h"
 #include <dirent.h>
 #include <openssl/sha.h>
 
 /* The stdio stream we'll use to output statistics on file i/o.  Off by default. */
 FILE *udcLogStream = NULL;
 
 void udcSetLog(FILE *fp)
 /* Turn on logging of file i/o. 
  * For each UDC file two lines are written.  One line for the open, and one line for the close. 
  * The Open line just has the URL being opened.
  * The Close line has the the URL plus a bunch of counts of the number of seeks, reads, and writes
  *   for the following four files: the udc bitmap, the udc sparse data, the incoming calls
  *   to the UDC layer, and the network connection to the (possibly) remote file.
@@ -517,41 +518,59 @@
     Using HEAD with HIPPAA-compliant signed AmazonS3 URLs generates 403.
     The signed URL generated for GET cannot be used with HEAD.
     Instead call GET with byterange=0-0 in netUrlFakeHeadByGet().
     This supplies both size via Content-Range response header,
     as well as Last-Modified header which is important for caching.
     There are also sites which support byte-ranges 
     but they do not return Content-Length with HEAD.
     */
     if (status == 403 || (status==200 && !sizeString))
 	{ 
 	hashFree(&hash);
 	hash = newHash(0);
 	status = netUrlFakeHeadByGet(url, hash);
 	if (status == 206) 
 	    break;
+	if (status == 200)  // helps get more info to user
+	    break;
 	}
     if (status != 301 && status != 302 && status != 307 && status != 308)
 	return FALSE;
     ++redirectCount;
     if (redirectCount > 5)
 	{
 	warn("code %d redirects: exceeded limit of 5 redirects, %s", status, url);
 	return FALSE;
 	}
     char *newUrl = hashFindValUpperCase(hash, "Location:");
-    retInfo->ci.redirUrl = cloneString(newUrl);
+     if (!newUrl)
+	{
+	warn("code %d redirects: redirect location missing, %s", status, url);
+	return FALSE;
+	}
+
+    // path may be relative
+    if (hasProtocol(newUrl))
+	{
+        newUrl = cloneString(newUrl);
+	}
+    else
+	{
+	newUrl = expandUrlOnBase(url, newUrl);
+	}
+
+    retInfo->ci.redirUrl = newUrl;
     url = transferParamsToRedirectedUrl(url, newUrl);		
     hashFree(&hash);
     }
 
 char *sizeHeader = NULL;
 if (status == 200)
     {
     sizeHeader = "Content-Length:";
     // input pattern: Content-Length: 2738262
     }
 if (status == 206)
     {
     sizeHeader = "Content-Range:";
     // input pattern: Content-Range: bytes 0-99/2738262
     }