由libcurl接收的utf8编码的xml数据的下载导致损坏的字符串

时间:2012-02-23 21:33:12

标签: c++ xml unicode utf-8 libcurl

在使用libcurl实现Amazon S3访问库的项目中,我遇到UTF8问题。列出存储桶内容的方法将适当的请求发送到S3服务器,正确签名和全部。我收到一个xml文档,但数据已损坏。

我把它保存到std :: string中。 例如,它从以下片段开始:

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult

在“ListBucketResult”的最后一个“t”之后,代码中有一个“0”(零),终止了std :: string。在调试器中查看字符串的内容或将它们写入文件会显示此信息,并在不同的位置显示更多的零,例如在某些(但不是全部)“&gt;”关闭括号。

我使用在WinXP上运行的MS Visual Studio 2008,该项目是使用unicode支持编译的。

我应该怎么做才能在std :: string中接收正确的UTF8(根据几个来源,它应该是unicode不可知的)?有关这一个的任何提示吗?

bool Http::Download(std::string& url, std::string& targetString, std::vector<std::string>* customHeaders)
{
    CURLcode result = CURLE_FAILED_INIT;
    dl = true;

    if (curl)
    {
        curl = curl_easy_init();

        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_HEADER, 0);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &targetString);

        if (unsafe)
        {
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        }

        if (customHeaders)
        {
            curl_slist* headers = 0;

            for (std::vector<std::string>::const_iterator iter = customHeaders->begin(); iter != customHeaders->end(); iter++)
            {
                headers = curl_slist_append(headers, (*iter).c_str());
                headers = curl_slist_append(headers, "\n");
            }

            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        }

        result = curl_easy_perform(curl);

        long http_code = 0;
        curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
        lastHttpResult = static_cast<int>(http_code);

        curl_easy_cleanup(curl);
    }

    return (result == CURLE_OK);
};

size_t Http::WriteData(char* data, size_t size, size_t nmemb, void* target)
{
    if(target)
    {
        reinterpret_cast<std::string*>(target)->append(data);
        size_t len = size * nmemb;
        return len;
    }

    return 0;
};

2 个答案:

答案 0 :(得分:1)

这一行很可能是问题的一部分:

reinterpret_cast<std::string*>(target)->append(data);

data不是NULL终止,所以谁知道你在字符串中放了什么。替换为:

reinterpret_cast<std::string*>(target)->append(data, size * nmemb);

答案 1 :(得分:0)

我觉得您应该在WriteData()函数中调用以下内容:

size_t len = size * nmemb;
reinterpret_cast<std::string*>(target)->append(data, len);

CURLOPT_WRITEFUNCTION状态的libcurl文档:

  

ptr指向的数据大小是大小乘以nmemb,它不会被零终止。

因此,您无法依靠append(const char*)正确处理追加。