Sending post request with libcurl - c++

I am trying to login to Twitter via CURL.
This is my code:
#include <iostream>
#include <string>
#include <curl\curl.h>
#include <sstream>
using std::string;
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
std::string buf = std::string(static_cast<char *>(ptr), size * nmemb);
std::stringstream *response = static_cast<std::stringstream *>(stream);
response->write(buf.c_str(), (std::streamsize)buf.size());
return size * nmemb;
}
int main(int argc, char*argv[])
{
std::string target = "https://twitter.com/login";
CURL *curl;
CURLcode res;
std::stringstream response;
char* data = "session[username_or_email]=user&session[password]=pass";
struct curl_slist *chunk = NULL;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, target.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
}
std::cout << response.str() << std::endl;
cin.ignore();
return 0;
}
And I'm getting this message:
403 Forbidden: The server understood the request, but is refusing to
fulfill it
What should I do?

I suggest your request is (correctly) being identified as coming from a program not a human, and therefore denied.
It will be a matter of capturing all the right headers and cookies from a "real" (ie browser) session... But really, I think you'd be better off working with the Twitter api, as that is what it's designed for.

Related

Store the result from curl get request for use in another function C++

Trying to store the data out of the function and use it for another function from res variable, but still to no avail.
Been able to extract the data from the website and looks like this:
Approximate: 19879888
#include <stdio.h>
#include <iostream>
using namespace std;
#define CURL_STATICLIB
#include <curl/curl.h>
int main()
{
CURLcode res;
CURL* curl = curl_easy_init();
struct curl_slist* header = NULL;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "website for c++ practice");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
Been searching a lot already but cant find a direct answer. Help would be greatly appreciated!
Use the CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA options to save the content to a variable, eg:
#include <iostream>
#include <string>
using namespace std;
#define CURL_STATICLIB
#include <curl/curl.h>
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
size_t total = size * nmemb;
static_cast<string*>(userdata)->append(ptr, total);
return total;
}
int main()
{
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "website for c++ practice");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
string data;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
CURLcode res = curl_easy_perform(curl);
// use res and data as needed...
curl_easy_cleanup(curl);
}
return 0;
}

Logging into an off branch of a site using cURL for c++

I wrote this piece of code to automate a mundane activity i have to do everyday,
the first step is to log into the site so i wrote some simple cURL code and i got that to work by POSTing the required fields
#include<curl/curl.h>
#include<string>
#include<iostream>
#include <sstream>
#include<vector>
using namespace std;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void main()
{
string readBuffer,readBuffer2,url,url2;
url = "https://example/login/index.php";
auto curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36");
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_REFERER,url.c_str());
istringstream iss(readBuffer);
vector<string> c;
do {
string word;
iss >> word;
c.push_back(word);
} while (iss);
string check = "name=\"logintoken\"" ;
string token;
for (int i=200;i<c.size(); i++)
{
if (c[i] == check)
token =c[i+1];
}
cout << token;
string finaltoken;
for (int i = token.size() - 3; i > 6; i--)
{
finaltoken = token[i]+finaltoken;
}
string adds = "logintoken="+finaltoken+"&username=USERNAME&password=PASSWORD";
readBuffer = readBuffer + "\n--------------------------------------------------";
curl_easy_setopt(curl , CURLOPT_POSTFIELDS, adds.c_str());
curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
cout<< readBuffer;
}
Im able to login fine to the main landing page of the site with this, but my task requires me to go to an off branch of this site.
The way i decided to work around this was instead of going to the login page and doing multiple GETs was to go directly to the off branch link https://example/mod/attendance/view.php?id="some number". as i would be logged out it would ask me to login and id be redirected to the page where i want to be at. For some reason im not able to login and i cant figure out why i can login from the main page but not from the other pages. (i can log in to off branches via browser though)
Using chromes webdev tools there isnt any difference in the POSTed data for both logins
any help would be greatly appreciated
I got the solution, turns out you just need to use the COOKIEJAR method to store the cookies.
So i logged in to the main page once and used the cookies from that session to login to the off branch page like so
#include<curl/curl.h>
#include<string>
#include<iostream>
#include <sstream>
#include<vector>
using namespace std;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void main()
{
string readBuffer,readBuffer2,url,url2;
url = "https://example/login/index.php";
url2 = "https://example/mod/attendance/view.php?id=no";
auto curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36");
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_perform(curl);
istringstream iss(readBuffer);
vector<string> c;
do {
string word;
iss >> word;
c.push_back(word);
} while (iss);
string check = "name=\"logintoken\"" ;
string token;
for (int i=200;i<c.size(); i++)
{
if (c[i] == check)
token =c[i+1];
}
cout << token;
string finaltoken;
for (int i = token.size() - 3; i > 6; i--)
{
finaltoken = token[i]+finaltoken;
}
string adds = "logintoken="+finaltoken+"&username=USERNAME&password=PASSWORD";
readBuffer = "";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, adds.c_str());
//curl_easy_setopt(curl, CURLOPT_REFERER, url.c_str());
curl_easy_perform(curl);
readBuffer = "";
curl_easy_setopt(curl, CURLOPT_URL, url2.c_str());
curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
cout<< readBuffer;
}

Curl data from Steam community market

I've been trying to fetch data from steam community market ,
Code :
#include <iostream>
#include <string>
#include <curl/curl.h>
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://steamcommunity.com/market/priceoverview/?market_hash_name=AK-47%20%7C%20Redline%20%28Field-Tested%29&appid=730&currency=1");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
std::cout << readBuffer << std::endl;
}
return 0;
}
But when I run it , nothing show up .
Any help is appreciated ,
Thanks
curl doesn't follow redirects by default, and the site you mention uses those.
I had to turn on CURLOPT_FOLLOWLOCATION to make it work:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // redirects
// bonus:
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L); // corp. proxies etc.
Possible output:
{"success":true,"lowest_price":"$19.00","volume":"477","median_price":"$18.95"}
While debugging, you may want this option too to see what curl is up to:
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

C++ Telegram Bot POST request for updates no result

I'm tring to create a telegram bot. I' m first trying to get updates from the bot like said in the Telegram API with /getUpdates method.
With Postman the request is working good and I have all the data in json format.
Using cUrl I have no response and res is 0. Here there is the snippet of code:
#include <iostream>
#include <curl/curl.h>
#include <string>
using namespace std;
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void getUpdates()
{
std::string readBuffer;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "http://api.telegram.org/BOTTOKEN/getUpdates");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
std::cout << "Buffer content"<<readBuffer << std::endl;
long code = -1;
curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &code );
std::cout<<"HTTP Response Code: "<< code <<std::endl;
std::cout<<"Res: "<<res<<std::endl;
res = curl_easy_perform(curl);
}
}
int main()
{
getUpdates();
return 0;
}
Buffer content is empty and res is 0.
Could you give me any hints? Thank you!
I solved it! Here there is the updated code:
void getUpdates()
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "http://api.telegram.org/botyourtoken/getUpdates");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
std::cout << "Buffer content: "<<std::endl;
std::cout<<readBuffer << std::endl;
}
curl_easy_cleanup(curl);
}
Thank you!

How to rewrite POST request from python to C++ with curl

I have POST request on python with a lot of settings, and I don't uderstand how their look like in curl.
data_str = '{' + '"username": "{}", "domain_id": {}, "password": {}'.format(login, domain_id, password) + '}'
try:
data = requests.post("https://example.com/v/session",
proxies=proxy,
verify=False,
data=data_str,
headers={"Content-Type": "application/json;charset=UTF-8",
"Accept": "application/json"})
if is_json(data.text):
print(data)
I find that url set parament CURLOPT_URL, headers - CURLOPT_HTTPHEADER. But how set proxy, verify, data ? How get json as in python ?
how to complete the code that it have the same result as in python:
CURL *curl = curl_easy_init();
struct curl_slist *list = NULL;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
list = curl_slist_append(list, "Shoesize: 10");
list = curl_slist_append(list, "Accept:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
curl_easy_perform(curl);
curl_slist_free_all(list); /* free the list again */
}
In order to get the return data from the curl request, we need a callback function for the CURLOPT_WRITEFUNCTION option.
The proxy, data, verify parameters should be set as following :
#include <iostream>
#include <string>
#include <curl/curl.h>
size_t curlWriter(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
try
{
s->append((char*)contents, newLength);
}
catch(std::bad_alloc &e)
{
//memory problem
return 0;
}
return newLength;
}
int main()
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl)
{
std::string strResponse;
std::string strPostData = "my data post";
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/v/session");
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
//set the proxy
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.net");
curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080L);
//verify=False. SSL checking disabled
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//set the callback function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriter);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strPostData.length() );
/* pass in a pointer to the data - libcurl will not copy */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPostData.c_str() );
/* Execute the request */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
std::cerr << "CURL error : " << curl_easy_strerror(res) << std::endl;
}else {
std::cout << "CURL result : " << strResponse << std::endl;
}
curl_easy_cleanup(curl);
}
}