123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902 |
- /*
- ** JNetLib
- ** Copyright (C) 2000-2007 Nullsoft, Inc.
- ** Author: Justin Frankel
- ** File: httpget.cpp - JNL HTTP GET implementation
- ** License: see jnetlib.h
- */
- #include "netinc.h"
- #include "util.h"
- #include "wac_network_http_receiver.h"
- #ifdef USE_SSL
- #include "wac_network_ssl_connection.h"
- #endif
- #include <stdio.h>
- #pragma intrinsic(memcpy)
- #include "../nu/strsafe.h"
- #include "nu/AutoLock.h"
- #include "..\WAT\WAT.h"
- char *wa::Components::WAC_Network_HTTPGet::g_proxy = 0;
- static nu::LockGuard proxy_guard;
- char *wa::Components::WAC_Network_HTTPGet::get_proxy()
- {
- nu::AutoLock auto_lock( proxy_guard );
- if ( g_proxy )
- return _strdup( g_proxy );
- else
- return 0;
- }
- void wa::Components::WAC_Network_HTTPGet::set_proxy( const char *p_proxy )
- {
- nu::AutoLock auto_lock( proxy_guard );
- free( g_proxy );
- if ( p_proxy )
- g_proxy = _strdup( p_proxy );
- else
- g_proxy = 0;
- }
- wa::Components::WAC_Network_HTTPGet::WAC_Network_HTTPGet( api_dns *p_dns, size_t p_recvbufsize, const char *p_proxy )
- {
- JNL::open_socketlib();
- reinit();
- open( p_dns, p_recvbufsize, p_proxy );
- }
- wa::Components::WAC_Network_HTTPGet::~WAC_Network_HTTPGet()
- {
- deinit();
- free( m_sendheaders );
- free( m_http_proxylpinfo );
- free( m_http_proxyhost );
- }
- void wa::Components::WAC_Network_HTTPGet::open( api_dns *p_dns, size_t p_recvbufsize, const char *p_proxy )
- {
- m_recvbufsize = p_recvbufsize;
- if ( p_dns != API_DNS_AUTODNS )
- m_dns = p_dns;
- if ( p_proxy )
- {
- char *p = _strdup( p_proxy );
- if ( p )
- {
- char *r = NULL;
- do_parse_url( p, &m_http_proxyhost, &m_http_proxyport, &r, &m_http_proxylpinfo );
- free( r );
- free( p );
- }
- }
- }
- void wa::Components::WAC_Network_HTTPGet::reinit()
- {
- m_errstr = 0;
- m_recvheaders = NULL;
- m_recvheaders_size = 0;
- m_http_state = 0;
- m_http_port = 0;
- m_http_url = 0;
- m_reply = 0;
- m_http_host = NULL;
- m_http_lpinfo = NULL;
- m_http_request = NULL;
- m_http_content_type = NULL;
- }
- void wa::Components::WAC_Network_HTTPGet::deinit( bool p_full )
- {
- if ( !persistent || p_full || ( m_con && m_con->get_state() == WAC_Network_Connection::STATE_ERROR ) )
- {
- delete m_con;
- m_con = NULL;
- }
- free( m_recvheaders );
- free( m_http_url );
- free( m_http_host );
- free( m_http_lpinfo );
- free( m_http_request );
- if ( m_http_content_type )
- free( m_http_content_type );
- free( m_errstr );
- free( m_reply );
- if ( zlibStream )
- inflateEnd( zlibStream );
- free( zlibStream );
- zlibStream = 0;
- reinit();
- }
- void wa::Components::WAC_Network_HTTPGet::set_sendbufsize( size_t p_sendbufsize )
- {
- m_sendbufsize = p_sendbufsize;
- }
- int wa::Components::WAC_Network_HTTPGet::set_recv_buffer_size( size_t p_new_buffer_size )
- {
- if ( m_con )
- {
- int ret = m_con->set_recv_buffer_size( p_new_buffer_size );
- if ( ret == NErr_NoAction )// this will get returned if new_buffer_size is smaller than existing.
- return NErr_Success;
- else if ( ret != NErr_Success )
- return ret;
- }
- m_recvbufsize = p_new_buffer_size;
- return NErr_Success;
- }
- void wa::Components::WAC_Network_HTTPGet::addheader( const char *header )
- {
- if ( strstr( header, "\r" ) || strstr( header, "\n" ) )
- return;
- if ( !m_sendheaders )
- {
- size_t len = strlen( header ) + 3;
- m_sendheaders = (char *)malloc( len );
- if ( m_sendheaders )
- {
- char *itr = m_sendheaders;
- StringCchCopyExA( itr, len, header, &itr, &len, 0 );
- StringCchCatExA( itr, len, "\r\n", &itr, &len, 0 );
- }
- }
- else
- {
- size_t len = strlen( header ) + strlen( m_sendheaders ) + 1 + 2;
- char *t = (char *)malloc( len );
- if ( t )
- {
- char *newHeaders = t;
- StringCchCopyExA( t, len, m_sendheaders, &t, &len, 0 );
- StringCchCatExA( t, len, header, &t, &len, 0 );
- StringCchCatExA( t, len, "\r\n", &t, &len, 0 );
- free( m_sendheaders );
- m_sendheaders = newHeaders;
- }
- }
- }
- void wa::Components::WAC_Network_HTTPGet::addheadervalue( const char *header, const char *value )
- {
- size_t additional = strlen( header ) + 2 + strlen( value ) + 2 + 1;
- if ( !m_sendheaders )
- {
- m_sendheaders = (char *)malloc( additional );
- if ( m_sendheaders )
- {
- char *p = m_sendheaders;
- StringCchCopyExA( p, additional, header, &p, &additional, 0 );
- StringCchCatExA( p, additional, ": ", &p, &additional, 0 );
- StringCchCatExA( p, additional, value, &p, &additional, 0 );
- StringCchCatExA( p, additional, "\r\n", &p, &additional, 0 );
- }
- }
- else
- {
- size_t alloc_len = strlen( m_sendheaders ) + additional;
- char *t = (char *)malloc( alloc_len );
- if ( t )
- {
- char *p = t;
- StringCchCopyExA( p, alloc_len, m_sendheaders, &p, &alloc_len, 0 );
- StringCchCatExA( p, alloc_len, header, &p, &alloc_len, 0 );
- StringCchCatExA( p, alloc_len, ": ", &p, &alloc_len, 0 );
- StringCchCatExA( p, alloc_len, value, &p, &alloc_len, 0 );
- StringCchCatExA( p, alloc_len, "\r\n", &p, &alloc_len, 0 );
- free( m_sendheaders );
- m_sendheaders = t;
- }
- }
- }
- void wa::Components::WAC_Network_HTTPGet::do_encode_mimestr( char *in, char *out )
- {
- char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- int shift = 0;
- int accum = 0;
- while ( in && *in )
- {
- if ( *in )
- {
- accum <<= 8;
- shift += 8;
- accum |= *in++;
- }
- while ( shift >= 6 )
- {
- shift -= 6;
- *out++ = alphabet[ ( accum >> shift ) & 0x3F ];
- }
- }
- if ( shift == 4 )
- {
- *out++ = alphabet[ ( accum & 0xF ) << 2 ];
- *out++ = '=';
- }
- else if ( shift == 2 )
- {
- *out++ = alphabet[ ( accum & 0x3 ) << 4 ];
- *out++ = '=';
- *out++ = '=';
- }
- *out++ = 0;
- }
- void wa::Components::WAC_Network_HTTPGet::connect( const char *url, int ver, const char *requestmethod )
- {
- deinit( false );
- m_http_url = _strdup( url );
- do_parse_url( m_http_url, &m_http_host, &m_http_port, &m_http_request, &m_http_lpinfo );
- if ( !m_http_host || !m_http_host[ 0 ] || !m_http_port )
- {
- m_http_state = -1;
- seterrstr( "invalid URL" );
- return;
- }
- size_t sendbufferlen = 0;
- if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
- sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_request ) + 9 /* HTTP/1.0 */ + 2;
- else
- {
- sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_url ) + 9 /* HTTP/1.0 */ + 2;
- if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
- sendbufferlen += 58 + strlen( m_http_proxylpinfo ) * 2; // being safe here
- }
- sendbufferlen += 5 /* Host: */ + strlen( m_http_host ) + 2;
- if ( m_http_port != 80 )
- sendbufferlen += 6;
- if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
- sendbufferlen += 46 + strlen( m_http_lpinfo ) * 2; // being safe here
- if ( m_sendheaders )
- sendbufferlen += strlen( m_sendheaders );
- size_t strLen = sendbufferlen + 1024;
- char *str = (char *)calloc( strLen, sizeof( char ) );
- char *connectString = str;
- if ( !str )
- {
- seterrstr( "error allocating memory" );
- m_http_state = -1;
- }
- if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
- {
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_request, ver % 10 );
- }
- else
- {
- char *myp = NULL;
- if ( strncasecmp( m_http_url, "uvox://", 7 ) == 0 )
- {
- myp = m_http_url + 7;
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http: //%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
- }
- else if ( strncasecmp( m_http_url, "unsv://", 7 ) == 0 )
- {
- myp = m_http_url + 7;
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http: //%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
- }
- else if ( strncasecmp( m_http_url, "uasf://", 7 ) == 0 )
- {
- myp = m_http_url + 7;
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http: //%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
- }
- else
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_url, ver % 10 );
- }
- if ( ver % 10 == 1 )
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Connection: close\r\n" );
- if ( m_http_port == 80 )
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s\r\n", m_http_host );
- else
- StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s:%d\r\n", m_http_host, m_http_port );
- if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
- {
- StringCchCatExA( str, strLen, "Authorization: Basic ", &str, &strLen, 0 );
- do_encode_mimestr( m_http_lpinfo, str );
- StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
- }
- if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
- {
- StringCchCatExA( str, strLen, "Proxy-Authorization: Basic ", &str, &strLen, 0 );
- do_encode_mimestr( m_http_proxylpinfo, str );
- StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
- }
- if ( allowCompression )
- StringCchCatExA( str, strLen, "Accept-Encoding: compress, gzip\r\n", &str, &strLen, 0 );
- if ( m_sendheaders )
- StringCchCatExA( str, strLen, m_sendheaders, &str, &strLen, 0 );
- StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
- int a = (int)m_recvbufsize;
- if ( a < 4096 )
- a = 4096;
- if ( !m_con )
- {
- //m_con=new WAC_Network_Connection(m_dns,strlen(str)+4,a);
- /*
- ** Joshua Teitelbaum delta 1/15/2006
- */
- #ifdef USE_SSL
- /*
- ** Joshua Teitelbaum 1/27/2006
- ** Check for secure
- */
- if ( !_strnicmp( m_http_url, "https:", strlen( "https:" ) ) )
- {
- size_t send_buffer_size = strlen( connectString ) + 4;
- if ( send_buffer_size < 8192 )
- send_buffer_size = 8192;
- send_buffer_size += m_sendbufsize;
- if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
- send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
- m_con = new JNL_SSL_Connection( NULL, m_dns, send_buffer_size, a );
- }
- else
- {
- #endif
- size_t send_buffer_size = strlen( connectString ) + 4 + m_sendbufsize;
- if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
- send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
- m_con = new WAC_Network_Connection( m_dns, send_buffer_size, a );
- #ifdef USE_SSL
- }
- #endif
- if ( m_con )
- {
- if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
- m_con->connect( m_http_host, m_http_port );
- else
- m_con->connect( m_http_proxyhost, m_http_proxyport );
- m_con->send_string( connectString );
- }
- else
- {
- m_http_state = -1;
- seterrstr( "could not create connection object" );
- }
- }
- else
- {
- m_con->reuse();
- m_con->send_string( connectString );
- }
- free( connectString );
- }
- void wa::Components::WAC_Network_HTTPGet::do_parse_url( const char *url, char **host, unsigned short *port, char **req, char **lp )
- {
- char *l_port = 0;
- JNL::parse_url( url, &l_port, host, port, req, lp );
- if ( !*port )
- {
- if ( l_port )
- {
- addrinfo *res;
- addrinfo hints;
- memset( &hints, 0, sizeof( hints ) );
- hints.ai_family = PF_UNSPEC;
- hints.ai_flags = 0;
- hints.ai_socktype = SOCK_STREAM;
- if ( getaddrinfo( 0, l_port, &hints, &res ) == 0 )
- {
- if ( res->ai_family == AF_INET )
- *port = htons( ( (sockaddr_in *)res->ai_addr )->sin_port );
- else if ( res->ai_family == AF_INET6 )
- *port = htons( ( (sockaddr_in6 *)res->ai_addr )->sin6_port );
- else // wtf?
- *port = 80;
- }
- else
- *port = 80;
- }
- else
- *port = 80;
- }
- if ( l_port )
- free( l_port );
- if ( !*req )
- *req = _strdup( "/" );
- }
- const char *wa::Components::WAC_Network_HTTPGet::getallheaders()
- {
- // double null terminated, null delimited list
- if ( m_recvheaders )
- return m_recvheaders;
- else
- return "\0\0";
- }
- char *wa::Components::WAC_Network_HTTPGet::getheader( const char *headername )
- {
- char *ret = NULL;
- if ( headername[ 0 ] == 0 || !m_recvheaders )
- return NULL;
- size_t headername_size = strlen( headername );
- char *buf = (char *)malloc( headername_size + 2 );
- #ifdef _WIN32
- StringCchCopyA( buf, headername_size + 2, headername );
- #elif defined(__APPLE__)
- strlcpy( buf, headername, headername_size + 2 );
- #else
- strncpy( buf, headername, headername_size + 1 );
- buf[ headername_size + 1 ] = 0;
- #endif
- if ( buf[ headername_size - 1 ] != ':' )
- {
- buf[ headername_size++ ] = ':';
- buf[ headername_size ] = 0;
- }
- char *p = m_recvheaders;
- while ( p && *p )
- {
- if ( !strncasecmp( buf, p, headername_size ) )
- {
- ret = p + headername_size;
- while ( ret && *ret && *ret == ' ' )
- ret++;
- break;
- }
- p += strlen( p ) + 1;
- }
- free( buf );
- return ret;
- }
- int wa::Components::WAC_Network_HTTPGet::run()
- {
- int cnt = 0;
- if ( m_http_state == -1 || !m_con )
- return HTTPRECEIVER_RUN_ERROR; // error
- run_again:
- m_con->run();
- if ( m_con->get_state() == WAC_Network_Connection::STATE_ERROR )
- {
- seterrstr( m_con->get_errstr() );
- return HTTPRECEIVER_RUN_ERROR;
- }
- if ( m_con->get_state() == WAC_Network_Connection::STATE_CLOSED )
- return HTTPRECEIVER_RUN_CONNECTION_CLOSED;
- if ( m_http_state == 0 ) // connected, waiting for reply
- {
- if ( m_con->recv_lines_available() > 0 )
- {
- char buf[ 4096 ] = { 0 };
- m_con->recv_line( buf, 4096 );
- buf[ 4095 ] = 0;
- if ( m_reply && getreplycode() == 100 )
- {
- free( m_reply );
- m_reply = 0;
- goto run_again;
- }
- m_reply = _strdup( buf );
- int code = getreplycode();
- if ( code >= 200 && code <= 206 )
- m_http_state = 2; // proceed to read headers normally
- else if ( code == 301 || code == 302 || code == 303 || code == 307 )
- {
- m_http_state = 1; // redirect city
- }
- else if ( code != 100 ) // in case of HTTP 100 Continue code, we'll keep looping
- {
- if ( accept_all_reply_codes )
- {
- m_http_state = 2; // proceed to read headers normally
- }
- else
- {
- seterrstr( buf );
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- }
- cnt = 0;
- }
- else if ( !cnt++ )
- goto run_again;
- }
- if ( m_http_state == 1 ) // redirect
- {
- char *loc = 0;
- while ( m_con->recv_lines_available() > 0 )
- {
- char buf[ 4096 ] = { 0 };
- m_con->recv_line( buf, 4096 );
- buf[ 4095 ] = 0;
- if ( !buf[ 0 ] )
- {
- if ( !loc )
- {
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- else
- break;
- }
- if ( !strncasecmp( buf, "Location:", 9 ) )
- {
- char *p = buf + 9;
- while ( p && *p && *p == ' ' ) p++;
- if ( p && *p )
- {
- // TODO need to make this match the request type
- loc = _strdup( p );
- }
- }
- }
- if ( loc )
- {
- connect( loc, 1 );
- free( loc );
- return HTTPRECEIVER_RUN_OK;
- }
- }
- /* ----- read headers ----- */
- if ( m_http_state == 2 )
- {
- if ( !cnt++ && m_con->recv_lines_available() < 1 )
- goto run_again;
- while ( m_con->recv_lines_available() > 0 )
- {
- char buf[ 8192 ] = { 0 };
- m_con->recv_line( buf, 8192 );
- buf[ 8191 ] = 0;
- if ( !buf[ 0 ] )
- {
- const char *compression = getheader( "Content-Encoding" );
- if ( compression && !strcmp( compression, "gzip" ) )
- {
- zlibStream = (z_stream *)malloc( sizeof( z_stream ) );
- zlibStream->next_in = Z_NULL;
- zlibStream->avail_in = Z_NULL;
- zlibStream->next_out = Z_NULL;
- zlibStream->avail_out = Z_NULL;
- zlibStream->zalloc = (alloc_func)0;
- zlibStream->zfree = (free_func)0;
- zlibStream->opaque = 0;
- int z_err = inflateInit2( zlibStream, 15 + 16 /* +16 for gzip */ );
- if ( z_err != Z_OK )
- {
- free( zlibStream );
- zlibStream = 0;
- }
- }
- else
- {
- if ( zlibStream )
- {
- free( zlibStream );
- zlibStream = 0;
- }
- }
- m_http_state = 3;
- break;
- }
- if ( !m_recvheaders )
- {
- m_recvheaders_size = strlen( buf ) + 1;
- if ( m_recvheaders_size == 0 || m_recvheaders_size == (size_t)-1 ) // check for overflow
- {
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- m_recvheaders = (char *)malloc( m_recvheaders_size + 1 );
- if ( m_recvheaders )
- {
- strcpy( m_recvheaders, buf ); // safe because we malloc'd specifically above
- m_recvheaders[ m_recvheaders_size ] = 0;
- }
- else
- {
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- }
- else
- {
- size_t oldsize = m_recvheaders_size;
- m_recvheaders_size += strlen( buf ) + 1;
- if ( m_recvheaders_size + 1 < oldsize ) // check for overflow
- {
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- char *n = (char *)realloc( m_recvheaders, m_recvheaders_size + 1 );
- if ( !n )
- {
- m_http_state = -1;
- return HTTPRECEIVER_RUN_ERROR;
- }
- strcpy( n + oldsize, buf ); // safe because we malloc specifially for the size
- n[ m_recvheaders_size ] = 0; // double null terminate
- m_recvheaders = n;
- }
- }
- }
- return HTTPRECEIVER_RUN_OK;
- }
- int wa::Components::WAC_Network_HTTPGet::get_status() // returns 0 if connecting, 1 if reading headers, 2 if reading content, -1 if error.
- {
- if ( m_http_state < 0 )
- return HTTPRECEIVER_STATUS_ERROR;
- if ( m_http_state < 2 )
- return HTTPRECEIVER_STATUS_CONNECTING;
- if ( m_http_state == 2 )
- return HTTPRECEIVER_STATUS_READING_HEADERS;
- if ( m_http_state == 3 )
- return HTTPRECEIVER_STATUS_READING_CONTENT;
- return HTTPRECEIVER_STATUS_ERROR;
- }
- int wa::Components::WAC_Network_HTTPGet::getreplycode() // returns 0 if none yet, otherwise returns http reply code.
- {
- if ( !m_reply )
- return 0;
- char *p = m_reply;
- while ( p && *p && *p != ' ' )
- p++; // skip over HTTP/x.x
- if ( !p || !*p )
- return 0;
- return atoi( ++p );
- }
- size_t wa::Components::WAC_Network_HTTPGet::bytes_available()
- {
- if ( m_con && m_http_state == 3 )
- return m_con->recv_bytes_available();
- return 0;
- }
- size_t wa::Components::WAC_Network_HTTPGet::get_bytes( char *buf, size_t len )
- {
- if ( m_con && m_http_state == 3 )
- {
- if ( zlibStream )
- {
- // TODO: benski> we need to pick a better buffer size
- // either alloca() and use the passed in length
- // or malloc a buffer based on the constructor-initted buffer size
- char temp[ 8192 ] = { 0 };
- int size = (int)m_con->peek_bytes( temp, 8192 );
- if ( size )
- {
- zlibStream->next_in = reinterpret_cast<Bytef *>( temp );
- zlibStream->avail_in = (uInt)size;
- zlibStream->next_out = reinterpret_cast<Bytef *>( buf );
- zlibStream->avail_out = (uInt)len;
- int zlib_err = inflate( zlibStream, Z_SYNC_FLUSH );
- if ( zlib_err == Z_OK || zlib_err == Z_STREAM_END )
- {
- m_con->recv_bytes( 0, size - zlibStream->avail_in ); // since we only peeked above
- return len - zlibStream->avail_out;
- }
- else
- return 0; // TODO: should we do something else here?
- }
- }
- else
- return m_con->recv_bytes( buf, len );
- }
- return 0;
- }
- size_t wa::Components::WAC_Network_HTTPGet::peek_bytes( char *buf, size_t len )
- {
- if ( m_con && m_http_state == 3 )
- {
- if ( zlibStream )
- return 0; // TODO: benski> how are we going to do peek_bytes, since the inflater saves state?
- else
- return m_con->peek_bytes( buf, len );
- }
- return 0;
- }
- uint64_t wa::Components::WAC_Network_HTTPGet::content_length()
- {
- const char *p = getheader( "Content-Length" );
- if ( p && *p )
- return strtoull( p, 0, 10 );
- else
- {
- // TODO need to check this further for reliability!
- // Helps to handle responses without content-length
- if ( m_recvheaders_size > 0 && bytes_available() > 0 )
- return bytes_available() - m_recvheaders_size;
- }
- return 0;
- }
- void wa::Components::WAC_Network_HTTPGet::seterrstr( const char *str )
- {
- if ( m_errstr )
- free( m_errstr );
- m_errstr = _strdup( str );
- }
- void wa::Components::WAC_Network_HTTPGet::AllowCompression()
- {
- allowCompression = true;
- }
- void wa::Components::WAC_Network_HTTPGet::reset_headers()
- {
- if ( m_sendheaders )
- {
- free( m_sendheaders );
- m_sendheaders = 0;
- }
- }
- void wa::Components::WAC_Network_HTTPGet::set_accept_all_reply_codes()
- {
- accept_all_reply_codes = true;
- }
- void wa::Components::WAC_Network_HTTPGet::set_persistent()
- {
- persistent = true;
- }
- size_t wa::Components::WAC_Network_HTTPGet::AddRef()
- {
- return this->_reference_count.fetch_add( 1 );
- }
- size_t wa::Components::WAC_Network_HTTPGet::Release()
- {
- std::size_t l_reference_count = this->_reference_count.fetch_sub( 1 );
- if ( l_reference_count == 0 )
- delete this;
- return l_reference_count;
- }
- #ifdef CBCLASS
- #undef CBCLASS
- #endif
- #define CBCLASS wa::Components::WAC_Network_HTTPGet
- START_DISPATCH;
- CB( ADDREF, AddRef )
- CB( RELEASE, Release )
- VCB( API_HTTPRECEIVER_OPEN, open )
- VCB( API_HTTPRECEIVER_ADDHEADER, addheader )
- VCB( API_HTTPRECEIVER_ADDHEADERVALUE, addheadervalue )
- VCB( API_HTTPRECEIVER_CONNECT, connect )
- CB( API_HTTPRECEIVER_RUN, run )
- CB( API_HTTPRECEIVER_GETSTATUS, get_status )
- CB( API_HTTPRECEIVER_GETBYTESAVAILABLE, bytes_available )
- CB( API_HTTPRECEIVER_GETBYTES, get_bytes )
- CB( API_HTTPRECEIVER_PEEKBYTES, peek_bytes )
- CB( API_HTTPRECEIVER_GETHEADER, getheader )
- CB( API_HTTPRECEIVER_GETCONTENTLENGTH, content_length )
- CB( API_HTTPRECEIVER_GETALLHEADERS, getallheaders )
- CB( API_HTTPRECEIVER_GETREPLYCODE, getreplycode )
- CB( API_HTTPRECEIVER_GETREPLY, getreply )
- CB( API_HTTPRECEIVER_GETERROR, geterrorstr )
- CB( API_HTTPRECEIVER_GETCONNECTION, get_con )
- VCB( API_HTTPRECEIVER_ALLOW_COMPRESSION, AllowCompression )
- VCB( API_HTTPRECEIVER_RESET_HEADERS, reset_headers )
- CB( API_HTTPRECEIVER_GET_URL, get_url )
- VCB( API_HTTPRECEIVER_SET_SENDBUFSIZE, set_sendbufsize )
- VCB( API_HTTPRECEIVER_SET_ACCEPT_ALL_REPLY_CODES, set_accept_all_reply_codes )
- VCB( API_HTTPRECEIVER_SET_PERSISTENT, set_persistent )
- END_DISPATCH;
- #undef CBCLASS
|