Last active
August 29, 2015 14:25
-
-
Save p120ph37/8281362ae9da042f3043 to your computer and use it in GitHub Desktop.
libcurl basic-auth soap example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* HTTP POST with authentiction using "basic" method. | |
* Hybrid of anyauthput.c and postinmemory.c | |
* Specifically adapted for SOAP use. | |
* | |
* Usage: | |
* cc basicauthsoap.c -lcurl -o basicauthsoap | |
* ./basicauthsoap | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <curl/curl.h> | |
struct MemoryStruct { | |
char *memory; | |
size_t size; | |
}; | |
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *context) { | |
size_t bytec = size * nmemb; | |
struct MemoryStruct *mem = (struct MemoryStruct *)context; | |
mem->memory = realloc(mem->memory, mem->size + bytec + 1); | |
if(mem->memory == NULL) { | |
printf("not enough memory (realloc returned NULL)\n"); | |
return 0; | |
} | |
memcpy(&(mem->memory[mem->size]), ptr, bytec); | |
mem->size += bytec; | |
mem->memory[mem->size] = 0; | |
return nmemb; | |
} | |
static size_t xmlEscape(char *out, char *in) { | |
int i, j = 0; | |
for(i = 0; in[i] != 0; i++) { | |
// encoding non-ASCII characters is beyond the scope of this example... | |
if((unsigned char)in[i] > 127) abort(); | |
switch(in[i]) { | |
case '"': | |
if(out) sprintf(out+j, """); j += 6; break; | |
case '\'': | |
if(out) sprintf(out+j, "'"); j += 6; break; | |
case '<': | |
if(out) sprintf(out+j, "<"); j += 4; break; | |
case '>': | |
if(out) sprintf(out+j, ">"); j += 4; break; | |
case '&': | |
if(out) sprintf(out+j, "&"); j += 5; break; | |
default: | |
if(out) out[j] = in[i]; j++; | |
} | |
} | |
if(out) out[j] = 0; | |
return j; | |
} | |
static size_t compose_soap_frobnicate(char *buf, size_t size, char *foo, char *bar, char *baz) { | |
char fooEsc[xmlEscape(NULL, foo) + 1]; xmlEscape(fooEsc, foo); | |
char barEsc[xmlEscape(NULL, bar) + 1]; xmlEscape(barEsc, bar); | |
char bazEsc[xmlEscape(NULL, baz) + 1]; xmlEscape(bazEsc, baz); | |
return snprintf(buf, size, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" | |
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" | |
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" | |
" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" | |
"<soap:Body>" | |
"<frobnicate xmlns=\"http://example.com/frobnicate\">" | |
"<foo>%s</foo>" | |
"<bar>%s</bar>" | |
"<baz>%s</baz>" | |
"</frobnicate>" | |
"</soap:Body>" | |
"</soap:Envelope>", | |
fooEsc, barEsc, bazEsc); | |
} | |
int main(void) { | |
CURL *curl; | |
CURLcode res; | |
struct MemoryStruct chunk; | |
chunk.memory = malloc(1); | |
chunk.size = 0; | |
chunk.memory[chunk.size] = 0; | |
curl_global_init(CURL_GLOBAL_ALL); | |
curl = curl_easy_init(); | |
if(curl) { | |
curl_easy_setopt(curl, CURLOPT_URL, "https://ameriwether.com/cgi-bin/info.pl"); | |
size_t soap_size = compose_soap_frobnicate(NULL, 0, "'Ein'", ">Zwei<", "\"Drei\"") + 1; | |
char soap[soap_size]; | |
compose_soap_frobnicate(soap, soap_size, "'Ein'", ">Zwei<", "\"Drei\""); | |
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, soap); | |
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC); | |
curl_easy_setopt(curl, CURLOPT_USERNAME, "user"); | |
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password"); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); | |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); | |
struct curl_slist *headers = NULL; | |
headers = curl_slist_append(headers, "Content-Type: text/xml; charset=utf-8"); | |
headers = curl_slist_append(headers, "SOAPAction: \"https://ameriwether.com/cgi-bin/info.pl/frobnicate\""); | |
headers = curl_slist_append(headers, "Accept: text/plain"); // Example output easier to read as plain text. | |
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | |
// Make the example URL work even if your CA bundle is missing. | |
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); | |
res = curl_easy_perform(curl); | |
if(res != CURLE_OK) { | |
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); | |
} else { | |
printf("%s\n",chunk.memory); | |
} | |
// Remember to call the appropriate "free" functions. | |
curl_slist_free_all(headers); | |
curl_easy_cleanup(curl); | |
free(chunk.memory); | |
curl_global_cleanup(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is what it looks like when run:
The source for the CGI that is generating this response can be found here: https://gist.github.com/p120ph37/3bf6c500e0f00ab635da