예제 #1
0
static Boolean addAuthenticationToWSInvokation(
	WSMethodInvocationRef wsRef, 
	CFStringRef username, 
	CFStringRef password, 
	CFDictionaryRef response)
{
    CFHTTPMessageRef message = 
		(CFHTTPMessageRef)CFDictionaryGetValue(response, kWSHTTPResponseMessage);
    CFHTTPMessageRef outgoingMessage = NULL;

    if (message != NULL) {
        CFURLRef theURL = CFHTTPMessageCopyRequestURL(message);
        if (theURL != NULL) {
            //Move the stuff that counts into our new message
            outgoingMessage = CFHTTPMessageCreateRequest(NULL, CFSTR("POST"), 
				theURL, kCFHTTPVersion1_1);
            CFRelease(theURL);
        }
    }

    Boolean successful = FALSE;

    if ((message != NULL) && (outgoingMessage != NULL)) {
        successful =  CFHTTPMessageAddAuthentication(outgoingMessage, message, 
			username, password, kCFHTTPAuthenticationSchemeDigest, FALSE);
    }

    if (successful) {
		/* FIXME kWSHTTPMessage isn't exported by WebServicesCore
		 * I can't find the source but there is a string in the binary that
		 * looks like this, with the leading '/' */
        WSMethodInvocationSetProperty(wsRef, CFSTR("/kWSHTTPMessage"), outgoingMessage);
    }

    if (outgoingMessage) {
		CFRelease(outgoingMessage);
	}
    return successful;
}
static void do_upload__string(
    SG_context* pCtx,
    const char* pszUrl,
    const char* psz_method,
    SG_pathname* pPath,
    const char* psz_username,
    const char* psz_password,
    SG_string** ppstr
)
{
    SG_string* pstr = NULL;
    CFHTTPMessageRef myRequest = NULL;
    CFHTTPMessageRef myResponse = NULL;
    CFStringRef s_username = NULL;
    CFStringRef s_password = NULL;

    SG_ERR_CHECK(  make_request(pCtx, pszUrl, psz_method, NULL, &myRequest)  );
    SG_ERR_CHECK(  perform_upload_request__string(pCtx, myRequest, pPath, &myResponse, &pstr)  );
#if 0
    {
        CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse);
        fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
        CFRelease(d);
    }
#endif
    UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(myResponse);

    if (
        psz_username
        && psz_password
        && (statusCode == 401 || statusCode == 407)
    )
    {
        s_username = CFStringCreateWithCString(kCFAllocatorDefault, psz_username, kCFStringEncodingUTF8);
        s_password = CFStringCreateWithCString(kCFAllocatorDefault, psz_password, kCFStringEncodingUTF8);
        if (!CFHTTPMessageAddAuthentication(myRequest, myResponse, s_username, s_password, kCFHTTPAuthenticationSchemeDigest, FALSE))
        {
            SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "CFHTTPMessageAddAuthentication failed"));
        }

#if 0
        {
            CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest);
            fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
            CFRelease(d);
        }
#endif

        CFRelease(s_username);
        s_username = NULL;

        CFRelease(s_password);
        s_password = NULL;

        CFRelease(myResponse);
        myResponse = NULL;

        SG_STRING_NULLFREE(pCtx, pstr);
        SG_ERR_CHECK(  perform_upload_request__string(pCtx, myRequest, pPath, &myResponse, &pstr)  );

#if 0
        {
            CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse);
            fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
            CFRelease(d);
        }
#endif
        statusCode = CFHTTPMessageGetResponseStatusCode(myResponse);
    }

    if (statusCode != 200)
    {
        SG_ERR_THROW2_RETURN(SG_ERR_SERVER_HTTP_ERROR, (pCtx, "%d", (int) statusCode));
    }

    *ppstr = pstr;
    pstr = NULL;

    /* fall through */

fail:
    if (s_username)
    {
        CFRelease(s_username);
        s_username = NULL;
    }
    if (s_password)
    {
        CFRelease(s_password);
        s_password = NULL;
    }
    if (myRequest)
    {
        CFRelease(myRequest);
        myRequest = NULL;
    }

    if (myResponse)
    {
        CFRelease(myResponse);
        myResponse = NULL;
    }

    SG_STRING_NULLFREE(pCtx, pstr);
}
// TODO give this a better name.  It gets used outside this file now.
void do_url(
    SG_context* pCtx,
    const char* pszUrl,
    const char* psz_method,
    const char* psz_data,
    const char* psz_username,
    const char* psz_password,
    SG_string** ppstr,
    SG_pathname* pPath,
    SG_bool b_progress
)
{
    SG_string* pstr = NULL;
    CFHTTPMessageRef myRequest = NULL;
    CFHTTPMessageRef myResponse = NULL;
    CFStringRef s_username = NULL;
    CFStringRef s_password = NULL;

    if (pPath && ppstr)
    {
        SG_ERR_RESET_THROW2(SG_ERR_INVALIDARG, (pCtx, "do_url() returns into a string or a file, but not both"));
    }

    if (!pPath && !ppstr)
    {
        SG_ERR_RESET_THROW2(SG_ERR_INVALIDARG, (pCtx, "do_url() returns into a string or a file, one or the other"));
    }

    SG_ERR_CHECK(  make_request(pCtx, pszUrl, psz_method, psz_data, &myRequest)  );

#if 0
    {
        CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest);
        fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
        CFRelease(d);
    }
#endif

    if (pPath)
    {
        SG_ERR_CHECK(  perform_request__file(pCtx, myRequest, &myResponse, pPath, b_progress)  );
    }
    else
    {
        SG_ERR_CHECK(  perform_request__string(pCtx, myRequest, &myResponse, &pstr)  );
    }

    if (!myResponse)
    {
        SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "No response from server"));
    }

    //fprintf(stderr, "\n%s\n", SG_string__sz(pstr));
    UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(myResponse);
#if 0
    {
        CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse);
        fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
        CFRelease(d);
    }
#endif

    if (
        psz_username
        && psz_password
        && (statusCode == 401 || statusCode == 407)
    )
    {
        s_username = CFStringCreateWithCString(kCFAllocatorDefault, psz_username, kCFStringEncodingUTF8);
        s_password = CFStringCreateWithCString(kCFAllocatorDefault, psz_password, kCFStringEncodingUTF8);
        if (!CFHTTPMessageAddAuthentication(myRequest, myResponse, s_username, s_password, kCFHTTPAuthenticationSchemeDigest, FALSE))
        {
            SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "CFHTTPMessageAddAuthentication failed"));
        }

#if 0
        {
            CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest);
            fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
            CFRelease(d);
        }
#endif

        CFRelease(s_username);
        s_username = NULL;

        CFRelease(s_password);
        s_password = NULL;

        CFRelease(myResponse);
        myResponse = NULL;

        if (pPath)
        {
            SG_ERR_IGNORE(  SG_fsobj__remove__pathname(pCtx, pPath)  );
            SG_ERR_CHECK(  perform_request__file(pCtx, myRequest, &myResponse, pPath, b_progress)  );
        }
        else
        {
            SG_STRING_NULLFREE(pCtx, pstr);
            SG_ERR_CHECK(  perform_request__string(pCtx, myRequest, &myResponse, &pstr)  );
        }
#if 0
        {
            CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse);
            fprintf(stderr, "%s\n", CFDataGetBytePtr(d));
            CFRelease(d);
        }
#endif
        statusCode = CFHTTPMessageGetResponseStatusCode(myResponse);
    }

    if (statusCode != 200)
    {
        if (401 == statusCode)
        {
            SG_ERR_THROW(SG_ERR_HTTP_401);
        }
        else if (404 == statusCode)
        {
            SG_ERR_THROW(SG_ERR_HTTP_404);
        }
        else if (502 == statusCode)
        {
            SG_ERR_THROW(SG_ERR_HTTP_502);
        }
        else
        {
            SG_ERR_THROW2(SG_ERR_SERVER_HTTP_ERROR, (pCtx, "%d", (int) statusCode));
        }
    }

    if (ppstr)
    {
        *ppstr = pstr;
        pstr = NULL;
    }

    /* fall through */

fail:
    if (s_username)
    {
        CFRelease(s_username);
        s_username = NULL;
    }

    if (s_password)
    {
        CFRelease(s_password);
        s_password = NULL;
    }

    if (myRequest)
    {
        CFRelease(myRequest);
        myRequest = NULL;
    }

    if (myResponse)
    {
        CFRelease(myResponse);
        myResponse = NULL;
    }

    SG_STRING_NULLFREE(pCtx, pstr);
}