From fb49c84899f2b98ab8f9a1e6ede0f142d274a4df Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 17 Aug 2013 02:50:40 +0200 Subject: [PATCH] This fixes the crash and the unrequested printf of the downloaded json --- wordref/CMakeLists.txt | 1 + wordref/src/HttpReader.cpp | 86 +++++++++++++++++++++++++++++++++++ wordref/src/HttpReader.hpp | 17 +++++++ wordref/src/WordReference.cpp | 45 ++---------------- wordref/src/main.hpp | 1 + 5 files changed, 109 insertions(+), 41 deletions(-) create mode 100644 wordref/src/HttpReader.cpp create mode 100644 wordref/src/HttpReader.hpp diff --git a/wordref/CMakeLists.txt b/wordref/CMakeLists.txt index 61bedfc..63b5b0b 100644 --- a/wordref/CMakeLists.txt +++ b/wordref/CMakeLists.txt @@ -21,6 +21,7 @@ link_directories( add_executable(${PROJECT_NAME} src/main.cpp src/WordReference.cpp + src/HttpReader.cpp ) target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} diff --git a/wordref/src/HttpReader.cpp b/wordref/src/HttpReader.cpp new file mode 100644 index 0000000..c3fb30e --- /dev/null +++ b/wordref/src/HttpReader.cpp @@ -0,0 +1,86 @@ +/* +WordReferenceCLI, a c++ program to access WordReference.com. +Copyright (C) 2013 King_DuckZ + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "main.hpp" +#include "HttpReader.hpp" +#include +#include + +namespace { + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + extern "C" int readCurlHelper(char* parData, size_t parSize, size_t parNmemb, void* parBuffer) { + std::string* const that = static_cast(parBuffer); + const size_t dataLen = parSize * parNmemb; + that->reserve(that->size() + dataLen); + const size_t effectiveWrite = std::min(dataLen, that->capacity() - that->size()); + that->append(parData, effectiveWrite); + return effectiveWrite; + } +} //unnamed namespace + +struct HttpReader::LocalData { + explicit LocalData ( CURL* parCurl ) : curl(parCurl), headers(nullptr) {} + + CURL* const curl; + struct curl_slist* headers; +}; + +///---------------------------------------------------------------------------- +///---------------------------------------------------------------------------- +HttpReader::HttpReader() : + m_localData(new LocalData(curl_easy_init())) +{ + if (m_localData->curl) { + curl_slist_append(m_localData->headers, "Accept: application/json"); + curl_slist_append(m_localData->headers, "Content-Type: application/json"); + curl_slist_append(m_localData->headers, "charset: utf-8"); + } + else { + throw std::runtime_error("Can't create the CURL object, curl_easy_init() failed"); + } +} + +///---------------------------------------------------------------------------- +///---------------------------------------------------------------------------- +HttpReader::~HttpReader() noexcept { + if (m_localData->curl) + curl_easy_cleanup(m_localData->curl); + curl_slist_free_all(m_localData->headers); +} + +///---------------------------------------------------------------------------- +///---------------------------------------------------------------------------- +std::string HttpReader::GetPage (const std::string& parAddress) const { + std::string localString; + + curl_easy_setopt(m_localData->curl, CURLOPT_FOLLOWLOCATION, 1L); //Tell curl to follow redirection when needed + curl_easy_setopt(m_localData->curl, CURLOPT_HTTPHEADER, m_localData->headers); + curl_easy_setopt(m_localData->curl, CURLOPT_URL, parAddress.c_str()); + curl_easy_setopt(m_localData->curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(m_localData->curl, CURLOPT_WRITEFUNCTION, &readCurlHelper); + curl_easy_setopt(m_localData->curl, CURLOPT_WRITEDATA, &localString); + + const CURLcode res = curl_easy_perform(m_localData->curl); + if (CURLE_OK != res) { + std::ostringstream oss; + oss << "Error during the CURL request: " << curl_easy_strerror(res); + throw std::runtime_error(oss.str()); + } + return localString; +} diff --git a/wordref/src/HttpReader.hpp b/wordref/src/HttpReader.hpp new file mode 100644 index 0000000..53f06e0 --- /dev/null +++ b/wordref/src/HttpReader.hpp @@ -0,0 +1,17 @@ +#ifndef idC90956E8210D439AA5E2801D9E9FD799 +#define idC90956E8210D439AA5E2801D9E9FD799 + +class HttpReader { +public: + HttpReader ( void ); + ~HttpReader ( void ) noexcept; + + std::string GetPage ( const std::string& parAddress ) const; + +private: + struct LocalData; + + const std::unique_ptr m_localData; +}; + +#endif diff --git a/wordref/src/WordReference.cpp b/wordref/src/WordReference.cpp index 04735b4..c31bfaa 100644 --- a/wordref/src/WordReference.cpp +++ b/wordref/src/WordReference.cpp @@ -18,10 +18,10 @@ along with this program. If not, see . #include "main.hpp" #include "WordReference.hpp" +#include "HttpReader.hpp" +#include "libjson.h" #include #include -#include -#include "libjson.h" namespace { const char* ApiVersion = "0.8"; @@ -54,43 +54,6 @@ namespace { return parWord; } - ///------------------------------------------------------------------------- - ///------------------------------------------------------------------------- - void DownloadHttpPage (const std::string& parAddress, std::string& parDest) { - struct CurlAuto { - CurlAuto ( void ) : curl(curl_easy_init()) {} - ~CurlAuto ( void ) { if (curl) curl_easy_cleanup(curl); } - CURL* const curl; - }; - - CurlAuto curl; - if (curl.curl) { - curl_easy_setopt(curl.curl, CURLOPT_URL, parAddress.c_str()); - //Tell curl to follow redirection when needed - curl_easy_setopt(curl.curl, CURLOPT_FOLLOWLOCATION, 1L); - - const CURLcode res = curl_easy_perform(curl.curl); - if (CURLE_OK == res) { - char* reading; - const CURLcode res = curl_easy_getinfo(curl.curl, CURLINFO_CONTENT_TYPE, &reading); - if (CURLE_OK != res or not reading) { - std::ostringstream oss; - oss << "Error while requesting http page: " << curl_easy_strerror(res); - throw std::runtime_error(oss.str()); - } - parDest = reading; - } - else { - std::ostringstream oss; - oss << "Error during the CURL request: " << curl_easy_strerror(res); - throw std::runtime_error(oss.str()); - } - } - else { - throw std::runtime_error("Error initializing CURL"); - } - } - ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- JSONNode QueryJSon (const std::string& parFrom, const std::string& parTo, const std::string& parKey, const std::string& parWord) { @@ -98,8 +61,8 @@ namespace { oss << "http://api.wordreference.com/" << ApiVersion << "/" << parKey << "/json/" << parFrom << parTo << "/" << GetCleanWord(parWord); - std::string jsonResponse; - DownloadHttpPage(oss.str(), jsonResponse); + HttpReader http; + std::string jsonResponse(http.GetPage(oss.str())); return libjson::parse(libjson::to_json_string(jsonResponse)); } } //unnamed namespace diff --git a/wordref/src/main.hpp b/wordref/src/main.hpp index 395852d..48a8002 100644 --- a/wordref/src/main.hpp +++ b/wordref/src/main.hpp @@ -23,5 +23,6 @@ along with this program. If not, see . #include #include #include +#include #endif