Libpurple: When service.web_directory and service.web_url is set, PURPLE_MESSAGE_IMAGES are stored to web_directory and link is forwarded to the user. Tested only with Facebook for now. Fix #106
This commit is contained in:
parent
408413abf2
commit
65d5b4fe99
2 changed files with 99 additions and 18 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include "purple.h"
|
#include "purple.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "transport/NetworkPlugin.h"
|
#include "transport/NetworkPlugin.h"
|
||||||
#include "transport/Logging.h"
|
#include "transport/Logging.h"
|
||||||
|
@ -1123,6 +1124,32 @@ static void conv_write(PurpleConversation *conv, const char *who, const char *al
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *calculate_data_hash(guchar *data, size_t len,
|
||||||
|
const gchar *hash_algo)
|
||||||
|
{
|
||||||
|
PurpleCipherContext *context;
|
||||||
|
static gchar digest[129]; /* 512 bits hex + \0 */
|
||||||
|
|
||||||
|
context = purple_cipher_context_new_by_name(hash_algo, NULL);
|
||||||
|
if (context == NULL)
|
||||||
|
{
|
||||||
|
purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo);
|
||||||
|
g_return_val_if_reached(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash the data */
|
||||||
|
purple_cipher_context_append(context, data, len);
|
||||||
|
if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL))
|
||||||
|
{
|
||||||
|
purple_debug_error("jabber", "Failed to get digest for %s cipher.\n",
|
||||||
|
hash_algo);
|
||||||
|
g_return_val_if_reached(NULL);
|
||||||
|
}
|
||||||
|
purple_cipher_context_destroy(context);
|
||||||
|
|
||||||
|
return g_strdup(digest);
|
||||||
|
}
|
||||||
|
|
||||||
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
|
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
|
||||||
// Don't forwards our own messages.
|
// Don't forwards our own messages.
|
||||||
if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
|
if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
|
||||||
|
@ -1130,23 +1157,77 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
|
||||||
}
|
}
|
||||||
PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
|
PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
|
||||||
|
|
||||||
// char *striped = purple_markup_strip_html_wrapped(message);
|
std::string message_;
|
||||||
// std::string msg = striped;
|
std::string xhtml_;
|
||||||
// g_free(striped);
|
|
||||||
|
|
||||||
|
if (flags & PURPLE_MESSAGE_IMAGES && !CONFIG_STRING(config, "service.web_directory").empty() && !CONFIG_STRING(config, "service.web_url").empty() ) {
|
||||||
|
LOG4CXX_INFO(logger, "Received image body='" << msg << "'");
|
||||||
|
std::string body = msg;
|
||||||
|
std::string plain = msg;
|
||||||
|
size_t i;
|
||||||
|
while ((i = body.find("<img id=\"")) != std::string::npos) {
|
||||||
|
int from = i + strlen("<img id=\"");
|
||||||
|
int to = body.find("\"", from + 1);
|
||||||
|
std::string id = body.substr(from, to - from);
|
||||||
|
LOG4CXX_INFO(logger, "Image ID = '" << id << "' " << from << " " << to);
|
||||||
|
|
||||||
// Escape HTML characters.
|
PurpleStoredImage *image = purple_imgstore_find_by_id(atoi(id.c_str()));
|
||||||
char *newline = purple_strdup_withhtml_wrapped(msg);
|
if (!image) {
|
||||||
char *strip, *xhtml;
|
LOG4CXX_ERROR(logger, "Cannot find image with id " << id << ".");
|
||||||
purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip);
|
return;
|
||||||
// xhtml_linkified = spectrum_markup_linkify(xhtml);
|
}
|
||||||
std::string message_(strip);
|
|
||||||
|
|
||||||
std::string xhtml_(xhtml);
|
std::string ext = "icon";
|
||||||
g_free(newline);
|
std::string name;
|
||||||
g_free(xhtml);
|
guchar * data = (guchar *) purple_imgstore_get_data_wrapped(image);
|
||||||
// g_free(xhtml_linkified);
|
size_t len = purple_imgstore_get_size_wrapped(image);
|
||||||
g_free(strip);
|
if (len < 300000 && data) {
|
||||||
|
ext = purple_imgstore_get_extension(image);
|
||||||
|
char *hash = calculate_data_hash(data, len, "sha1");
|
||||||
|
if (!hash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
name = hash;
|
||||||
|
g_free(hash);
|
||||||
|
|
||||||
|
std::ofstream output;
|
||||||
|
output.open(std::string(CONFIG_STRING(config, "service.web_directory") + "/" + name + "." + ext).c_str(), std::ios::out | std::ios::binary);
|
||||||
|
output.write((char *)data, len);
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
purple_imgstore_unref_wrapped(image);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
purple_imgstore_unref_wrapped(image);
|
||||||
|
|
||||||
|
std::string src = CONFIG_STRING(config, "service.web_url") + "/" + name + "." + ext;
|
||||||
|
std::string img = "<img src=\"" + src + "\"/>";
|
||||||
|
boost::replace_all(body, "<img id=\"" + id + "\">", img);
|
||||||
|
boost::replace_all(plain, "<img id=\"" + id + "\">", src);
|
||||||
|
}
|
||||||
|
LOG4CXX_INFO(logger, "New image body='" << body << "'");
|
||||||
|
char *strip, *xhtml;
|
||||||
|
purple_markup_html_to_xhtml_wrapped(body.c_str(), &xhtml, &strip);
|
||||||
|
message_ = strip;
|
||||||
|
if (message_.empty()) {
|
||||||
|
message_ = plain;
|
||||||
|
}
|
||||||
|
xhtml_ = xhtml;
|
||||||
|
g_free(xhtml);
|
||||||
|
g_free(strip);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Escape HTML characters.
|
||||||
|
char *newline = purple_strdup_withhtml_wrapped(msg);
|
||||||
|
char *strip, *xhtml;
|
||||||
|
purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip);
|
||||||
|
message_ = strip;
|
||||||
|
xhtml_ = xhtml;
|
||||||
|
g_free(newline);
|
||||||
|
g_free(xhtml);
|
||||||
|
g_free(strip);
|
||||||
|
}
|
||||||
|
|
||||||
// AIM and XMPP adds <body>...</body> here...
|
// AIM and XMPP adds <body>...</body> here...
|
||||||
if (xhtml_.find("<body>") == 0) {
|
if (xhtml_.find("<body>") == 0) {
|
||||||
|
@ -1167,8 +1248,6 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
|
||||||
timestamp = buf;
|
timestamp = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
|
|
||||||
|
|
||||||
if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
|
if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
|
||||||
std::string w = purple_normalize_wrapped(account, who);
|
std::string w = purple_normalize_wrapped(account, who);
|
||||||
std::string n;
|
std::string n;
|
||||||
|
@ -1177,11 +1256,11 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
|
||||||
n = w.substr((int) pos + 1, w.length() - (int) pos);
|
n = w.substr((int) pos + 1, w.length() - (int) pos);
|
||||||
w.erase((int) pos, w.length() - (int) pos);
|
w.erase((int) pos, w.length() - (int) pos);
|
||||||
}
|
}
|
||||||
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << w);
|
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "' name='" << w << "'");
|
||||||
np->handleMessage(np->m_accounts[account], w, message_, n, xhtml_, timestamp);
|
np->handleMessage(np->m_accounts[account], w, message_, n, xhtml_, timestamp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name_wrapped(conv) << "' " << who);
|
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "' name='" << purple_conversation_get_name_wrapped(conv) << "' " << who);
|
||||||
np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, who, xhtml_, timestamp);
|
np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, who, xhtml_, timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,8 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
||||||
("service.vip_only", value<bool>()->default_value(false), "")
|
("service.vip_only", value<bool>()->default_value(false), "")
|
||||||
("service.vip_message", value<std::string>()->default_value(""), "")
|
("service.vip_message", value<std::string>()->default_value(""), "")
|
||||||
("service.reconnect_all_users", value<bool>()->default_value(false), "")
|
("service.reconnect_all_users", value<bool>()->default_value(false), "")
|
||||||
|
("service.web_directory", value<std::string>()->default_value(""), "Full path to directory used to save files to which the links are sent to users.")
|
||||||
|
("service.web_url", value<std::string>()->default_value(""), "URL on which files in web_directory are accessible.")
|
||||||
("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
|
("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
|
||||||
("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
|
("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
|
||||||
("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
|
("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
|
||||||
|
|
Loading…
Add table
Reference in a new issue