a90b80696b95a7af02251c0206a11f7e24f3e0c3
max
  Mon Jun 8 03:32:12 2015 -0700
allowing a single redirect in udc info requests, refs #12728

diff --git src/lib/udc.c src/lib/udc.c
index 2ab135c..9e3f913 100644
--- src/lib/udc.c
+++ src/lib/udc.c
@@ -378,32 +378,43 @@
     errnoAbort("udcDataViaHttpOrFtp: error reading socket");
 if (ci == NULL)
     mustCloseFd(&sd);
 else
     ci->offset += total;
 return total;
 }
 
 boolean udcInfoViaHttp(char *url, struct udcRemoteFileInfo *retInfo)
 /* Gets size and last modified time of URL
  * and returns status of HEAD GET. */
 {
 verbose(4, "checking http remote info on %s\n", url);
 struct hash *hash = newHash(0);
 int status = netUrlHead(url, hash);
+
+// dropbox always redirects once
+if (status == 302 && hashFindVal(hash, "LOCATION:"))
+    {
+    char *newUrl = cloneString((char *)hashFindVal(hash, "LOCATION:"));
+    freeHashAndVals(&hash);
+    hash = newHash(0);
+    status = netUrlHead(newUrl, hash);
+    }
+
 if (status != 200) // && status != 302 && status != 301)
     return FALSE;
+
 char *sizeString = hashFindValUpperCase(hash, "Content-Length:");
 if (sizeString == NULL)
     {
     /* try to get remote file size by an alternate method */
     long long retSize = netUrlSizeByRangeResponse(url);
     if (retSize < 0)
 	{
     	hashFree(&hash);
 	errAbort("No Content-Length: returned in header for %s, can't proceed, sorry", url);
 	}
     retInfo->size = retSize;
     }
 else
     {
     retInfo->size = atoll(sizeString);
@@ -970,31 +981,31 @@
 
         file->fdSparse = mustOpenFd(file->sparseFileName, O_RDWR);
         }
 
     }
 freeMem(afterProtocol);
 return file;
 }
 
 struct udcFile *udcFileOpen(char *url, char *cacheDir)
 /* Open up a cached file.  cacheDir may be null in which case udcDefaultDir() will be
  * used.  Abort if file doesn't exist. */
 {
 struct udcFile *udcFile = udcFileMayOpen(url, cacheDir);
 if (udcFile == NULL)
-    errAbort("Couldn't open %s", url);
+    errAbort("UDC Couldn't open %s", url);
 return udcFile;
 }
 
 
 struct slName *udcFileCacheFiles(char *url, char *cacheDir)
 /* Return low-level list of files used in cache. */
 {
 char *protocol, *afterProtocol, *colon;
 struct udcFile *file;
 udcParseUrl(url, &protocol, &afterProtocol, &colon);
 if (colon == NULL)
     return NULL;
 AllocVar(file);
 udcPathAndFileNames(file, cacheDir, protocol, afterProtocol);
 struct slName *list = NULL;