mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1470 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1470 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#define __http_init
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Creates global.__HttpClient
 | 
						|
// real __http_init()
 | 
						|
 | 
						|
global.__HttpClient = object_add();
 | 
						|
object_set_persistent(global.__HttpClient, true);
 | 
						|
 | 
						|
#define __http_split
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// real __http_split(string text, delimeter delimeter, real limit)
 | 
						|
// Splits string into items
 | 
						|
 | 
						|
// text - string comma-separated values
 | 
						|
// delimeter - delimeter to split by
 | 
						|
// limit  if non-zero, maximum times to split text
 | 
						|
// When limited, the remaining text will be left as the last item.
 | 
						|
// E.g. splitting "1,2,3,4,5" with delimeter "," and limit 2 yields this list:
 | 
						|
// "1", "2", "3,4,5"
 | 
						|
 | 
						|
// return value - ds_list containing strings of values
 | 
						|
 | 
						|
var text, delimeter, limit;
 | 
						|
text = argument0;
 | 
						|
delimeter = argument1;
 | 
						|
limit = argument2;
 | 
						|
 | 
						|
var list, count;
 | 
						|
list = ds_list_create();
 | 
						|
count = 0;
 | 
						|
 | 
						|
while (string_pos(delimeter, text) != 0)
 | 
						|
{
 | 
						|
    ds_list_add(list, string_copy(text, 1, string_pos(delimeter,text) - 1));
 | 
						|
    text = string_copy(text, string_pos(delimeter, text) + string_length(delimeter), string_length(text) - string_pos(delimeter, text));
 | 
						|
 | 
						|
    count += 1;
 | 
						|
    if (limit and count == limit)
 | 
						|
        break;
 | 
						|
}
 | 
						|
ds_list_add(list, text);
 | 
						|
 | 
						|
return list;
 | 
						|
 | 
						|
#define __http_parse_url
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Parses a URL into its components
 | 
						|
// real __http_parse_url(string url)
 | 
						|
 | 
						|
// Return value is a ds_map containing keys for the different URL parts: (or -1 on failure)
 | 
						|
// "url" - the URL which was passed in
 | 
						|
// "scheme" - the URL scheme (e.g. "http")
 | 
						|
// "host" - the hostname (e.g. "example.com" or "127.0.0.1")
 | 
						|
// "port" - the port (e.g. 8000) - this is a real, unlike the others
 | 
						|
// "abs_path" - the absolute path (e.g. "/" or "/index.html")
 | 
						|
// "query" - the query string (e.g. "a=b&c=3")
 | 
						|
// Parts which are not included will not be in the map
 | 
						|
// e.g. http://example.com will not have the "port", "path" or "query" keys
 | 
						|
 | 
						|
// This will *only* work properly for URLs of format:
 | 
						|
// scheme ":" "//" host [ ":" port ] [ abs_path [ "?" query ]]"
 | 
						|
// where [] denotes an optional component
 | 
						|
// file: URLs will *not* work as they lack the authority (host:port) component
 | 
						|
// It will not work correctly for IPv6 host values
 | 
						|
 | 
						|
var url;
 | 
						|
url = argument0;
 | 
						|
 | 
						|
var map;
 | 
						|
map = ds_map_create();
 | 
						|
ds_map_add(map, 'url', url);
 | 
						|
 | 
						|
// before scheme
 | 
						|
var colonPos;
 | 
						|
// Find colon for end of scheme
 | 
						|
colonPos = string_pos(':', url);
 | 
						|
// No colon - bad URL
 | 
						|
if (colonPos == 0)
 | 
						|
    return -1;
 | 
						|
ds_map_add(map, 'scheme', string_copy(url, 1, colonPos - 1));
 | 
						|
url = string_copy(url, colonPos + 1, string_length(url) - colonPos);
 | 
						|
 | 
						|
// before double slash
 | 
						|
// remove slashes (yes this will screw up file:// but who cares)
 | 
						|
while (string_char_at(url, 1) == '/')
 | 
						|
    url = string_copy(url, 2, string_length(url) - 1);
 | 
						|
 | 
						|
// before hostname
 | 
						|
var slashPos, colonPos;
 | 
						|
// Find slash for beginning of path
 | 
						|
slashPos = string_pos('/', url);
 | 
						|
// No slash ahead - http://host format with no ending slash
 | 
						|
if (slashPos == 0)
 | 
						|
{
 | 
						|
    // Find : for beginning of port
 | 
						|
    colonPos = string_pos(':', url);
 | 
						|
}
 | 
						|
else
 | 
						|
{
 | 
						|
    // Find : for beginning of port prior to /
 | 
						|
    colonPos = string_pos(':', string_copy(url, 1, slashPos - 1));
 | 
						|
}
 | 
						|
// No colon - no port
 | 
						|
if (colonPos == 0)
 | 
						|
{
 | 
						|
    // There was no slash
 | 
						|
    if (slashPos == 0)
 | 
						|
    {
 | 
						|
        ds_map_add(map, 'host', url);
 | 
						|
        return map;
 | 
						|
    }
 | 
						|
    // There was a slash
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ds_map_add(map, 'host', string_copy(url, 1, slashPos - 1));
 | 
						|
        url = string_copy(url, slashPos, string_length(url) - slashPos + 1);
 | 
						|
    }
 | 
						|
}
 | 
						|
// There's a colon - port specified
 | 
						|
else
 | 
						|
{
 | 
						|
    // There was no slash
 | 
						|
    if (slashPos == 0)
 | 
						|
    {
 | 
						|
        ds_map_add(map, 'host', string_copy(url, 1, colonPos - 1));
 | 
						|
        ds_map_add(map, 'port', real(string_copy(url, colonPos + 1, string_length(url) - colonPos)));
 | 
						|
        return map;
 | 
						|
    }
 | 
						|
    // There was a slash
 | 
						|
    else
 | 
						|
    {
 | 
						|
        ds_map_add(map, 'host', string_copy(url, 1, colonPos - 1));
 | 
						|
        url = string_copy(url, colonPos + 1, string_length(url) - colonPos);
 | 
						|
        slashPos = string_pos('/', url);
 | 
						|
        ds_map_add(map, 'port', real(string_copy(url, 1, slashPos - 1)));
 | 
						|
        url = string_copy(url, slashPos, string_length(url) - slashPos + 1); 
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// before path
 | 
						|
var queryPos;
 | 
						|
queryPos = string_pos('?', url);
 | 
						|
// There's no ? - no query
 | 
						|
if (queryPos == 0)
 | 
						|
{
 | 
						|
    ds_map_add(map, 'abs_path', url);
 | 
						|
    return map;
 | 
						|
}
 | 
						|
else
 | 
						|
{
 | 
						|
    ds_map_add(map, 'abs_path', string_copy(url, 1, queryPos - 1));
 | 
						|
    ds_map_add(map, 'query', string_copy(url, queryPos + 1, string_length(url) - queryPos));
 | 
						|
    return map;
 | 
						|
}
 | 
						|
 | 
						|
// Return -1 upon unlikely error
 | 
						|
ds_map_destroy(map);
 | 
						|
return -1;
 | 
						|
 | 
						|
#define __http_resolve_url
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Takes a base URL and a URL reference and applies it to the base URL
 | 
						|
// Returns resulting absolute URL
 | 
						|
// string __http_resolve_url(string baseUrl, string refUrl)
 | 
						|
 | 
						|
// Return value is a string containing the new absolute URL, or "" on failure
 | 
						|
 | 
						|
// Works only for restricted URL syntax as understood by by http_resolve_url
 | 
						|
// The sole restriction of which is that only scheme://authority/path URLs work
 | 
						|
// This notably excludes file: URLs which lack the authority component
 | 
						|
 | 
						|
// As described by RFC3986:
 | 
						|
//      URI-reference = URI / relative-ref
 | 
						|
//      relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
 | 
						|
//      relative-part = "//" authority path-abempty
 | 
						|
//                    / path-absolute
 | 
						|
//                    / path-noscheme
 | 
						|
//                    / path-empty
 | 
						|
// However http_resolve_url does *not* deal with fragments
 | 
						|
 | 
						|
// Algorithm based on that of section 5.2.2 of RFC 3986
 | 
						|
 | 
						|
var baseUrl, refUrl;
 | 
						|
baseUrl = argument0;
 | 
						|
refUrl = argument1;
 | 
						|
 | 
						|
// Parse base URL
 | 
						|
var urlParts;
 | 
						|
urlParts = __http_parse_url(baseUrl);
 | 
						|
if (urlParts == -1)
 | 
						|
    return '';
 | 
						|
 | 
						|
// Try to parse reference URL
 | 
						|
var refUrlParts, canParseRefUrl;
 | 
						|
refUrlParts = __http_parse_url(refUrl);
 | 
						|
canParseRefUrl = (refUrlParts != -1);
 | 
						|
if (refUrlParts != -1)
 | 
						|
    ds_map_destroy(refUrlParts);
 | 
						|
 | 
						|
var result;
 | 
						|
result = '';
 | 
						|
 | 
						|
// Parsing of reference URL succeeded - it's absolute and we're done
 | 
						|
if (canParseRefUrl)
 | 
						|
{
 | 
						|
    result = refUrl;
 | 
						|
}
 | 
						|
// Begins with '//' - scheme-relative URL
 | 
						|
else if (string_copy(refUrl, 1, 2) == '//' and string_length(refUrl) > 2)
 | 
						|
{
 | 
						|
    result = ds_map_find_value(urlParts, 'scheme') + ':' + refUrl;
 | 
						|
}
 | 
						|
// Is or begins with '/' - absolute path relative URL
 | 
						|
else if (((string_char_at(refUrl, 1) == '/' and string_length(refUrl) > 1) or refUrl == '/')
 | 
						|
// Doesn't begin with ':' and is not blank - relative path relative URL
 | 
						|
    or (string_char_at(refUrl, 1) != ':' and string_length(refUrl) > 0)) 
 | 
						|
{
 | 
						|
    // Find '?' for query
 | 
						|
    var queryPos;
 | 
						|
    queryPos = string_pos('?', refUrl);
 | 
						|
    // No query
 | 
						|
    if (queryPos == 0)
 | 
						|
    {
 | 
						|
        refUrl = __http_resolve_path(ds_map_find_value(urlParts, 'abs_path'), refUrl);
 | 
						|
        ds_map_replace(urlParts, 'abs_path', refUrl);
 | 
						|
        if (ds_map_exists(urlParts, 'query'))
 | 
						|
            ds_map_delete(urlParts, 'query');
 | 
						|
    }
 | 
						|
    // Query exists, split
 | 
						|
    else
 | 
						|
    {
 | 
						|
        var path, query;
 | 
						|
        path = string_copy(refUrl, 1, queryPos - 1);
 | 
						|
        query = string_copy(refUrl, queryPos + 1, string_length(relUrl) - queryPos);
 | 
						|
        path = __http_resolve_path(ds_map_find_value(urlParts, 'abs_path'), path);
 | 
						|
        ds_map_replace(urlParts, 'abs_path', path);
 | 
						|
        if (ds_map_exists(urlParts, 'query'))
 | 
						|
            ds_map_replace(urlParts, 'query', query);
 | 
						|
        else
 | 
						|
            ds_map_add(urlParts, 'query', query);
 | 
						|
    }
 | 
						|
    result = __http_construct_url(urlParts);
 | 
						|
}
 | 
						|
 | 
						|
ds_map_destroy(urlParts);
 | 
						|
return result;
 | 
						|
 | 
						|
#define __http_resolve_path
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Takes a base path and a path reference and applies it to the base path
 | 
						|
// Returns resulting absolute path
 | 
						|
// string __http_resolve_path(string basePath, string refPath)
 | 
						|
 | 
						|
// Return value is a string containing the new absolute path
 | 
						|
 | 
						|
// Deals with UNIX-style / paths, not Windows-style \ paths
 | 
						|
// Can be used to clean up .. and . in non-absolute paths too ('' as basePath)
 | 
						|
 | 
						|
var basePath, refPath;
 | 
						|
basePath = argument0;
 | 
						|
refPath = argument1;
 | 
						|
 | 
						|
// refPath begins with '/' (is absolute), we can ignore all of basePath
 | 
						|
if (string_char_at(refPath, 1) == '/')
 | 
						|
{
 | 
						|
    basePath = refPath;
 | 
						|
    refPath = '';
 | 
						|
}
 | 
						|
 | 
						|
var parts, refParts;
 | 
						|
parts = __http_split(basePath, '/', 0);
 | 
						|
refParts = __http_split(refPath, '/', 0);
 | 
						|
 | 
						|
if (refPath != '')
 | 
						|
{
 | 
						|
    // Find last part of base path
 | 
						|
    var lastPart;
 | 
						|
    lastPart = ds_list_find_value(parts, ds_list_size(parts) - 1);
 | 
						|
 | 
						|
    // If it's not blank (points to a file), remove it
 | 
						|
    if (lastPart != '')
 | 
						|
    {
 | 
						|
        ds_list_delete(parts, ds_list_size(parts) - 1);
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Concatenate refParts to end of parts
 | 
						|
    var i;
 | 
						|
    for (i = 0; i < ds_list_size(refParts); i += 1)
 | 
						|
        ds_list_add(parts, ds_list_find_value(refParts, i));
 | 
						|
}
 | 
						|
 | 
						|
// We now don't need refParts any more
 | 
						|
ds_list_destroy(refParts);
 | 
						|
 | 
						|
// Deal with '..' and '.'
 | 
						|
for (i = 0; i < ds_list_size(parts); i += 1)
 | 
						|
{
 | 
						|
    var part;
 | 
						|
    part = ds_list_find_value(parts, i);
 | 
						|
 | 
						|
    if (part == '.')
 | 
						|
    {
 | 
						|
        if (i == 1 or i == ds_list_size(parts) - 1)
 | 
						|
            ds_list_replace(parts, i, '');
 | 
						|
        else
 | 
						|
            ds_list_delete(parts, i);
 | 
						|
        i -= 1;
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
    else if (part == '..')
 | 
						|
    {
 | 
						|
        if (i > 1)
 | 
						|
        {
 | 
						|
            ds_list_delete(parts, i - 1);
 | 
						|
            ds_list_delete(part, i);
 | 
						|
            i -= 2;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            ds_list_replace(parts, i, '');
 | 
						|
            i -= 1;
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
    else if (part == '' and i != 0 and i != ds_list_size(parts) - 1)
 | 
						|
    {
 | 
						|
        ds_list_delete(parts, i);
 | 
						|
        i -= 1;
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// Reconstruct path from parts
 | 
						|
var path;
 | 
						|
path = '';
 | 
						|
for (i = 0; i < ds_list_size(parts); i += 1)
 | 
						|
{
 | 
						|
    if (i != 0)
 | 
						|
        path += '/';
 | 
						|
    path += ds_list_find_value(parts, i);
 | 
						|
}
 | 
						|
 | 
						|
ds_map_destroy(parts);
 | 
						|
return path;
 | 
						|
 | 
						|
#define __http_parse_hex
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Takes a lowercase hexadecimal string and returns its integer value
 | 
						|
// real __http_parse_hex(string hexString)
 | 
						|
 | 
						|
// Return value is the whole number value (or -1 if invalid)
 | 
						|
// Only works for whole numbers (non-fractional numbers >= 0) and lowercase hex
 | 
						|
 | 
						|
var hexString;
 | 
						|
hexString = argument0;
 | 
						|
 | 
						|
var result, hexValues;
 | 
						|
result = 0;
 | 
						|
hexValues = "0123456789abcdef";
 | 
						|
 | 
						|
var i;
 | 
						|
for (i = 1; i <= string_length(hexString); i += 1) {
 | 
						|
    result *= 16;
 | 
						|
    var digit;
 | 
						|
    digit = string_pos(string_char_at(hexString, i), hexValues) - 1;
 | 
						|
    if (digit == -1)
 | 
						|
        return -1;
 | 
						|
    result += digit;
 | 
						|
}
 | 
						|
 | 
						|
return result;
 | 
						|
 | 
						|
#define __http_construct_url
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Constructs an URL from its components (as http_parse_url would return)
 | 
						|
// string __http_construct_url(real parts)
 | 
						|
 | 
						|
// Return value is the string of the constructed URL
 | 
						|
// Keys of parts map:
 | 
						|
// "scheme" - the URL scheme (e.g. "http")
 | 
						|
// "host" - the hostname (e.g. "example.com" or "127.0.0.1")
 | 
						|
// "port" - the port (e.g. 8000) - this is a real, unlike the others
 | 
						|
// "abs_path" - the absolute path (e.g. "/" or "/index.html")
 | 
						|
// "query" - the query string (e.g. "a=b&c=3")
 | 
						|
// Parts which are omitted will be omitted in the URL
 | 
						|
// e.g. http://example.com lacks "port", "path" or "query" keys
 | 
						|
 | 
						|
// This will *only* work properly for URLs of format:
 | 
						|
// scheme ":" "//" host [ ":" port ] [ abs_path [ "?" query ]]"
 | 
						|
// where [] denotes an optional component
 | 
						|
// file: URLs will *not* work as they lack the authority (host:port) component
 | 
						|
// Should work correctly for IPv6 host values, but bare in mind parse_url won't
 | 
						|
 | 
						|
var parts;
 | 
						|
parts = argument0;
 | 
						|
 | 
						|
var url;
 | 
						|
url = '';
 | 
						|
 | 
						|
url += ds_map_find_value(parts, 'scheme');
 | 
						|
url += '://';
 | 
						|
url += ds_map_find_value(parts, 'host');
 | 
						|
if (ds_map_exists(parts, 'port'))
 | 
						|
    url += ':' + string(ds_map_find_value(parts, 'port'));
 | 
						|
if (ds_map_exists(parts, 'abs_path'))
 | 
						|
{
 | 
						|
    url += ds_map_find_value(parts, 'abs_path');
 | 
						|
    if (ds_map_exists(parts, 'query'))
 | 
						|
        url += '?' + ds_map_find_value(parts, 'query');
 | 
						|
}
 | 
						|
 | 
						|
return url;
 | 
						|
 | 
						|
#define __http_prepare_request
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Internal function - prepares request
 | 
						|
// void __http_prepare_request(real client, string url, real headers)
 | 
						|
 | 
						|
// client - HttpClient object to prepare
 | 
						|
// url - URL to send GET request to
 | 
						|
// headers - ds_map of extra headers to send, -1 if none
 | 
						|
 | 
						|
var client, url, headers;
 | 
						|
client = argument0;
 | 
						|
url = argument1;
 | 
						|
headers = argument2;
 | 
						|
 | 
						|
var parsed;
 | 
						|
parsed = __http_parse_url(url);
 | 
						|
 | 
						|
if (parsed == -1)
 | 
						|
    show_error("Error when making HTTP GET request - can't parse URL: " + url, true);
 | 
						|
 | 
						|
if (!ds_map_exists(parsed, 'port'))
 | 
						|
    ds_map_add(parsed, 'port', 80);
 | 
						|
if (!ds_map_exists(parsed, 'abs_path'))
 | 
						|
    ds_map_add(parsed, 'abs_path', '/');
 | 
						|
 | 
						|
with (client)
 | 
						|
{
 | 
						|
    destroyed = false;
 | 
						|
    CR = chr(13);
 | 
						|
    LF = chr(10);
 | 
						|
    CRLF = CR + LF;
 | 
						|
    socket = tcp_connect(ds_map_find_value(parsed, 'host'), ds_map_find_value(parsed, 'port'));
 | 
						|
    state = 0;
 | 
						|
    errored = false;
 | 
						|
    error = '';
 | 
						|
    linebuf = '';
 | 
						|
    line = 0;
 | 
						|
    statusCode = -1;
 | 
						|
    reasonPhrase = '';
 | 
						|
    responseBody = buffer_create();
 | 
						|
    responseBodySize = -1;
 | 
						|
    responseBodyProgress = -1;
 | 
						|
    responseHeaders = ds_map_create();
 | 
						|
    requestUrl = url;
 | 
						|
    requestHeaders = headers;
 | 
						|
 | 
						|
    //  Request       = Request-Line              ; Section 5.1
 | 
						|
    //                  *(( general-header        ; Section 4.5
 | 
						|
    //                   | request-header         ; Section 5.3
 | 
						|
    //                   | entity-header ) CRLF)  ; Section 7.1
 | 
						|
    //                  CRLF
 | 
						|
    //                  [ message-body ]          ; Section 4.3
 | 
						|
 | 
						|
    // "The Request-Line begins with a method token, followed by the
 | 
						|
    // Request-URI and the protocol version, and ending with CRLF. The
 | 
						|
    // elements are separated by SP characters. No CR or LF is allowed
 | 
						|
    // except in the final CRLF sequence."
 | 
						|
    if (ds_map_exists(parsed, 'query'))
 | 
						|
        write_string(socket, 'GET ' + ds_map_find_value(parsed, 'abs_path') + '?' + ds_map_find_value(parsed, 'query') + ' HTTP/1.1' + CRLF);
 | 
						|
    else
 | 
						|
        write_string(socket, 'GET ' + ds_map_find_value(parsed, 'abs_path') + ' HTTP/1.1' + CRLF);
 | 
						|
 | 
						|
    // "A client MUST include a Host header field in all HTTP/1.1 request
 | 
						|
    // messages."
 | 
						|
    // "A "host" without any trailing port information implies the default
 | 
						|
    // port for the service requested (e.g., "80" for an HTTP URL)."
 | 
						|
    if (ds_map_find_value(parsed, 'port') == 80)
 | 
						|
        write_string(socket, 'Host: ' + ds_map_find_value(parsed, 'host') + CRLF);
 | 
						|
    else
 | 
						|
        write_string(socket, 'Host: ' + ds_map_find_value(parsed, 'host')
 | 
						|
            + ':' + string(ds_map_find_value(parsed, 'port')) + CRLF);
 | 
						|
 | 
						|
    // "An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
 | 
						|
    // maintain a persistent connection unless a Connection header including
 | 
						|
    // the connection-token "close" was sent in the request."
 | 
						|
    write_string(socket, 'Connection: close' + CRLF);
 | 
						|
 | 
						|
    // "If no Accept-Encoding field is present in a request, the server MAY
 | 
						|
    // assume that the client will accept any content coding."
 | 
						|
    write_string(socket, 'Accept-Encoding:' + CRLF);
 | 
						|
    
 | 
						|
    // If headers specified
 | 
						|
    if (headers != -1)
 | 
						|
    {
 | 
						|
        var key;
 | 
						|
        // Iterate over headers map
 | 
						|
        for (key = ds_map_find_first(headers); is_string(key); key = ds_map_find_next(headers, key))
 | 
						|
        {
 | 
						|
            write_string(socket, key + ': ' + ds_map_find_value(headers, key) + CRLF);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Send extra CRLF to terminate request
 | 
						|
    write_string(socket, CRLF);
 | 
						|
    
 | 
						|
    socket_send(socket);
 | 
						|
 | 
						|
    ds_map_destroy(parsed);
 | 
						|
}
 | 
						|
 | 
						|
#define __http_parse_header
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Internal function - parses header
 | 
						|
// real __http_parse_header(string linebuf, real line)
 | 
						|
// Returns false if it errored (caller should return and destroy)
 | 
						|
 | 
						|
var linebuf, line;
 | 
						|
linebuf = argument0;
 | 
						|
line = argument1;
 | 
						|
 | 
						|
// "HTTP/1.1 header field values can be folded onto multiple lines if the
 | 
						|
// continuation line begins with a space or horizontal tab."
 | 
						|
if ((string_char_at(linebuf, 1) == ' ' or ord(string_char_at(linebuf, 1)) == 9))
 | 
						|
{
 | 
						|
    if (line == 1)
 | 
						|
    {
 | 
						|
        errored = true;
 | 
						|
        error = "First header line of response can't be a continuation, right?";
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    headerValue = ds_map_find_value(responseHeaders, string_lower(headerName))
 | 
						|
        + string_copy(linebuf, 2, string_length(linebuf) - 1);
 | 
						|
}
 | 
						|
// "Each header field consists
 | 
						|
// of a name followed by a colon (":") and the field value. Field names
 | 
						|
// are case-insensitive. The field value MAY be preceded by any amount
 | 
						|
// of LWS, though a single SP is preferred."
 | 
						|
else
 | 
						|
{
 | 
						|
    var colonPos;
 | 
						|
    colonPos = string_pos(':', linebuf);
 | 
						|
    if (colonPos == 0)
 | 
						|
    {
 | 
						|
        errored = true;
 | 
						|
        error = "No colon in a header line of response";
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    headerName = string_copy(linebuf, 1, colonPos - 1);
 | 
						|
    headerValue = string_copy(linebuf, colonPos + 1, string_length(linebuf) - colonPos);
 | 
						|
    // "The field-content does not include any leading or trailing LWS:
 | 
						|
    // linear white space occurring before the first non-whitespace
 | 
						|
    // character of the field-value or after the last non-whitespace
 | 
						|
    // character of the field-value. Such leading or trailing LWS MAY be
 | 
						|
    // removed without changing the semantics of the field value."
 | 
						|
    while (string_char_at(headerValue, 1) == ' ' or ord(string_char_at(headerValue, 1)) == 9)
 | 
						|
        headerValue = string_copy(headerValue, 2, string_length(headerValue) - 1);
 | 
						|
}
 | 
						|
 | 
						|
ds_map_add(responseHeaders, string_lower(headerName), headerValue);
 | 
						|
 | 
						|
if (string_lower(headerName) == 'content-length')
 | 
						|
{
 | 
						|
    responseBodySize = real(headerValue);
 | 
						|
    responseBodyProgress = 0;
 | 
						|
}
 | 
						|
 | 
						|
return true;
 | 
						|
 | 
						|
#define __http_client_step
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Steps the HTTP client (needs to be called each step or so)
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
with (client)
 | 
						|
{
 | 
						|
    if (errored)
 | 
						|
        exit;
 | 
						|
    
 | 
						|
    // Socket error
 | 
						|
    if (socket_has_error(socket))
 | 
						|
    {
 | 
						|
        errored = true;
 | 
						|
        error = "Socket error: " + socket_error(socket);
 | 
						|
        return __http_client_destroy();
 | 
						|
    }
 | 
						|
    
 | 
						|
    var available;
 | 
						|
    available = tcp_receive_available(socket);
 | 
						|
    
 | 
						|
    switch (state)
 | 
						|
    {
 | 
						|
    // Receiving lines
 | 
						|
    case 0:
 | 
						|
        if (!available && tcp_eof(socket))
 | 
						|
        {
 | 
						|
            errored = true;
 | 
						|
            error = "Unexpected EOF when receiving headers/status code";
 | 
						|
            return __http_client_destroy();
 | 
						|
        }
 | 
						|
    
 | 
						|
        var bytesRead, c;
 | 
						|
        for (bytesRead = 1; bytesRead <= available; bytesRead += 1)
 | 
						|
        {
 | 
						|
            c = read_string(socket, 1);
 | 
						|
            // Reached end of line
 | 
						|
            // "HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
 | 
						|
            // protocol elements except the entity-body (see appendix 19.3 for
 | 
						|
            // tolerant applications)."
 | 
						|
            if (c == LF and string_char_at(linebuf, string_length(linebuf)) == CR)
 | 
						|
            {
 | 
						|
                // Strip trailing CR
 | 
						|
                linebuf = string_copy(linebuf, 1, string_length(linebuf) - 1);
 | 
						|
                // First line - status code
 | 
						|
                if (line == 0)
 | 
						|
                {
 | 
						|
                    // "The first line of a Response message is the Status-Line, consisting
 | 
						|
                    // of the protocol version followed by a numeric status code and its
 | 
						|
                    // associated textual phrase, with each element separated by SP
 | 
						|
                    // characters. No CR or LF is allowed except in the final CRLF sequence."
 | 
						|
                    var httpVer, spacePos;
 | 
						|
                    spacePos = string_pos(' ', linebuf);
 | 
						|
                    if (spacePos == 0)
 | 
						|
                    {
 | 
						|
                        errored = true;
 | 
						|
                        error = "No space in first line of response";
 | 
						|
                        return __http_client_destroy();
 | 
						|
                    }
 | 
						|
                    httpVer = string_copy(linebuf, 1, spacePos);
 | 
						|
                    linebuf = string_copy(linebuf, spacePos + 1, string_length(linebuf) - spacePos);
 | 
						|
    
 | 
						|
                    spacePos = string_pos(' ', linebuf);
 | 
						|
                    if (spacePos == 0)
 | 
						|
                    {
 | 
						|
                        errored = true;
 | 
						|
                        error = "No second space in first line of response";
 | 
						|
                        return __http_client_destroy();
 | 
						|
                    }
 | 
						|
                    statusCode = real(string_copy(linebuf, 1, spacePos));
 | 
						|
                    reasonPhrase = string_copy(linebuf, spacePos + 1, string_length(linebuf) - spacePos);
 | 
						|
                }
 | 
						|
                // Other line
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    // Blank line, end of response headers
 | 
						|
                    if (linebuf == '')
 | 
						|
                    {
 | 
						|
                        state = 1;
 | 
						|
                        // write remainder
 | 
						|
                        write_buffer_part(responseBody, socket, available - bytesRead);
 | 
						|
                        responseBodyProgress = available - bytesRead;
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
                    // Header
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        if (!__http_parse_header(linebuf, line))
 | 
						|
                            return __http_client_destroy();
 | 
						|
                    }
 | 
						|
                }
 | 
						|
    
 | 
						|
                linebuf = '';
 | 
						|
                line += 1;
 | 
						|
            }
 | 
						|
            else
 | 
						|
                linebuf += c;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    // Receiving response body
 | 
						|
    case 1:
 | 
						|
        write_buffer(responseBody, socket);
 | 
						|
        responseBodyProgress += available;
 | 
						|
        if (tcp_eof(socket))
 | 
						|
        {
 | 
						|
            if (ds_map_exists(responseHeaders, 'transfer-encoding'))
 | 
						|
            {
 | 
						|
                if (ds_map_find_value(responseHeaders, 'transfer-encoding') == 'chunked')
 | 
						|
                {
 | 
						|
                    // Chunked transfer, let's decode it
 | 
						|
                    var actualResponseBody, actualResponseSize;
 | 
						|
                    actualResponseBody = buffer_create();
 | 
						|
                    actualResponseBodySize = 0;
 | 
						|
 | 
						|
                    // Parse chunks
 | 
						|
                    // chunk          = chunk-size [ chunk-extension ] CRLF
 | 
						|
                    //                  chunk-data CRLF
 | 
						|
                    // chunk-size     = 1*HEX
 | 
						|
                    while (buffer_bytes_left(responseBody))
 | 
						|
                    {
 | 
						|
                        var chunkSize, c;
 | 
						|
                        chunkSize = '';
 | 
						|
                        
 | 
						|
                        // Read chunk size byte by byte 
 | 
						|
                        while (buffer_bytes_left(responseBody))
 | 
						|
                        {
 | 
						|
                            c = read_string(responseBody, 1);
 | 
						|
                            if (c == CR or c == ';')
 | 
						|
                                break;
 | 
						|
                            else
 | 
						|
                                chunkSize += c;
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        // We found a semicolon - beginning of chunk-extension
 | 
						|
                        if (c == ';')
 | 
						|
                        {
 | 
						|
                            // skip all extension stuff
 | 
						|
                            while (buffer_bytes_left(responseBody) && c != CR)
 | 
						|
                            {
 | 
						|
                                c = read_string(responseBody, 1);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        // Reached end of header
 | 
						|
                        if (c == CR)
 | 
						|
                        {
 | 
						|
                            c += read_string(responseBody, 1);
 | 
						|
                            // Doesn't end in CRLF
 | 
						|
                            if (c != CRLF)
 | 
						|
                            {
 | 
						|
                                errored = true;
 | 
						|
                                error = 'header of chunk in chunked transfer did not end in CRLF';
 | 
						|
                                buffer_destroy(actualResponseBody);
 | 
						|
                                return __http_client_destroy();
 | 
						|
                            }
 | 
						|
                            // chunk-size is empty - something's up!
 | 
						|
                            if (chunkSize == '')
 | 
						|
                            {
 | 
						|
                                errored = true;
 | 
						|
                                error = 'empty chunk-size in a chunked transfer';
 | 
						|
                                buffer_destroy(actualResponseBody);
 | 
						|
                                return __http_client_destroy();
 | 
						|
                            }
 | 
						|
                            chunkSize = __http_parse_hex(chunkSize);
 | 
						|
                            // Parsing of size failed - not hex?
 | 
						|
                            if (chunkSize == -1)
 | 
						|
                            {
 | 
						|
                                errored = true;
 | 
						|
                                error = 'chunk-size was not hexadecimal in a chunked transfer';
 | 
						|
                                buffer_destroy(actualResponseBody);
 | 
						|
                                return __http_client_destroy();
 | 
						|
                            }
 | 
						|
                            // Is the chunk bigger than the remaining response?
 | 
						|
                            if (chunkSize + 2 > buffer_bytes_left(responseBody))
 | 
						|
                            {
 | 
						|
                                errored = true;
 | 
						|
                                error = 'chunk-size was greater than remaining data in a chunked transfer';
 | 
						|
                                buffer_destroy(actualResponseBody);
 | 
						|
                                return __http_client_destroy();
 | 
						|
                            }
 | 
						|
                            // OK, everything's good, read the chunk
 | 
						|
                            write_buffer_part(actualResponseBody, responseBody, chunkSize);
 | 
						|
                            actualResponseBodySize += chunkSize;
 | 
						|
                            // Check for CRLF
 | 
						|
                            if (read_string(responseBody, 2) != CRLF)
 | 
						|
                            {
 | 
						|
                                errored = true;
 | 
						|
                                error = 'chunk did not end in CRLF in a chunked transfer';
 | 
						|
                                return __http_client_destroy();
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            errored = true;
 | 
						|
                            error = 'did not find CR after reading chunk header in a chunked transfer, Faucet HTTP bug?';
 | 
						|
                            return __http_client_destroy();
 | 
						|
                        }
 | 
						|
                        // if the chunk size is zero, then it was the last chunk
 | 
						|
                        if (chunkSize == 0
 | 
						|
                            // trailer headers will be present
 | 
						|
                            and ds_map_exists(responseHeaders, 'trailer'))
 | 
						|
                        {
 | 
						|
                            // Parse header lines
 | 
						|
                            var line;
 | 
						|
                            line = 1;
 | 
						|
                            while (buffer_bytes_left(responseBody))
 | 
						|
                            {
 | 
						|
                                var linebuf;
 | 
						|
                                linebuf = '';
 | 
						|
                                while (buffer_bytes_left(responseBody))
 | 
						|
                                {
 | 
						|
                                    c = read_string(responseBody, 1);
 | 
						|
                                    if (c != CR)
 | 
						|
                                        linebuf += c;
 | 
						|
                                    else
 | 
						|
                                        break;
 | 
						|
                                }
 | 
						|
                                c += read_string(responseBody, 1);
 | 
						|
                                if (c != CRLF)
 | 
						|
                                {
 | 
						|
                                    errored = true;
 | 
						|
                                    error = 'trailer header did not end in CRLF in a chunked transfer';
 | 
						|
                                    return __http_client_destroy();
 | 
						|
                                }
 | 
						|
                                if (!__http_parse_header(linebuf, line))
 | 
						|
                                    return __http_client_destroy();
 | 
						|
                                line += 1;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    responseBodySize = actualResponseBodySize;
 | 
						|
                    buffer_destroy(responseBody);
 | 
						|
                    responseBody = actualResponseBody;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    errored = true;
 | 
						|
                    error = 'Unsupported Transfer-Encoding: "' + ds_map_find_value(responseHaders, 'transfer-encoding') + '"';
 | 
						|
                    return __http_client_destroy();
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if (responseBodySize != -1)
 | 
						|
            {
 | 
						|
                if (responseBodyProgress < responseBodySize)
 | 
						|
                {
 | 
						|
                    errored = true;
 | 
						|
                    error = "Unexpected EOF, response body size is less than expected";
 | 
						|
                    return __http_client_destroy();
 | 
						|
                }
 | 
						|
            }
 | 
						|
            // 301 Moved Permanently/302 Found/303 See Other/307 Moved Temporarily
 | 
						|
            if (statusCode == 301 or statusCode == 302 or statusCode == 303 or statusCode == 307)
 | 
						|
            {
 | 
						|
                if (ds_map_exists(responseHeaders, 'location'))
 | 
						|
                {
 | 
						|
                    var location, resolved;
 | 
						|
                    location = ds_map_find_value(responseHeaders, 'location');
 | 
						|
                    resolved = __http_resolve_url(requestUrl, location);
 | 
						|
                    // Resolving URL didn't fail and it's http://
 | 
						|
                    if (resolved != '' and string_copy(resolved, 1, 7) == 'http://')
 | 
						|
                    {
 | 
						|
                        // Restart request
 | 
						|
                        __http_client_destroy();
 | 
						|
                        __http_prepare_request(client, resolved, requestHeaders);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        errored = true;
 | 
						|
                        error = "301, 302, 303 or 307 response with invalid or unsupported Location URL ('" + location +  "') - can't redirect";
 | 
						|
                        return __http_client_destroy();
 | 
						|
                    }
 | 
						|
                    exit;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    errored = true;
 | 
						|
                    error = "301, 302, 303 or 307 response without Location header - can't redirect";
 | 
						|
                    return __http_client_destroy();
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
                state = 2;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    // Done.
 | 
						|
    case 2:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#define __http_client_destroy
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Clears up contents of an httpClient prior to destruction or after error
 | 
						|
 | 
						|
if (!destroyed) {
 | 
						|
    socket_destroy(socket);
 | 
						|
    buffer_destroy(responseBody);
 | 
						|
    ds_map_destroy(responseHeaders);
 | 
						|
}
 | 
						|
destroyed = true;
 | 
						|
 | 
						|
#define http_new_get
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Makes a GET HTTP request
 | 
						|
// real http_new_get(string url)
 | 
						|
 | 
						|
// url - URL to send GET request to
 | 
						|
 | 
						|
// Return value is an HttpClient instance that can be passed to
 | 
						|
// fct_http_request_status etc.
 | 
						|
// (errors on failure to parse URL)
 | 
						|
 | 
						|
var url, client;
 | 
						|
 | 
						|
url = argument0;
 | 
						|
 | 
						|
if (!variable_global_exists('__HttpClient'))
 | 
						|
    __http_init();
 | 
						|
 | 
						|
client = instance_create(0, 0, global.__HttpClient);
 | 
						|
__http_prepare_request(client, url, -1);
 | 
						|
return client;
 | 
						|
 | 
						|
#define http_new_get_ex
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Makes a GET HTTP request with custom headers
 | 
						|
// real http_new_get_ex(string url, real headers)
 | 
						|
 | 
						|
// url - URL to send GET request to
 | 
						|
// headers - ds_map of extra headers to send
 | 
						|
 | 
						|
// Return value is an HttpClient instance that can be passed to
 | 
						|
// fct_http_request_status etc.
 | 
						|
// (errors on failure to parse URL)
 | 
						|
 | 
						|
var url, headers, client;
 | 
						|
 | 
						|
url = argument0;
 | 
						|
headers = argument1;
 | 
						|
 | 
						|
if (!variable_global_exists('__HttpClient'))
 | 
						|
    __http_init();
 | 
						|
 | 
						|
client = instance_create(0, 0, global.__HttpClient);
 | 
						|
__http_prepare_request(client, url, headers);
 | 
						|
return client;
 | 
						|
 | 
						|
#define http_step
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Steps the HTTP client. This is what makes everything actually happen.
 | 
						|
// Call it each step. Returns whether or not the request has finished.
 | 
						|
// real http_step(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is either:
 | 
						|
// 0 - In progress
 | 
						|
// 1 - Done or Errored
 | 
						|
 | 
						|
// Example usage:
 | 
						|
// req = http_new_get("http://example.com/x.txt");
 | 
						|
// while (http_step(req)) {}
 | 
						|
// if (http_status_code(req) != 200) {
 | 
						|
//     // Errored!
 | 
						|
// } else {
 | 
						|
//     // Hasn't errored, do stuff here.
 | 
						|
// }
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
__http_client_step(client);
 | 
						|
 | 
						|
if (client.errored || client.state == 2)
 | 
						|
    return 1;
 | 
						|
else
 | 
						|
    return 0;
 | 
						|
 | 
						|
#define http_status_code
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the status code
 | 
						|
// real http_status_code(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is either:
 | 
						|
// * 0, if the request has not yet finished
 | 
						|
// * a negative value, if there was an internal Faucet HTTP error
 | 
						|
// * a positive value, the status code of the HTTP request
 | 
						|
 | 
						|
// "The Status-Code element is a 3-digit integer result code of the
 | 
						|
// attempt to understand and satisfy the request. These codes are fully
 | 
						|
// defined in section 10. The Reason-Phrase is intended to give a short
 | 
						|
// textual description of the Status-Code. The Status-Code is intended
 | 
						|
// for use by automata and the Reason-Phrase is intended for the human
 | 
						|
// user. The client is not required to examine or display the Reason-
 | 
						|
// Phrase."
 | 
						|
 | 
						|
// See also: http_reason_phrase, gets the Reason-Phrase
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
if (client.errored)
 | 
						|
    return -1;
 | 
						|
else if (client.state == 2)
 | 
						|
    return client.statusCode;
 | 
						|
else
 | 
						|
    return 0;
 | 
						|
 | 
						|
#define http_reason_phrase
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the reason phrase
 | 
						|
// string http_reason_phrase(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
// Return value is either:
 | 
						|
// * "", if the request has not yet finished
 | 
						|
// * an internal Faucet HTTP error message, if there was one
 | 
						|
// * the reason phrase of the HTTP request
 | 
						|
 | 
						|
// "The Status-Code element is a 3-digit integer result code of the
 | 
						|
// attempt to understand and satisfy the request. These codes are fully
 | 
						|
// defined in section 10. The Reason-Phrase is intended to give a short
 | 
						|
// textual description of the Status-Code. The Status-Code is intended
 | 
						|
// for use by automata and the Reason-Phrase is intended for the human
 | 
						|
// user. The client is not required to examine or display the Reason-
 | 
						|
// Phrase."
 | 
						|
 | 
						|
// See also: http_status_code, gets the Status-Code
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
if (client.errored)
 | 
						|
    return client.error;
 | 
						|
else if (client.state == 2)
 | 
						|
    return client.reasonPhrase;
 | 
						|
else
 | 
						|
    return "";
 | 
						|
 | 
						|
#define http_response_body
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the response body returned by an HTTP request as a buffer
 | 
						|
// real http_response_body(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is a buffer if client hasn't errored and is finished
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
return client.responseBody;
 | 
						|
 | 
						|
#define http_response_body_size
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the size of response body returned by an HTTP request
 | 
						|
// real http_response_body_size(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is the size in bytes, or -1 if we don't know or don't know yet
 | 
						|
 | 
						|
// Call this each time you use the size - it may have changed in the case of redirect
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
return client.responseBodySize;
 | 
						|
 | 
						|
#define http_response_body_progress
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the size of response body returned by an HTTP request which is so far downloaded 
 | 
						|
// real http_response_body_progress(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is the size in bytes, or -1 if we haven't started yet or client has errored
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
return client.responseBodyProgress;
 | 
						|
 | 
						|
#define http_response_headers
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Gets the response headers returned by an HTTP request as a ds_map
 | 
						|
// real http_response_headers(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
// Return value is a ds_map if client hasn't errored and is finished
 | 
						|
 | 
						|
// All headers will have lowercase keys
 | 
						|
// The ds_map is owned by the HttpClient, do not use ds_map_destroy() yourself
 | 
						|
// Call when the request has finished - otherwise may be incomplete or missing
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
return client.responseHeaders;
 | 
						|
 | 
						|
#define http_destroy
 | 
						|
// ***
 | 
						|
// This function forms part of Faucet HTTP v1.0
 | 
						|
// https://github.com/TazeTSchnitzel/Faucet-HTTP-Extension
 | 
						|
// 
 | 
						|
// Copyright (c) 2013-2014, Andrea Faulds <ajf@ajf.me>
 | 
						|
// 
 | 
						|
// Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
// purpose with or without fee is hereby granted, provided that the above
 | 
						|
// copyright notice and this permission notice appear in all copies.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
// ***
 | 
						|
 | 
						|
// Cleans up HttpClient
 | 
						|
// void http_destroy(real client)
 | 
						|
 | 
						|
// client - HttpClient object
 | 
						|
 | 
						|
var client;
 | 
						|
client = argument0;
 | 
						|
 | 
						|
with (client)
 | 
						|
{
 | 
						|
    __http_client_destroy();
 | 
						|
    instance_destroy();
 | 
						|
}
 | 
						|
 |