cURL 发布模式参数无效
cURL Release Mode Invalid Parameter
我正在开发一个 C++ 程序,该程序使用 cURL 来“登录”我的 Valorant 帐户。该代码在调试模式下运行良好(Visual Studio 2019),但当我切换到发布模式时出现无效参数错误。做了一些研究后,我发现这是因为 libcurl,但网上没有修复。我还使用 json 和一小段用于 base64 解码的代码片段,但我认为这些无关紧要。我的项目属性是默认属性,我什至尝试创建一个新项目并复制我的代码,但得到了相同的结果。
代码:
#include <iostream>
#include "json.hpp"
#include <curl/curl.h>
#include <string>
#include <sstream>
#include "base64.hpp"
#include <stdio.h>
using json = nlohmann::json;
CURL* hnd = curl_easy_init();
size_t WriteCallback(char* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void authCookies()
{
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"client_id\":\"play-valorant-web-prod\",\"nonce\":\"1\",\"redirect_uri\":\"https://playvalorant.com/opt_in\",\"response_type\":\"token id_token\"}");
CURLcode ret = curl_easy_perform(hnd);
}
std::string getAuthToken(std::string username, std::string password)
{
std::string token = "";
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
std::string response;
json toSend = {
{"type", "auth"},
{"username", username},
{"password", password},
{"remember", false},
{"language", "en_US"}
};
std::string sendText = toSend.dump(4);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, sendText.c_str());
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
json resp = json::parse(response);
//parse the uri and look for a token
std::string uri = std::string(resp["response"]["parameters"]["uri"]);
size_t loc = uri.find("#access_token=");
for (int i = loc + 14; i < uri.length(); i++)
{
if (uri[i] != '&') { token += uri[i]; }
else { break; }
}
return token;
}
void cookieReauth()
{
std::string response;
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/authorize?redirect_uri=https%3A%2F%2Fplayvalorant.com%2Fopt_in&client_id=play-valorant-web-prod&response_type=token%20id_token");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
}
std::string getEntitlement(std::string token)
{
std::string out = "";
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "https://entitlements.auth.riotgames.com/api/token/v1");
struct curl_slist* headers = NULL;
std::string auth = "Authorization: Bearer " + token;
headers = curl_slist_append(headers, auth.c_str());
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &out);
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
CURLcode ret = curl_easy_perform(hnd);
json resp = json::parse(out);
return std::string(resp["entitlements_token"]);
}
struct valorantUser
{
std::string displayName;
std::string puuid;
std::string name;
std::string tag;
};
std::vector<valorantUser> getUsersByPuuid(std::string token, std::string entitlement, json puuidList, std::string region)
{
std::vector<valorantUser> userList;
std::string response;
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL, std::string("https://pd." + region + ".a.pvp.net/name-service/v2/players").c_str());
struct curl_slist* headers = NULL;
std::string auth = "Authorization: Bearer " + token;
std::string ent = "Entitlements: " + entitlement;
headers = curl_slist_append(headers, auth.c_str());
headers = curl_slist_append(headers, ent.c_str());
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
std::string toSend = puuidList.dump();
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, toSend.c_str());
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
json resData = json::parse(response);
for (int i = 0; i < resData.size(); i++)
{
valorantUser dat;
dat.displayName = std::string(resData[i]["DisplayName"]);
dat.puuid = std::string(resData[i]["Subject"]);
dat.name = std::string(resData[i]["GameName"]);
dat.tag = std::string(resData[i]["TagLine"]);
userList.push_back(dat);
}
return userList;
}
std::string getTokenPuuid(std::string token)
{
std::vector<std::string> toks;
std::stringstream test(token);
std::string cur;
while (std::getline(test, cur, '.'))
{
toks.push_back(cur);
}
json decoded = json::parse(base64_decode(toks[1]));
return decoded["sub"];
}
int main()
{
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
authCookies(); //get auth cookies
std::string token = getAuthToken("username", "password"); //get auth token
cookieReauth(); //get more auth cookies
std::string entitlement = getEntitlement(token); //get entitlement token
std::string puuid = getTokenPuuid(token); //get user puuid from token
json puuidList = json::array({puuid});
valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid
std::cout << "Signed in as " << botData.name << "#" << botData.tag;
}
谢谢
编辑:
通过注释掉我所有的功能,错误停止了。如果我什至从 authCookies() 函数中删除评论,错误又回来了。也是很奇怪,直到代码结束才出现错误
int main()
{
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
/*
authCookies(); //get auth cookies
std::string token = getAuthToken("username", "password"); //get auth token
cookieReauth(); //get more auth cookies
std::string entitlement = getEntitlement(token); //get entitlement token
std::string puuid = getTokenPuuid(token); //get user puuid from token
json puuidList = json::array({ puuid });
valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid
std::cout << "Signed in as " << botData.name << "#" << botData.tag;*/
curl_easy_cleanup(hnd);
return 0;
}
当调用 authCookies()
时,WriteCallback
将 userp
设置为 (void*)stdout
(如果未分配 CURLOPT_WRITEDATA
则为默认值)。 ((std::string*)userp)->append((char*)contents, size * nmemb);
将 FILE*
取消引用为 std::string*
。
为什么要将 char* contents
转换为 char*
?
我正在开发一个 C++ 程序,该程序使用 cURL 来“登录”我的 Valorant 帐户。该代码在调试模式下运行良好(Visual Studio 2019),但当我切换到发布模式时出现无效参数错误。做了一些研究后,我发现这是因为 libcurl,但网上没有修复。我还使用 json 和一小段用于 base64 解码的代码片段,但我认为这些无关紧要。我的项目属性是默认属性,我什至尝试创建一个新项目并复制我的代码,但得到了相同的结果。 代码:
#include <iostream>
#include "json.hpp"
#include <curl/curl.h>
#include <string>
#include <sstream>
#include "base64.hpp"
#include <stdio.h>
using json = nlohmann::json;
CURL* hnd = curl_easy_init();
size_t WriteCallback(char* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void authCookies()
{
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"client_id\":\"play-valorant-web-prod\",\"nonce\":\"1\",\"redirect_uri\":\"https://playvalorant.com/opt_in\",\"response_type\":\"token id_token\"}");
CURLcode ret = curl_easy_perform(hnd);
}
std::string getAuthToken(std::string username, std::string password)
{
std::string token = "";
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
std::string response;
json toSend = {
{"type", "auth"},
{"username", username},
{"password", password},
{"remember", false},
{"language", "en_US"}
};
std::string sendText = toSend.dump(4);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, sendText.c_str());
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
json resp = json::parse(response);
//parse the uri and look for a token
std::string uri = std::string(resp["response"]["parameters"]["uri"]);
size_t loc = uri.find("#access_token=");
for (int i = loc + 14; i < uri.length(); i++)
{
if (uri[i] != '&') { token += uri[i]; }
else { break; }
}
return token;
}
void cookieReauth()
{
std::string response;
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/authorize?redirect_uri=https%3A%2F%2Fplayvalorant.com%2Fopt_in&client_id=play-valorant-web-prod&response_type=token%20id_token");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
}
std::string getEntitlement(std::string token)
{
std::string out = "";
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "https://entitlements.auth.riotgames.com/api/token/v1");
struct curl_slist* headers = NULL;
std::string auth = "Authorization: Bearer " + token;
headers = curl_slist_append(headers, auth.c_str());
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &out);
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
CURLcode ret = curl_easy_perform(hnd);
json resp = json::parse(out);
return std::string(resp["entitlements_token"]);
}
struct valorantUser
{
std::string displayName;
std::string puuid;
std::string name;
std::string tag;
};
std::vector<valorantUser> getUsersByPuuid(std::string token, std::string entitlement, json puuidList, std::string region)
{
std::vector<valorantUser> userList;
std::string response;
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL, std::string("https://pd." + region + ".a.pvp.net/name-service/v2/players").c_str());
struct curl_slist* headers = NULL;
std::string auth = "Authorization: Bearer " + token;
std::string ent = "Entitlements: " + entitlement;
headers = curl_slist_append(headers, auth.c_str());
headers = curl_slist_append(headers, ent.c_str());
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
std::string toSend = puuidList.dump();
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, toSend.c_str());
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
CURLcode ret = curl_easy_perform(hnd);
json resData = json::parse(response);
for (int i = 0; i < resData.size(); i++)
{
valorantUser dat;
dat.displayName = std::string(resData[i]["DisplayName"]);
dat.puuid = std::string(resData[i]["Subject"]);
dat.name = std::string(resData[i]["GameName"]);
dat.tag = std::string(resData[i]["TagLine"]);
userList.push_back(dat);
}
return userList;
}
std::string getTokenPuuid(std::string token)
{
std::vector<std::string> toks;
std::stringstream test(token);
std::string cur;
while (std::getline(test, cur, '.'))
{
toks.push_back(cur);
}
json decoded = json::parse(base64_decode(toks[1]));
return decoded["sub"];
}
int main()
{
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
authCookies(); //get auth cookies
std::string token = getAuthToken("username", "password"); //get auth token
cookieReauth(); //get more auth cookies
std::string entitlement = getEntitlement(token); //get entitlement token
std::string puuid = getTokenPuuid(token); //get user puuid from token
json puuidList = json::array({puuid});
valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid
std::cout << "Signed in as " << botData.name << "#" << botData.tag;
}
谢谢
编辑: 通过注释掉我所有的功能,错误停止了。如果我什至从 authCookies() 函数中删除评论,错误又回来了。也是很奇怪,直到代码结束才出现错误
int main()
{
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
/*
authCookies(); //get auth cookies
std::string token = getAuthToken("username", "password"); //get auth token
cookieReauth(); //get more auth cookies
std::string entitlement = getEntitlement(token); //get entitlement token
std::string puuid = getTokenPuuid(token); //get user puuid from token
json puuidList = json::array({ puuid });
valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid
std::cout << "Signed in as " << botData.name << "#" << botData.tag;*/
curl_easy_cleanup(hnd);
return 0;
}
当调用 authCookies()
时,WriteCallback
将 userp
设置为 (void*)stdout
(如果未分配 CURLOPT_WRITEDATA
则为默认值)。 ((std::string*)userp)->append((char*)contents, size * nmemb);
将 FILE*
取消引用为 std::string*
。
为什么要将 char* contents
转换为 char*
?