C CURL programming - c

I am building a C program that uses libcurl to send a XML file by
HTTP POST.
I am sending SOAP request and the response should be saved in an xml file
The program is:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define URL "http://192.168.1.159:8200/ctl/ContentDir"
size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fwrite(ptr,size,nmeb,stream);
}
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,stream);
}
int main(char * Browse_request, char * response)
{
FILE * rfp = fopen("Browse_request.xml", "r");
if(!rfp) {
perror("Read File Open:");
}
FILE * wfp = fopen("response.xml", "w+"); //File pointer to write the soap response
if(!wfp) {
perror("Write File Open:");
}
struct curl_slist *header = NULL;
header = curl_slist_append (header, "Content-Type:text/xml; Charset=UTF-8");
header = curl_slist_append (header, "SOAPAction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse");
header = curl_slist_append (header, "Content-Length:0");
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data); //Reads xml file to be sent via POST operation
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
curl_easy_setopt(curl, CURLOPT_VERBOSE,1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
}
It gives an error, 400 bad request.
If I do the same using command line, i am getting expected result and the result is saved in response.xml. the command that i use is:
curl -v -o response.xml -H "Content-Type: text/xml; Charset="UTF-8"" -H "SOAPAction: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"" -d #Browse_request.xml -X POST http://192.168.1.159:8200/ctl/ContentDir
my browse_request.xml which is same for command line and program is:
<?xml version = "1.0" encoding="utf-8"?>
<s:Envelope
xmlns:s = "http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:Browse xmlns:u="urn:schemas-upnp-org:Service:ContentDirectory:1">
<ObjectID>0</ObjectID>
<BrowseFlag>BrowseDirectChildren</BrowseFlag>
<Filter>*</Filter>
<StartingIndex>1</StartingIndex>
<RequestedCount>5</RequestedCount>
<SortCriteria></SortCriteria>
</u:Browse>
</s:Body>
</s:Envelope>
when i try to implement using c program, why is it giving 400 bad request
thanks in advance

Related

How to send SOAP(xml over http) Post request and parse result using libcurl

I am trying to connect a C program to a SOAP Server all running in localhost.
I have this test example but I don't know how to integrate it into my C code with libcurl:
POST /otd HTTP/1.1
User-Agent: OT
Host: localhost:9002
Content-Length: 196
Connection: Close
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<doSome/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here is a libcurl example that I found, but can't figure out how to integrate my xml Post that I provided above and how to get response and parse it on my own:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define URL "localhost:9002"
size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fwrite(ptr,size,nmeb,stream);
}
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,stream);
}
int sendMessage (char * inFile, char * outFile) {
//writing to file initially
FILE * rfp = fopen(inFile, "r");
if(!rfp) {
perror("Read File Open:");
// exit(0);
}
FILE * wfp = fopen(outFile, "w+"); //File pointer to write the soap response
if(!wfp) {
perror("Write File Open:");
// exit(0);
}
struct curl_slist *header = NULL;
header = curl_slist_append (header, "POST /otd HTTP/1.1");
header = curl_slist_append (header, "User-Agent: OpenTrackDispatcher");
header = curl_slist_append (header, "Host: localhost:9002");
header = curl_slist_append (header, "Content-Length: 196");
header = curl_slist_append (header, "Connection: Close");
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data); //Reads xml file to be sent via POST operation
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
// curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_VERBOSE,1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
};
ps: my module needs to continuously request data from the SOAP server (each second!)..

curl implementation using c for SOAP

I am building a C program that uses libcurl to send a XML file by
HTTP POST. This is a part of SOAP implementation in UPnP
I am sending SOAP request and the response should be saved in an xml file
The program is:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define URL "http://192.168.1.159:8200/ctl/ContentDir"
size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fwrite(ptr,size,nmeb,stream);
}
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,stream);
}
int main(char * Browse_request, char * response)
{
FILE * rfp = fopen("Browse_request.xml", "r");
if(!rfp) {
perror("Read File Open:");
}
FILE * wfp = fopen("response.xml", "w+"); //File pointer to write the soap response
if(!wfp) {
perror("Write File Open:");
}
struct curl_slist *header = NULL;
header = curl_slist_append (header, "Content-Type:text/xml; Charset=UTF-8");
header = curl_slist_append (header, "SOAPAction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse");
header = curl_slist_append (header, "Content-Length:0");
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data); //Reads xml file to be sent via POST operation
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
curl_easy_setopt(curl, CURLOPT_VERBOSE,1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
}
It gives an error, 400 bad request.
If I do the same using command line, i am getting expected result and the result is saved in response.xml. the command that i use is:
curl -v -o response.xml -H "Content-Type: text/xml; Charset="UTF-8"" -H "SOAPAction: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"" -d #Browse_request.xml -X POST http://192.168.1.159:8200/ctl/ContentDir
my browse_request.xml which is same for command line and program is:
<?xml version = "1.0" encoding="utf-8"?>
<s:Envelope
xmlns:s = "http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:Browse xmlns:u="urn:schemas-upnp-org:Service:ContentDirectory:1">
<ObjectID>0</ObjectID>
<BrowseFlag>BrowseDirectChildren</BrowseFlag>
<Filter>*</Filter>
<StartingIndex>1</StartingIndex>
<RequestedCount>5</RequestedCount>
<SortCriteria></SortCriteria>
</u:Browse>
</s:Body>
</s:Envelope>
when i try to implement using c program, why is it giving 400 bad request
thanks in advance

How to download a ZIP file from server using cURL in C?

I am developing on Linux platform. I am using libcurl and able to receive json response and saving it to file. Below is the code.
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <string.h>
#define URL "http://www.joes-hardware.com/tools.html"
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void) {
CURL *curl;
FILE *fp;
CURLcode res;
//const char url[] = "http://www.joes-hardware.com/tools.html";
char *url= URL;
char outfilename[FILENAME_MAX] = "./json";
curl = curl_easy_init();
if (curl) {
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
Now I need to fetch a zip file from the server. Suppose the URL is of the format shown below:
#define URL "https://Server/File.zip"
For such URL, the code is not able to save the zip file.
How to achieve this?
I resolved the issue. The problem was with HTTPS connection. I had to add certificates for HTTPS.
Based on below links:
Can't connect to HTTPS site using cURL. Returns 0 length content instead
Getting no content from a HTTPS connection using CURL
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <string.h>
#include <stdlib.h>
#define false 0
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void) {
CURL *curl;
FILE *fp;
CURLcode res;
const char url[] = "https://example.com/filename.zip";
const char outfilename[FILENAME_MAX] = "./json.zip";
curl_version_info_data * vinfo = curl_version_info(CURLVERSION_NOW);
if(vinfo->features & CURL_VERSION_SSL){
printf("CURL: SSL enabled\n");
}else{
printf("CURL: SSL not enabled\n");
}
curl = curl_easy_init();
if (curl) {
fp = fopen(outfilename,"wb");
/* Setup the https:// verification options. Note we */
/* do this on all requests as there may be a redirect */
/* from http to https and we still want to verify */
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CAINFO, "./ca-bundle.crt");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
int i=fclose(fp);
if( i==0)
system("unzip -j json.zip");
}
return 0;
}

Curl in C - don't print html code

I'm using Curl in C, but I don't want to echo the webpage code:
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "www.example.com");
curl_easy_perform(curl);
curl_easy_cleanup(curl);
Is there any Curl option for this?
I found a good solution for this problem:
size_t function(void *ptr, size_t size, size_t nmemb, FILE *stream) {
return fwrite(ptr, size, nmemb, stream);
}
...
FILE *outfile;
outfile = fopen("test", "w");
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "www.example.com");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
You can print the html code in in a file and don't print it in the "console"

SOAP Request and Response Read from and to file using libcurl - C

I am trying to send a SOAP request from a xml file and send to a SOAP service and then read the response while saving it into a file, using libcurl.
An example request in an xml file is as followed:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:olm="http://127.0.0.1:1090/services/olmDSMN">
<soapenv:Header/>
<soapenv:Body>
<olm:getAllCommercialProducts soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</soapenv:Body>
</soapenv:Envelope>
The libcurl code I'm trying to use to make the read and write is as follows:
#define URL "http://192.168.56.101:8088/olmDSMN"
size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fwrite(ptr,size,nmeb,stream);
}
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,stream);
}
int sendMessage (char * inFile, char * outFile) {
//writing to file initially
FILE * rfp = fopen(inFile, "r");
if(!rfp) {
perror("Read File Open:");
// exit(0);
}
FILE * wfp = fopen(outFile, "w+"); //File pointer to write the soap response
if(!wfp) {
perror("Write File Open:");
// exit(0);
}
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data); //Reads xml file to be sent via POST operationt
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
}
At the moment the above does not work. When the function is invoked is just waits(as if waiting on a response that never comes). I'm just learning libcurl, so I'm sure I've done many things incorrectly. I've really been piecing together a couple different tutorials to get it do what I want it to do. Any assistance would be greatly appreciated.
Ok, so after a whole load of fiddling and piecing together code from different examples I've figured out how to perform the above task. See code below:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define URL "http://192.168.56.101:8088/olmDSMN"
size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fwrite(ptr,size,nmeb,stream);
}
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,stream);
}
int sendMessage (char * inFile, char * outFile) {
//writing to file initially
FILE * rfp = fopen(inFile, "r");
if(!rfp) {
perror("Read File Open:");
// exit(0);
}
FILE * wfp = fopen(outFile, "w+"); //File pointer to write the soap response
if(!wfp) {
perror("Write File Open:");
// exit(0);
}
struct curl_slist *header = NULL;
header = curl_slist_append (header, "Content-Type:text/xml");
header = curl_slist_append (header, "SOAPAction: myur1");
header = curl_slist_append (header, "Transfer-Encoding: chunked");
header = curl_slist_append (header, "Expect:");
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data); //Reads xml file to be sent via POST operationt
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
// curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_VERBOSE,1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
}
Presuming that your SOAP server expects a HTTP POST, you need to:
Set the CURLOPT_POST option;
Set the Content-Type header Content-Type: application/soap+xml using CURLOPT_HTTPHEADER;
Set the size of your XML request using the CURLOPT_POSTFIELDSIZE option.

Resources