Beispiel #1
0
void ck_file::open( const ck_string& path, const ck_string& mode )
{
    if( _f )
        CK_THROW(("Attempted to open() already open file object."));

    _f = fopen( path.c_str(), mode.c_str() );

    if( !_f )
        CK_THROW(("Unable to open file: %s (%s)",path.c_str(),mode.c_str()));
}
Beispiel #2
0
void ck_large_files_test::test_seek_tell()
{
    FILE* f = fopen( ASCII_FILE.c_str(), "r" );
    ck_fseeko( f, 0, SEEK_END );
    int64_t pos = ck_ftello( f );
    UT_ASSERT( pos == ASCII_FILE_LEN );
    fclose( f );
}
Beispiel #3
0
bool client_response::_add_line(std::list<ck_string>& lines, const ck_string& line)
{
    if(line.starts_with("\r\n") || line.starts_with("\n"))
        return true;

    if(line.starts_with(" ") || line.starts_with("\t"))
    {
        if(!lines.empty())
            lines.back() += line;
        else
            CK_STHROW(hyperhttp_exception, ("First line of header missing needed seperator."));
    }
    else
        lines.push_back(line);

    return false;
}
Beispiel #4
0
void ck_large_files_test::test_pre_allocated_file()
{
    FILE* f = fopen( PRE_ALLOCATED_FILE.c_str(), "r+b" );
    ck_fallocate( f, (1024*1024) );
    fclose( f );
    ck_file_info info;
    ck_stat(PRE_ALLOCATED_FILE,&info);
    UT_ASSERT( info.file_size == (1024*1024) );
}
Beispiel #5
0
void client_response::_read_chunked_body(shared_ptr<ck_stream_io> socket)
{
    char lineBuf[MAX_HEADER_LINE+1];
    bool moreChunks = true;

    while(moreChunks)
    {
        memset(lineBuf, 0, MAX_HEADER_LINE+1);

        _read_header_line(socket, lineBuf, false);

        if(lineBuf[0] == '0')
        {
            _consume_footer(socket);
            return;
        }

        if(_embed_null(lineBuf))
        {
            const ck_string chunkLenS = lineBuf;
            const uint32_t chunkLen = chunkLenS.to_uint(16);

            // We read our chunk into a temporary "chunk" ck_memory object, we then optionally
            // call our "chunk callback" function... Finally, we copy the new chunk into the
            // main body contents object.

            _chunk->clear();
            if(!_receive_data(socket, _chunk->extend_data(chunkLen).get_ptr(), chunkLen))
                CK_STHROW(hyperhttp_exception, ("Failed to read data from socket->"));

            // call callback here...
            if( _chunkCallback )
                _chunkCallback( _chunk, *this );

            // We only append a chunk to our "_bodyContents" if we are not streaming (
            // because "streams" potentially have no end, so an ck_memory that contains the
            // complete body contents would just grow forever).
            if(!_streaming)
                memcpy(_bodyContents->extend_data(chunkLen).get_ptr(), _chunk->map().get_ptr(), chunkLen);

            _read_end_of_line(socket);
        }
    }
}
Beispiel #6
0
void client_response::_process_request_lines(const list<ck_string>& requestLines)
{
    // Now, iterate on the header lines...

    for(list<ck_string>::const_iterator iter = requestLines.begin(), end = requestLines.end();
        iter != end;
        ++iter)
    {
        const size_t firstColon = iter->find(':');

        if(firstColon != string::npos)
        {
            const ck_string key = iter->substr(0, firstColon);
            const ck_string val = firstColon + 1 < iter->size() ? iter->substr(firstColon + 1) : "";

            _add_header(key.to_lower(), val.strip_eol());
        }
    }
}
Beispiel #7
0
bool cppkit::ck_uuid_string_valid(const ck_string& uuid)
{
    // XXX Note: This is a fairly shitty uuid validator. It only checks for
    // length and that the dashes are in the right place. This could bite us, 
    // but I doubt it... hopefully I'm right. :)
    if(uuid.length() != 36)
        return false;
    if(uuid[8]!='-' || uuid[13]!='-' || uuid[18]!='-' || uuid[23]!='-')
        return false;

    return true;
}
Beispiel #8
0
vector<ck_string> client_response::get_all_matching_headers(const ck_string& header) const
{
    vector<ck_string> matchingHeaders;

    auto matches = _headerParts.find(header.to_lower());
    if( matches != _headerParts.end() )
    {
        for( auto i = (*matches).second.begin(); i != (*matches).second.end(); ++i )
            matchingHeaders.push_back( *i );
    }

    return matchingHeaders;
}
Beispiel #9
0
int ck_ssl_socket::_compare_strings(ASN1_STRING *a, int cmp_type, ck_string hostname )
{
    if (!a->data || !a->length)
        return 0;

    if (cmp_type > 0)
    {
        if (cmp_type != a->type)
            return 0;
        if (cmp_type == V_ASN1_IA5STRING)
            return _equal_wildcard(a->data, a->length, (unsigned char*)hostname.c_str(), hostname.length() );
        if (a->length == (int)hostname.length() && !memcmp(a->data, (unsigned char*)hostname.c_str(), hostname.length() ))
            return 1;
        else
            return 0;
    }
    else
    {
        int astrlen = 0, rv = 0;
        unsigned char *astr = NULL;
        try
        {
            astrlen = ASN1_STRING_to_UTF8(&astr, a);
            if (astrlen < 0)
                return -1;
            rv = _equal_wildcard(astr, astrlen, (unsigned char*)hostname.c_str(), hostname.length() );
            OPENSSL_free(astr);
        }
        catch(...)
        {
            if( astr )
                OPENSSL_free(astr);
            throw;
        }
        return rv;
    }
}
Beispiel #10
0
void ck_large_files_test::setup()
{
    FILE* f = local_fopen(ASCII_FILE,LOCAL_WRITE_MODE);
    fwrite(ASCII_FILE.c_str(),ASCII_FILE.length(),1,f);
    fclose(f);
    f = local_fopen(UNICODE_FILE,LOCAL_WRITE_MODE);
    fwrite(UNICODE_FILE.get_wide_string().data(),UNICODE_FILE.get_wide_string().length(),1,f);
    fclose(f);
    f = local_fopen( PRE_ALLOCATED_FILE, "w+b" );
    fwrite(UNICODE_FILE.get_wide_string().data(),UNICODE_FILE.get_wide_string().length(),1,f);
    fclose(f);
}
Beispiel #11
0
void ck_large_files_test::teardown()
{
#ifdef IS_WINDOWS
    if ( !DeleteFile(UNICODE_FILE.get_wide_string().data()) )
        printf("Failed to delete unicode file\n");
    if ( !DeleteFile(ASCII_FILE.get_wide_string().data()) )
        printf("Failed to delete ascii file\n");
    if ( !DeleteFile(PRE_ALLOCATED_FILE.get_wide_string().data()) )
        printf("Failed to delete pre allocated file\n");
#endif
#ifdef IS_LINUX
    if ( remove(ASCII_FILE.c_str()) != 0)
        printf("Failed to delete ascii file\n");
    if (remove(UNICODE_FILE.c_str()) != 0)
        printf("Failed to delete unicode file\n");
    if (remove(PRE_ALLOCATED_FILE.c_str()) != 0)
        printf("Failed to delete pre allocated file\n");
#endif
}
Beispiel #12
0
chrono::system_clock::time_point cppkit::ck_iso_8601_to_time_point( const ck_string& str )
{
	const size_t tDex = str.find('T');

	if (tDex == string::npos)
        CK_THROW(("Invalid iso 8601 string: %s",str.c_str()));

	const size_t dotDex = str.find('.');
	const size_t zDex = str.find('Z');
	const size_t plusDex = str.find('+', 1);
	const size_t subDex = str.find('-', str.find('-', str.find('-') + 1) + 1);

	if (plusDex != string::npos && subDex != string::npos)
        CK_THROW(("Invalid iso 8601 string: %s",str.c_str()));

	size_t dtEnd = dotDex;

	if (dtEnd == string::npos || dtEnd > zDex)
		dtEnd = zDex;

	if (dtEnd == string::npos || dtEnd > plusDex)
		dtEnd = plusDex;

	if (dtEnd == string::npos || dtEnd > subDex)
		dtEnd = subDex;

	const string dateStr = str.substr(0, tDex);
	const string timeStr = str.substr(tDex + 1, (dtEnd - tDex) - 1);
	string fracSecStr;

	if (dotDex != string::npos)
	{
		size_t fsEnd = zDex;

		if (fsEnd == string::npos || fsEnd > plusDex)
			fsEnd = plusDex;

		if (fsEnd == string::npos || fsEnd > subDex)
			fsEnd = subDex;

		const size_t fsStart = dateStr.size() + 1 + timeStr.size();
		const size_t fsLen = fsEnd == string::npos ? string::npos : fsEnd - fsStart;

		fracSecStr = str.substr(fsStart, fsLen);
	}

	const size_t zoneDex = dateStr.size() + 1 + timeStr.size() + fracSecStr.size();
	const string zoneStr = zDex == str.size() ? "" : str.substr(zoneDex);

	tm ttm = tm();

	int yyyy = 0, mm = 0, dd = 0;
	SSCANF(dateStr.c_str(), "%4d-%2d-%2d", &yyyy, &mm, &dd);

	ttm.tm_year = yyyy - 1900;
	ttm.tm_mon = mm - 1; // Month since January 
	ttm.tm_mday = dd; // Day of the month [1-31]

	int HH = 0, MM = 0, SS = 0;
	SSCANF(timeStr.c_str(), "%2d:%2d:%2d", &HH, &MM, &SS);

	ttm.tm_hour = HH; // Hour of the day [00-23]
	ttm.tm_min = MM;
	ttm.tm_sec = SS;

	// We need to go from a broken down time (struct tm) to a time_t. BUT, we have to use the right function when converting
	// from struct tm. mktime() assumes the struct tm is in localtime. gmtime() assumes the struct tm is in UTC. If the incoming
	// iso 8601 string has a 'Z' then we need to use gmtime() (or _mkgmtime() on windows), else we can use mktime().
	time_t theTime = 0;
	if (zDex == string::npos) // input is local time
		theTime = mktime(&ttm);
	else // input is UTC
	{
#ifdef IS_WINDOWS
		theTime = _mkgmtime(&ttm);
#else
		theTime = timegm(&ttm);
#endif
	}

	system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(theTime);

	double fracSec = stod(fracSecStr);

	uint32_t numMillis = (uint32_t)(fracSec * 1000);

	time_point_result += std::chrono::milliseconds(numMillis);

	return time_point_result;
}
Beispiel #13
0
void ck_ssl_socket::connect( const ck_string& host, int port )
{
    unique_lock<recursive_mutex> guard( _sslLok );

    if( _sok.valid() )
        _sok.close();

    if( _ssl )
        close();

    _ssl = SSL_new( _ctx );
    if( !_ssl )
        CK_STHROW( ck_socket_exception, ("Unable to allocate SSL object.") );

    ck_string ip = host;
    if( ck_socket_address::is_hostname( host ) )
    {
        vector<ck_string> addresses = ck_resolve( ck_socket_address::get_address_family(host), host );
        if( addresses.size() == 0 )
            CK_STHROW( ck_socket_exception, ( "Unable to resolve hostname." ));

        ip = addresses[0];
        // If someone called SetHost(), use that value instead
        if( !_hostName.empty() )
            SSL_set_tlsext_host_name( _ssl, _hostName.c_str() );
        else
            SSL_set_tlsext_host_name( _ssl, host.c_str() );
    }

    _sok.connect( ip, port );

    if( _hostName.empty() )
        _hostName = host;

#ifdef IS_WINDOWS
    ULONG mode = 1;
    ioctlsocket( _sok.get_sok_id(), FIONBIO, &mode);
#else
    int flags = fcntl( _sok.get_sok_id(), F_GETFL, 0);
    fcntl( _sok.get_sok_id(), F_SETFL, flags | O_NONBLOCK );
#endif

    int fd = (int)_sok.get_sok_id();
    SSL_set_fd(_ssl, fd);

#ifndef IS_WINDOWS
    signal( SIGPIPE, SIG_IGN );
#endif

    bool verified = false;

    //If someone has asked to verify, then we must SSL_connect in order
    //to retreive the X509 cert.  Otherwise we do a passive connect
    if( _verifyConnection )
    {
        //Do handshake here to get X509
        int error = -1;
        int result = 0;

        // XXX - used to use member called connectTimeoutMillis
        uint64_t waitTime = 10000;
        do
        {
            ERR_clear_error();
            result = SSL_connect( _ssl );
            error = _handle_error( result, waitTime );
        }
        while( waitTime > 0 && error > XSSL_ERROR_NONE );

        if( result == 1 && error == XSSL_ERROR_NONE )
        {
            X509 *cert = SSL_get_peer_certificate( _ssl );
            if( cert != NULL )
            {
                if( SSL_get_verify_result( _ssl ) == X509_V_OK )
                {
                    int check = _x509_check_host(cert, _hostName);
                    //If check is 1, the certificate matched the hostname
                    verified = (check == 1);

                    if( ! verified )
                        CK_LOG_ERROR("WARNING: Possible man-in-the-middle attack detected.  The hostname specified %s does not match the hostname in the server's X509 certificate.", _hostName.c_str() );
                }
                else
                {
                    CK_LOG_ERROR("Unable to verify the ssl certificate presented by: %s", _hostName.c_str() );
                }

                X509_free( cert );
            }
            else CK_LOG_ERROR("Verification was requested but the server didn't return an X509 Certificate.");

            if( !verified )
                CK_STHROW( ck_ssl_socket_auth_exception, ("Unable to verify the ssl certificate presented by: %s", _hostName.c_str()));
        }

        return;
    }

    // This call lets OpenSSL know this socket will be used as a client. It also
    // enable auto renegotiation when doing io.
    SSL_set_connect_state( _ssl );
}
Beispiel #14
0
ck_string client_response::get_header(const ck_string& name) const
{
    auto values = _headerParts.find( name.to_lower() );

    return (values != _headerParts.end()) ? (*values).second.front() : "";
}
Beispiel #15
0
#include "cppkit/os/ck_large_files.h"
#include "cppkit/ck_types.h"
#include <stdio.h>
#include <stdlib.h>
#include "ck_large_files_test.h"

using namespace std;
using namespace cppkit;

REGISTER_TEST_FIXTURE(ck_large_files_test);

static const ck_string ASCII_FILE = "LargeFileTests_ASCII_File.txt";
static const int ASCII_FILE_LEN = strlen( ASCII_FILE.c_str() );
static const ck_string UNICODE_FILE = L"Masta_カメラ_2010-12-21_1652.txt";
static const ck_string PRE_ALLOCATED_FILE = "LargeFileTests_PreAllocatedFile.txt";
static const char* LOCAL_WRITE_MODE = "w+b";

FILE* local_fopen( const ck_string& path, const ck_string& mode )
{
    FILE* fp = NULL;
#ifdef IS_POSIX
    fp = fopen( path.c_str(), mode.c_str() );
    if ( !fp )
        CK_THROW(( "Unable to open file: %s\n", path.c_str() ));
#else
    errno_t err;

    if ( err = _wfopen_s( &fp, path.get_wide_string().c_str(), mode.get_wide_string().c_str() ) != 0 )
        CK_THROW(( "fopen_s returned error code: %d.\n", (int)err ));
 CK_API virtual bool handles_this_presentation( const ck_string& presentation ) { return presentation.contains( "/foo/bar" ); }
void ck_dynamic_library::load( const ck_string& libraryName )
{
    if( false == libraryName.empty() )
    {
        if( (_libraryName != libraryName) && _libraryInstance )
            unload();

#ifdef IS_WINDOWS
        _libraryInstance = ::LoadLibraryW( libraryName.get_wide_string().data() );
#else
        _libraryInstance = dlopen( libraryName.c_str(), RTLD_NOW | RTLD_GLOBAL );
#endif

        if( _libraryInstance == 0 )
        {
#ifdef IS_WINDOWS
            LPVOID str = 0;
            DWORD_PTR args[1] = { (DWORD_PTR)_libraryName.c_str() };

            FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                           NULL,
                           GetLastError(),
                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                           (LPTSTR)&str,
                           0,
                           (va_list*)args );

            // The string already comes with a carriage return.
            ck_string errorString = (LPTSTR)str;
            LocalFree( str );

            CK_THROW(("Unable to load library(%s); error(%s)",
                      libraryName.c_str(), errorString.c_str() ));
#else
            ck_string dlError = dlerror();

            if( dlError.contains( "undefined symbol: " ) )
            {
                vector<ck_string> parts = dlError.split( "undefined symbol: " );

                if( parts.size() == 2 )
                {
                    ck_string rhs = parts[1];

                    const size_t closeParen = rhs.find( ')' );

                    ck_string mangledName = rhs.substr( 0, (rhs.size()-closeParen) );

                    int status = 0;
                    char* demangled = abi::__cxa_demangle( mangledName.c_str(), NULL, NULL, &status );

                    ck_string demangledName = demangled;

                    free( demangled );

                    CK_THROW(("Unable to load library(%s); error(%s); demangled undefined symbol(%s);",
                              libraryName.c_str(), dlError.c_str(), demangledName.c_str() ));
                }
            }
            else CK_THROW(("Unable to load library(%s); error(%s)", libraryName.c_str(), dlerror() ));
#endif
        }

        _libraryName = libraryName;
    }
    else CK_THROW(("Library name is empty"));
}