// File: /workspace/github_c_makefile_star2_O1/icebert[P]pblat/lib/udc.c
// Function: udcInfoViaHttp
boolean udcInfoViaHttp(char *url, struct udcRemoteFileInfo *retInfo)
/* Gets size and last modified time of URL
 * and returns status of HEAD or GET byterange 0-0. */
{
verbose(4, "checking http remote info on %s\n", url);
// URLs passed into here should not have byterange clause.
int redirectCount = 0;
struct hash *hash;
int status;
char *sizeString = NULL;
/*
 For caching, sites should support byte-range and last-modified.
 However, several groups including ENCODE have made sites that use CGIs to 
 dynamically generate hub text files such as hub.txt, genome.txt, trackDb.txt.
 Byte-range and last-modified are difficult to support for this case,
 so they do without them, effectively defeat caching. Every 5 minutes (udcTimeout),
 they get re-downloaded, even when the data has not changed.  
*/
while (TRUE)
    {
    hash = newHash(0);
    status = netUrlHead(url, hash);
    sizeString = hashFindValUpperCase(hash, "Content-Length:");
    if (status == 200 && sizeString)
	break;
    /*
    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 != 301 && status != 302)
	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);
    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
    }

sizeString = hashFindValUpperCase(hash, sizeHeader);
if (sizeString)
    {
    char *parseString = sizeString;
    if (status == 206)
	{
	parseString = strchr(sizeString, '/');
	if (!parseString)
	    {
	    warn("Header value %s is missing '/' in %s in response for url %s", 
		sizeString, sizeHeader, url);
	    return FALSE;
	    }
	++parseString; // skip past slash
	}
    if (parseString)
	{
	retInfo->size = atoll(parseString);
	}
    else
	{
	warn("Header value %s is missing or invalid in %s in response for url %s", 
	    sizeString, sizeHeader, url);
	return FALSE;
	}
    }
else
    {
    warn("Response is missing required header %s for url %s", sizeHeader, url);
    return FALSE;
    }

char *lastModString = hashFindValUpperCase(hash, "Last-Modified:");
if (lastModString == NULL)
    {
    // Date is a poor substitute!  It will always appear that the cache is stale.
    // But at least we can read files from dropbox.com.
    lastModString = hashFindValUpperCase(hash, "Date:");
    if (lastModString == NULL)
	{
	hashFree(&hash);
	errAbort("No Last-Modified: or Date: returned in header for %s, can't proceed, sorry", url);
	}
    }

struct tm tm;
time_t t;
// Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
// This will always be GMT
if (strptime(lastModString, "%a, %d %b %Y %H:%M:%S %Z", &tm) == NULL)
    { /* Handle error */;
    hashFree(&hash);
    errAbort("unable to parse last-modified string [%s]", lastModString);
    }
t = mktimeFromUtc(&tm);
if (t == -1)
    { /* Handle error */;
    hashFree(&hash);
    errAbort("mktimeFromUtc failed while converting last-modified string [%s] from UTC time", lastModString);
    }
retInfo->updateTime = t;

hashFree(&hash);
return status;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, 0x8(%rsp)
movq %rdi, %r15
leaq 0x55204(%rip), %rsi     # 0x94af0
movl $0x4, %edi
movq %r15, %rdx
xorl %eax, %eax
callq 0x4246e
xorl %edi, %edi
movl $0x1, %esi
callq 0x29160
movq %rax, (%rsp)
movq %r15, %rdi
movq %rax, %rsi
callq 0x2fbc6
movl %eax, %r13d
movq (%rsp), %rdi
leaq 0x51b6e(%rip), %r12     # 0x91492
movq %r12, %rsi
callq 0x29055
cmpl $0xc8, %r13d
sete %bpl
testq %rax, %rax
setne %al
movl $0xc8, %r14d
andb %al, %bpl
jne 0x3fa7f
movl $0x6, %r14d
movq %rsp, %rbx
leaq 0x551f4(%rip), %r12     # 0x94b50
cmpl $0xc8, %r13d
setne %cl
cmpl $0x193, %r13d           # imm = 0x193
je 0x3f976
orb %al, %cl
testb $0x1, %cl
jne 0x3f9a7
movq %rbx, %rdi
callq 0x29565
xorl %edi, %edi
movl $0x1, %esi
callq 0x29160
movq %rax, (%rsp)
movq %r15, %rdi
movq %rax, %rsi
callq 0x2fbd5
movl %eax, %r13d
cmpl $0xce, %eax
je 0x3fa79
leal -0x12f(%r13), %eax
cmpl $-0x2, %eax
jb 0x3fa55
decl %r14d
je 0x3fa5d
movq (%rsp), %rdi
leaq 0x5517b(%rip), %rsi     # 0x94b46
callq 0x29055
movq %rax, %r13
movq %rax, %rdi
callq 0x1f9f6
movq 0x8(%rsp), %rcx
movq %rax, 0x28(%rcx)
movq %r15, %rdi
movq %r13, %rsi
callq 0x3070a
movq %rax, %r15
movq %rbx, %rdi
callq 0x29565
xorl %edi, %edi
movl $0x1, %esi
callq 0x29160
movq %rax, (%rsp)
movq %r15, %rdi
movq %rax, %rsi
callq 0x2fbc6
movl %eax, %r13d
movq (%rsp), %rdi
leaq 0x51a6f(%rip), %rsi     # 0x91492
callq 0x29055
cmpl $0xc8, %r13d
sete %bpl
testq %rax, %rax
setne %al
andb %al, %bpl
cmpb $0x1, %bpl
jne 0x3f95c
leaq 0x51a45(%rip), %r12     # 0x91492
movl $0xc8, %r14d
jmp 0x3fa7f
xorl %r14d, %r14d
jmp 0x3fb9e
leaq 0x550ad(%rip), %rdi     # 0x94b11
xorl %r14d, %r14d
movl %r13d, %esi
movq %r15, %rdx
xorl %eax, %eax
callq 0x268ca
jmp 0x3fb9e
movl $0xce, %r14d
movq (%rsp), %rdi
movq %r12, %rsi
callq 0x29055
testq %rax, %rax
je 0x3fb6b
movq %rax, %rbx
testb $0x1, %bpl
jne 0x3fab9
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x6270
testq %rax, %rax
je 0x3fb84
incq %rax
movq %rax, %rbx
movq %rbx, %rdi
callq 0x6520
movq 0x8(%rsp), %rcx
movq %rax, 0x8(%rcx)
movq (%rsp), %rdi
leaq 0x550f8(%rip), %rsi     # 0x94bcd
callq 0x29055
testq %rax, %rax
jne 0x3faf8
movq (%rsp), %rdi
leaq 0x550f2(%rip), %rsi     # 0x94bdc
callq 0x29055
testq %rax, %rax
je 0x3fbb0
movq %rax, %rbx
leaq 0x5512b(%rip), %rsi     # 0x94c2d
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
callq 0x60e0
testq %rax, %rax
jne 0x3fb2d
movq %rsp, %rdi
callq 0x29565
leaq 0x55123(%rip), %rdi     # 0x94c46
movq %rbx, %rsi
xorl %eax, %eax
callq 0x26b6f
leaq 0x10(%rsp), %rdi
callq 0x24183
movq %rax, %r15
cmpq $-0x1, %rax
jne 0x3fb59
movq %rsp, %rdi
callq 0x29565
leaq 0x55121(%rip), %rdi     # 0x94c70
movq %rbx, %rsi
xorl %eax, %eax
callq 0x26b6f
movq 0x8(%rsp), %rax
movq %r15, (%rax)
movq %rsp, %rdi
callq 0x29565
jmp 0x3fb9e
leaq 0x55029(%rip), %rdi     # 0x94b9b
xorl %r14d, %r14d
movq %r12, %rsi
movq %r15, %rdx
xorl %eax, %eax
callq 0x268ca
jmp 0x3fb9e
leaq 0x54fd4(%rip), %rdi     # 0x94b5f
xorl %r14d, %r14d
movq %rbx, %rsi
movq %r12, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x268ca
movl %r14d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rsp, %rdi
callq 0x29565
leaq 0x55023(%rip), %rdi     # 0x94be2
xorl %ebx, %ebx
movq %r15, %rsi
xorl %eax, %eax
callq 0x26b6f
jmp 0x3fafb