f64df8332a2328c2fe6325dcd1cb0b9281586957
galt
  Thu Feb 10 01:55:48 2011 -0800
added alternate method for finding filesize via byterange, useful workaround for udc used against poorly configured remote apache servers
diff --git src/lib/net.c src/lib/net.c
index 54bb60c..6a72092 100644
--- src/lib/net.c
+++ src/lib/net.c
@@ -921,37 +921,37 @@
 
 
 int netOpenHttpExt(char *url, char *method, char *optionalHeader)
 /* Return a file handle that will read the url.  optionalHeader
  * may by NULL or may contain cookies and other info.  */
 {
 return netHttpConnect(url, method, "HTTP/1.0", "genome.ucsc.edu/net.c", optionalHeader);
 }
 
 static int netGetOpenHttp(char *url)
 /* Return a file handle that will read the url.  */
 {
 return netOpenHttpExt(url, "GET", NULL);
 }
 
-int netUrlHead(char *url, struct hash *hash)
+int netUrlHeadExt(char *url, char *method, struct hash *hash)
 /* Go get head and return status.  Return negative number if
  * can't get head. If hash is non-null, fill it with header
  * lines with upper cased keywords for case-insensitive lookup, 
  * including hopefully CONTENT-TYPE: . */
 {
-int sd = netOpenHttpExt(url, "HEAD", NULL);
+int sd = netOpenHttpExt(url, method, NULL);
 int status = EIO;
 if (sd >= 0)
     {
     char *line, *word;
     struct lineFile *lf = lineFileAttach(url, TRUE, sd);
 
     if (lineFileNext(lf, &line, NULL))
 	{
 	if (startsWith("HTTP/", line))
 	    {
 	    word = nextWord(&line);
 	    word = nextWord(&line);
 	    if (word != NULL && isdigit(word[0]))
 	        {
 		status = atoi(word);
@@ -963,30 +963,68 @@
 			if (word == NULL)
 			    break;
 			hashAdd(hash, strUpper(word), cloneString(skipLeadingSpaces(line)));
 			}
 		    }
 		}
 	    }
 	}
     lineFileClose(&lf);
     }
 else
     status = errno;
 return status;
 }
 
+
+int netUrlHead(char *url, struct hash *hash)
+/* Go get head and return status.  Return negative number if
+ * can't get head. If hash is non-null, fill it with header
+ * lines with upper cased keywords for case-insensitive lookup, 
+ * including hopefully CONTENT-TYPE: . */
+{
+return netUrlHeadExt(url, "HEAD", hash);
+}
+
+
+long long netUrlSizeByRangeResponse(char *url)
+/* Use byteRange as a work-around alternate method to get file size (content-length).  
+ * Return negative number if can't get. */
+{
+long long retVal = -1;
+char rangeUrl[2048];
+safef(rangeUrl, sizeof(rangeUrl), "%s;byterange=0-0", url);
+struct hash *hash = newHash(0);
+int status = netUrlHeadExt(rangeUrl, "GET", hash);
+if (status == 206)
+    { 
+    char *rangeString = hashFindValUpperCase(hash, "Content-Range:");
+    if (rangeString)
+	{
+ 	/* input pattern: Content-Range: bytes 0-99/2738262 */
+	char *slash = strchr(rangeString,'/');
+	if (slash)
+	    {
+	    retVal = atoll(slash+1);
+	    }
+	}
+    }
+hashFree(&hash);
+return retVal;
+}
+
+
 int netUrlOpenSockets(char *url, int *retCtrlSocket)
 /* Return socket descriptor (low-level file handle) for read()ing url data,
  * or -1 if error. 
  * If retCtrlSocket is non-NULL and url is FTP, set *retCtrlSocket
  * to the FTP control socket which is left open for a persistent connection.
  * close(result) (and close(*retCtrlSocket) if applicable) when done. 
  * If url is missing :// then it's just treated as a file. */
 {
 if (stringIn("://", url) == NULL)
     return open(url, O_RDONLY);
 else
     {
     if (startsWith("http://",url) || startsWith("https://",url))
 	return netGetOpenHttp(url);
     else if (startsWith("ftp://",url))