Поврежденная строка в результате загрузки XML-данных в кодировке utf8, полученных libcurl - PullRequest
0 голосов
/ 24 февраля 2012

В проекте, который реализует библиотеку доступа Amazon S3 с использованием libcurl, у меня проблемы с UTF8.Метод для перечисления содержимого сегмента отправляет соответствующий запрос на сервер S3, правильно подписанный и все.Я получаю XML-документ, но данные повреждены.

Я сохраняю его в std :: string.Например, он начинается со следующего фрагмента:

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

После последнего «t» из «ListBucketResult» в коде присутствует «0» (ноль), заканчивающийся std :: string.Просмотр содержимого строки в отладчике или запись их в файл показывает это, и еще много нулей в разных позициях, например, в некоторых (но не во всех) закрывающих скобках ">".

Я использую MS VisualStudio 2008, работающая на WinXP, проект скомпилирован с поддержкой юникода.

Что я должен сделать, чтобы получить надлежащий UTF8 внутри std :: string (который должен быть независим от юникода, согласно нескольким источникам)?Есть намеки на это?

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 ]

1 голос
/ 24 февраля 2012

Вполне вероятно, что эта строка является частью проблемы:

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

data не заканчивается NULL, поэтому кто знает, что вы вкладываете в свою строку. Замените его следующим:

reinterpret_cast<std::string*>(target)->append(data, size * nmemb);
0 голосов
/ 24 февраля 2012

Мне кажется, что вы должны вызывать следующее в вашей WriteData() функции:

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

Документация libcurl для CURLOPT_WRITEFUNCTION состояний:

Размерданные, на которые указывает ptr, - это размер, умноженный на nmemb, он не будет нулевым.

Таким образом, вы не можете полагаться на append(const char*) для правильной обработки добавления.

...