Dear All, When sending the following custom request to imap server:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "fetch 1 rfc822" ); libcurl yields unexpected results producing simply * 1 FETCH (RFC822 {764347} This applies to both, the default setup that prints to stdout, as well as to a program with registered custom CURLOPT_WRITEFUNCTION handler. In the latter case, however, we can investigate the internal curl buffer, passed as the first argument to the handler BEYOND the number of bytes passed to the handler in the other parameters (even though it is technically UB). And it turns out, that the information that is supposed to be returned by FETCH seems to be there, but for some reason libcurl chooses to discard it. I'm aware that this 'bug' was previously reported here : https://github.com/curl/curl/issues/2055 with conclusion "This does not appear to be a bug in curl", perhaps because of the lack of communication with the guy who reported it. I also realise that (according to this link) there are alternative ways of retrieving this information, which may be better than direct FETCH. However, it does certainly seems to be a bug, or at least highly unexpected behavior -- the information that is supposed to be produced be FETCH is in the buffer -- simply libcurl does not want to disclose it for some misterious reason. In any case, if custom request are supported, they should produce what they are supposed to [BTW, I really love libcurl, even though I'm just starting to use it, otherwise I would not bother to report this bug]. I'm on Ubuntu 20.04, using libcurl shipped with my distro, and g++ as a compiler; curl_version() yields: libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3 A c++ file wich shows the problem is in the attachment -- simply switch between writeCallback and writeCallback_UB (the latter gives what I need). Best wishes, Adrian
// This is a modification od imap-ssl.c file #include<string> #include<iostream> std::size_t writeCallback(char *contents, size_t size, size_t nmemb, void *userp) { ((std::string*)userp)->append(contents,size * nmemb); return size * nmemb; } // This version is UB, because this overload of append expects null-terinated // string -- there is however no other option to chceck the content of // contents buffer, beyond size * nmemb bytes, // and it is this overload that seems to produce expected reponse to fetch request // below std::size_t writeCallback_UB(char *contents, size_t size, size_t nmemb, void *userp) { ((std::string*)userp)->append(contents); return size * nmemb; } #include <stdio.h> #include <curl/curl.h> int main(void) { // std::cout << curl_version() << std::endl; CURL *curl; CURLcode res = CURLE_OK; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_USERNAME, "..."); curl_easy_setopt(curl, CURLOPT_PASSWORD, "..."); curl_easy_setopt(curl, CURLOPT_URL, "imaps://poczta.interia.pl:993"); // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); std::string readBuffer; curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback_UB); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); res = curl_easy_perform(curl); if(res != CURLE_OK){ std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl ; curl_easy_cleanup(curl); return EXIT_FAILURE; } std::cout << "[Buffer:] " << std::endl; std::cerr << readBuffer << std::endl; // clear the buffer: readBuffer.clear(); std::cout << "\n\n[Now custom request:]\n\n" << std::endl; curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, R"(SELECT "INBOX")" ); res = curl_easy_perform(curl); std::cout << "[Buffer:] " << std::endl; std::cerr << readBuffer << std::endl; if(res != CURLE_OK){ std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl ; curl_easy_cleanup(curl); return EXIT_FAILURE; } std::cout << "[Now CURLOPT_CUSTOMREQUEST]: " << std::endl; readBuffer.clear(); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, R"(fetch 1 rfc822)" ); res = curl_easy_perform(curl); if(res != CURLE_OK){ std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl ; curl_easy_cleanup(curl); return EXIT_FAILURE; } std::cout << "[Buffer :]" << readBuffer <<std::endl; /* Always cleanup */ curl_easy_cleanup(curl); } return (int)res; }
-- Unsubscribe: https://lists.haxx.se/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.html