如何解决C ++ libcurl响应仅显示响应的第一行
编辑:运行更多命令后,似乎仅显示了以*
开头的行。有什么办法阻止吗?
我正试图在我的C ++程序中使用libcurl库,以使用IMAP协议接收电子邮件。问题在于,来自CURL调用的响应仅返回一行,并切断了应返回的其余内容。我知道请求本身是有效的,因为当我使用curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
启用详细模式时,它在输出中具有完整的结果。
例如,当我使用curl_easy_setopt(curl,"FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])");
时,响应为:
* 10000 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS (DATE FROM SUBJECT)] {140}
当我打开详细模式时,控制台会显示完整结果:
< A003 OK [READ-WRITE] INBOX selected. (Success)
> A004 FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])
< * 10000 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS (DATE FROM SUBJECT)] {140}
< Date: Wed,1 Apr 2020 01:59:45 -0500
< From: [REMOVED NAME] <[REMOVED EMAIL]>
< Subject: Testing subject here
<
< )
< A004 OK Success
我尝试了多种输出数据的方法:将其输出到stdout,一个外部文件以及在内存中(然后打印)。我觉得CURL结果只是由于某种原因没有返回比第一行更多的结果。如果有帮助,下面是代码(我正在使用wxWidgets):
App.cpp -忽略大部分内容,仅调用函数
#include "App.h"
#include "Frame.h"
#include "Config.h"
#include "IMAP.h"
wxIMPLEMENT_APP(App);
bool App::OnInit() {
curl_global_init(CURL_GLOBAL_SSL);
try {
Config config("settings.conf");
for(const auto& account : config["accounts"]) {
const char* url = account["incoming_server"].asCString();
const char* username = account["username"].asCString();
const char* password = account["password"].asCString();
IMAP connection(url,IMAP_DEFAULT_PORT);
if(connection.auth(username,password) == IMAP_SUCCESS) {
connection.select("INBOX");
auto folders = connection.getFolders();
}
}
} catch(std::exception& e) {
std::cerr << e.what() << std::endl;
exit(0);
}
curl_global_cleanup();
exit(1);
Frame *frame = new Frame("MailDuck",wxDefaultPosition,wxSize(100,100));
frame->Show(true);
frame->Centre();
return true;
}
App.cpp
#include "IMAP.h"
IMAP::IMAP(const char *url,int port) {
this->url = url;
this->port = port;
}
IMAP_CODE IMAP::auth(const char *username,const char *password) {
this->username = username;
this->password = password;
if(execute().size == -1) return IMAP_FAILED;
else return IMAP_SUCCESS;
}
std::vector<Folder> IMAP::getFolders() {
std::vector<Folder> folders;
memory mem = execute("FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])");
std::cout << mem.response << std::endl;
free(mem.response);
return folders;
}
IMAP::memory IMAP::execute(const char *command) {
CURL *curl;
CURLcode res = CURLE_OK;
struct memory chunk { (char *) malloc(1),0 };
curl = curl_easy_init();
std::string finalURL;
finalURL.append(this->url);
finalURL.append("/");
finalURL.append(this->mailbox);
if(curl) {
curl_easy_setopt(curl,CURLOPT_USE_SSL,CURLUSESSL_ALL);
curl_easy_setopt(curl,CURLOPT_USERNAME,this->username);
curl_easy_setopt(curl,CURLOPT_PASSWORD,this->password);
curl_easy_setopt(curl,CURLOPT_URL,finalURL.c_str());
curl_easy_setopt(curl,1L);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,(void *)&chunk);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_function);
curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,command);
res = curl_easy_perform(curl);
if(res != CURLE_OK) chunk.size = -1;
curl_easy_cleanup(curl);
} else chunk.size = -1;
if(chunk.size == -1) std::cerr << "ERROR >> Unable to call command: " << command << std::endl;
return chunk;
}
size_t IMAP::write_function(void *data,size_t size,size_t nmemb,void *userp) {
size_t real_size = size * nmemb;
auto *mem = (struct memory *) userp;
char *ptr = (char *) realloc(mem->response,mem->size + real_size + 1);
if(ptr == NULL) return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]),data,real_size);
mem->size += real_size;
mem->response[mem->size] = 0;
return real_size;
}
void IMAP::select(const char *box) {
this->mailbox = box;
}
IMAP.h
#ifndef MAILDUCK_IMAP_H
#define MAILDUCK_IMAP_H
#include <map>
#include <vector>
#include <string>
#include <json/json.h>
#include <curl/curl.h>
#include <iostream>
#include <istream>
enum {
IMAP_DEFAULT_PORT = 993,};
enum IMAP_CODE {
IMAP_SUCCESS = 1,IMAP_FAILED = 0
};
class Folder : public std::vector<Folder> {
public:
std::string name;
};
class IMAP {
private:
const char *url,*username,*password,*mailbox = "";
int port;
struct memory { char *response; size_t size; };
memory execute(const char *command = nullptr);
static size_t write_function(void *data,void *userp);
public:
IMAP(const char *url,int port);
IMAP_CODE auth(const char* username,const char* password);
std::vector<Folder> getFolders();
void select(const char *mailbox);
};
#endif
我对此一直停留了一段时间,因此,我感谢任何人都可以提供的见解。
解决方法
想通了!对于所有像我一样被困住的人:
显然,其余数据卡在标题数据中,因此添加以下内容:
struct memory chunk { (char *) malloc(1),0 };
curl_easy_setopt(curl,CURLOPT_HEADERFUNCTION,header_callback);
curl_easy_setopt(curl,CURLOPT_HEADERDATA,(void *)&chunk);
然后我的写功能与另一个完全一样...
size_t IMAP::header_callback(char *data,size_t size,size_t nmemb,void *userp) {
size_t real_size = size * nmemb;
auto *mem = (struct memory *) userp;
char *ptr = (char *) realloc(mem->response,mem->size + real_size + 1);
if(ptr == NULL) return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]),data,real_size);
mem->size += real_size;
mem->response[mem->size] = 0;
return real_size;
}
现在我得到了完整的答复。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。