diff options
Diffstat (limited to 'src/Cache.cpp')
-rw-r--r-- | src/Cache.cpp | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp index 0610a18..cba346b 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -4,12 +4,14 @@ #include "../include/FileUtil.hpp" #include "../include/Gif.hpp" #include "../include/Chatbar.hpp" +#include "../include/WebPagePreview.hpp" #include <boost/filesystem/convenience.hpp> #include <unordered_map> #include <process.hpp> #include <odhtdb/Hash.hpp> #include <sibs/SafeSerializer.hpp> #include <sibs/SafeDeserializer.hpp> +#include <libpreview.h> #if OS_FAMILY == OS_FAMILY_POSIX #include <pwd.h> @@ -22,7 +24,7 @@ using namespace TinyProcessLib; namespace dchat { - unordered_map<string, ImageByUrlResult> imageUrlCache; + unordered_map<string, ContentByUrlResult> contentUrlCache; boost::filesystem::path getHomeDir() { @@ -115,38 +117,71 @@ namespace dchat fileReplace(getDchatDir() / "binds", StringView((const char*)serializer.getBuffer().data(), serializer.getBuffer().size())); } - ImageByUrlResult loadImageFromFile(const boost::filesystem::path &filepath) + static ContentByUrlResult loadImageFromFile(const boost::filesystem::path &filepath) { StringView fileContent; try { fileContent = getFileContent(filepath); - if(Gif::isDataGif(fileContent)) - { - Gif *gif = new Gif(move(fileContent)); - return { gif, ImageByUrlResult::Type::CACHED }; - } - else + + sf::String webPageTitle; + bool foundHtmlContent = false; + preview_state state; + preview_init(&state); + size_t offset = 0; + do { - sf::Texture *texture = new sf::Texture(); - if(texture->loadFromMemory(fileContent.data, fileContent.size)) + // TODO: Get file content before doing this, the file might be in utf-16 encoding. That can happen for example if file contains html. + // Content type can be retrieved from HTTP response header when downloading content + offset += preview_step(&state, fileContent.data + offset, fileContent.size - offset); + if(state.step_result == PREVIEW_FOUND_IMAGE) { - delete fileContent.data; - fileContent.data = nullptr; - texture->setSmooth(true); - texture->generateMipmap(); - return { texture, ImageByUrlResult::Type::CACHED }; + if(Gif::isDataGif(fileContent)) + { + Gif *gif = new Gif(move(fileContent)); + return { gif, ContentByUrlResult::Type::CACHED }; + } + else + { + sf::Texture *texture = new sf::Texture(); + if(texture->loadFromMemory(fileContent.data, fileContent.size)) + { + delete fileContent.data; + fileContent.data = nullptr; + texture->setSmooth(true); + texture->generateMipmap(); + return { texture, ContentByUrlResult::Type::CACHED }; + } + delete texture; + } + break; } - delete texture; - delete fileContent.data; - fileContent.data = nullptr; + else if(state.step_result == PREVIEW_FOUND_TITLE) + { + foundHtmlContent = true; + webPageTitle = sf::String::fromUtf8(state.title, state.title + state.title_length); + } + else if(state.step_result == PREVIEW_FOUND_PARAGRAPH) + { + foundHtmlContent = true; + } + } while(offset < fileContent.size); + + delete fileContent.data; + fileContent.data = nullptr; + + if(foundHtmlContent) + { + // TODO: Use move semantics for webPageTitle when SFML supports it + WebPagePreview *webPagePreview = new WebPagePreview(webPageTitle); + return { webPagePreview, ContentByUrlResult::Type::CACHED }; } } catch(std::exception &e) { fprintf(stderr, "Failed to load image %s, reason: %s\n", filepath.string().c_str(), e.what()); } - return { (sf::Texture*)nullptr, ImageByUrlResult::Type::FAILED_DOWNLOAD }; + return { (sf::Texture*)nullptr, ContentByUrlResult::Type::FAILED_DOWNLOAD }; } Cache::Cache() : @@ -168,13 +203,13 @@ namespace dchat odhtdb::Hash urlHash(it->url.data(), it->url.size()); filepath /= urlHash.toString(); - ImageByUrlResult imageByUrlResult = loadImageFromFile(filepath); + ContentByUrlResult contentByUrlResult = loadImageFromFile(filepath); imageDownloadMutex.lock(); - imageUrlCache[it->url] = imageByUrlResult; + contentUrlCache[it->url] = contentByUrlResult; imageDownloadMutex.unlock(); - if(imageByUrlResult.type == ImageByUrlResult::Type::CACHED) + if(contentByUrlResult.type == ContentByUrlResult::Type::CACHED) { - printf("Download %s from url: %s\n", imageByUrlResult.isGif ? "gif" : "image", it->url.c_str()); + printf("Download content from url: %s\n", it->url.c_str()); } } it = imageDownloadProcesses.erase(it); @@ -208,11 +243,11 @@ namespace dchat downloadWaitThread.join(); } - const ImageByUrlResult Cache::getImageByUrl(const string &url, int downloadLimitBytes) + const ContentByUrlResult Cache::getContentByUrl(const string &url, int downloadLimitBytes) { lock_guard<mutex> lock(imageDownloadMutex); - auto it = imageUrlCache.find(url); - if(it != imageUrlCache.end()) + auto it = contentUrlCache.find(url); + if(it != contentUrlCache.end()) return it->second; // TODO: Verify hashed url is not too long for filepath on windows @@ -220,16 +255,21 @@ namespace dchat odhtdb::Hash urlHash(url.data(), url.size()); filepath /= urlHash.toString(); - ImageByUrlResult imageByUrlResult = loadImageFromFile(filepath); - if(imageByUrlResult.type == ImageByUrlResult::Type::CACHED) + ContentByUrlResult contentByUrlResult = loadImageFromFile(filepath); + if(contentByUrlResult.type == ContentByUrlResult::Type::CACHED) + { + contentUrlCache[url] = contentByUrlResult; + printf("Loaded content from file cache: %s\n", url.c_str()); + return contentByUrlResult; + } + else if(contentByUrlResult.type == ContentByUrlResult::Type::FAILED_DOWNLOAD && boost::filesystem::exists(filepath)) { - imageUrlCache[url] = imageByUrlResult; - printf("Loaded image from file cache: %s, is gif: %s\n", url.c_str(), imageByUrlResult.isGif ? "yes" : "no"); - return imageByUrlResult; + contentUrlCache[url] = contentByUrlResult; + return contentByUrlResult; } - ImageByUrlResult result((sf::Texture*)nullptr, ImageByUrlResult::Type::DOWNLOADING); - imageUrlCache[url] = result; + ContentByUrlResult result((sf::Texture*)nullptr, ContentByUrlResult::Type::DOWNLOADING); + contentUrlCache[url] = result; string downloadLimitBytesStr = to_string(downloadLimitBytes); |