libyahoo2 avatars supprot

This commit is contained in:
HanzZ 2012-05-27 15:35:22 +02:00
parent 6b88ad945d
commit d53b3a5433
4 changed files with 236 additions and 3 deletions

View file

@ -0,0 +1,159 @@
#include "httpfetch.h"
#include "transport/logging.h"
DEFINE_LOGGER(logger, "HTTPFetch");
static int url_to_host_port_path(const char *url,
char *host, int *port, char *path, int *ssl)
{
char *urlcopy = NULL;
char *slash = NULL;
char *colon = NULL;
/*
* http://hostname
* http://hostname/
* http://hostname/path
* http://hostname/path:foo
* http://hostname:port
* http://hostname:port/
* http://hostname:port/path
* http://hostname:port/path:foo
* and https:// variants of the above
*/
if (strstr(url, "http://") == url) {
urlcopy = strdup(url + 7);
} else if (strstr(url, "https://") == url) {
urlcopy = strdup(url + 8);
*ssl = 1;
} else {
return 0;
}
slash = strchr(urlcopy, '/');
colon = strchr(urlcopy, ':');
if (!colon || (slash && slash < colon)) {
if (*ssl)
*port = 443;
else
*port = 80;
} else {
*colon = 0;
*port = atoi(colon + 1);
}
if (!slash) {
strcpy(path, "/");
} else {
strcpy(path, slash);
*slash = 0;
}
strcpy(host, urlcopy);
free(urlcopy);
return 1;
}
HTTPFetch::HTTPFetch(Swift::BoostIOServiceThread *ioService, Swift::ConnectionFactory *factory) : m_ioService(ioService), m_factory(factory) {
m_afterHeader = false;
}
HTTPFetch::~HTTPFetch() {
}
void HTTPFetch::_connected(boost::shared_ptr<Swift::Connection> conn, const std::string url, bool error) {
if (error) {
_disconnected(conn);
}
else {
char host[255];
int port = 80;
char path[255];
int ssl = 0;
if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl))
return;
static char buff[2048];
snprintf(buff, sizeof(buff),
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: Mozilla/4.5 [en] (1/1)\r\n"
"Accept: */*\r\n"
"%s" "\r\n", path, host,
"Connection: close\r\n");
LOG4CXX_INFO(logger, "Sending " << buff << "\n");
conn->write(Swift::createSafeByteArray(buff));
}
}
void HTTPFetch::_disconnected(boost::shared_ptr<Swift::Connection> conn) {
conn->onConnectFinished.disconnect_all_slots();
conn->onDisconnected.disconnect_all_slots();
conn->onDataRead.disconnect_all_slots();
if (m_buffer.size() == 0) {
onURLFetched("");
}
else {
std::string img = m_buffer.substr(m_buffer.find("\r\n\r\n") + 4);
onURLFetched(img);
}
}
void HTTPFetch::_read(boost::shared_ptr<Swift::Connection> conn, boost::shared_ptr<Swift::SafeByteArray> data) {
std::string d(data->begin(), data->end());
// std::cout << d << "\n";
std::string img = d.substr(d.find("\r\n\r\n") + 4);
if (d.find("Location: ") == std::string::npos) {
m_buffer += d;
}
else {
d = d.substr(d.find("Location: ") + 10);
if (d.find("\r") == std::string::npos) {
d = d.substr(0, d.find("\n"));
}
else {
d = d.substr(0, d.find("\r"));
}
LOG4CXX_INFO(logger, "Next url is '" << d << "'");
fetchURL(d);
conn->onConnectFinished.disconnect_all_slots();
conn->onDisconnected.disconnect_all_slots();
conn->onDataRead.disconnect_all_slots();
}
}
bool HTTPFetch::fetchURL(const std::string &url) {
char host[255];
int port = 80;
char path[255];
char buff[1024];
int ssl = 0;
if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl)) {
LOG4CXX_ERROR(logger, "Invalid URL " << url);
return false;
}
LOG4CXX_INFO(logger, "Connecting to " << host << ":" << port);
boost::asio::ip::tcp::resolver resolver(*m_ioService->getIOService());
boost::asio::ip::tcp::resolver::query query(host, "");
boost::asio::ip::address address;
for(boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); i != boost::asio::ip::tcp::resolver::iterator(); ++i) {
boost::asio::ip::tcp::endpoint end = *i;
address = end.address();
break;
}
boost::shared_ptr<Swift::Connection> conn = m_factory->createConnection();
conn->onConnectFinished.connect(boost::bind(&HTTPFetch::_connected, this, conn, url, _1));
conn->onDisconnected.connect(boost::bind(&HTTPFetch::_disconnected, this, conn));
conn->onDataRead.connect(boost::bind(&HTTPFetch::_read, this, conn, _1));
conn->connect(Swift::HostAddressPort(Swift::HostAddress(address), port));
return true;
}

View file

@ -0,0 +1,43 @@
#pragma once
// Transport includes
#include "transport/config.h"
#include "transport/networkplugin.h"
#include "transport/logging.h"
// Swiften
#include "Swiften/Swiften.h"
#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h"
// for signal handler
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
// Boost
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
class HTTPFetch {
public:
HTTPFetch(Swift::BoostIOServiceThread *ioSerice, Swift::ConnectionFactory *factory);
virtual ~HTTPFetch();
bool fetchURL(const std::string &url);
boost::signal<void (const std::string &data)> onURLFetched;
private:
void _connected(boost::shared_ptr<Swift::Connection> conn, const std::string url, bool error);
void _disconnected(boost::shared_ptr<Swift::Connection> conn);
void _read(boost::shared_ptr<Swift::Connection> conn, boost::shared_ptr<Swift::SafeByteArray> data);
Swift::BoostIOServiceThread *m_ioService;
Swift::ConnectionFactory *m_factory;
std::string m_buffer;
bool m_afterHeader;
};

View file

@ -12,6 +12,7 @@
#include "yahoohandler.h"
#include "yahoolocalaccount.h"
#include "httpfetch.h"
// Swiften
#include "Swiften/Swiften.h"
@ -155,6 +156,26 @@ class YahooPlugin : public NetworkPlugin {
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
}
void _avatar_fetched(HTTPFetch *fetch, int account_id, unsigned int id, const std::string &img) {
handleVCard(m_ids[account_id], id, "", "", "", img);
delete fetch;
}
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
YahooLocalAccount *account = m_users[user];
if (!account) {
return;
}
if (account->urls.find(legacyName) == account->urls.end()) {
return;
}
HTTPFetch *fetch = new HTTPFetch(&m_boostIOServiceThread, m_factories->getConnectionFactory());
fetch->onURLFetched.connect(boost::bind(&YahooPlugin::_avatar_fetched, this, fetch, account->id, id, _1));
fetch->fetchURL(account->urls[legacyName]);
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
}
@ -356,6 +377,7 @@ static void ext_yahoo_status_changed(int id, const char *who, int stat, const ch
}
yahoo_buddyicon_request(id, who);
np->_yahoo_write_ready(account);
np->handleBuddyChanged(account->user, who, "", std::vector<std::string>(), status, msg ? msg : "");
}
@ -375,7 +397,7 @@ static void ext_yahoo_got_buddies(int id, YList * buds) {
np->handleBuddyChanged(account->user, bud->id, bud->real_name ? bud->real_name : "", groups, pbnetwork::STATUS_NONE);
}
yahoo_set_away(id, YAHOO_STATUS_AVAILABLE, "", 1);
// yahoo_set_away(id, YAHOO_STATUS_AVAILABLE, "", 1);
np->_yahoo_write_ready(account);
np->handleConnected(account->user);
}
@ -602,19 +624,27 @@ static void ext_yahoo_got_search_result(int id, int found, int start, int total,
}
static void ext_yahoo_got_buddyicon_checksum(int id, const char *a, const char *b, int checksum) {
LOG4CXX_INFO(logger, "got buddyicon_checksum");
}
static void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who, const char *old_group, const char *new_group) {
}
static void ext_yahoo_got_buddyicon(int id, const char *a, const char *b, const char *c, int checksum) {
LOG4CXX_INFO(logger, "got buddyicon " << c);
static void ext_yahoo_got_buddyicon(int id, const char *me, const char *who, const char *url, int checksum) {
YahooLocalAccount *account = np->getAccount(id);
if (!account) {
return;
}
LOG4CXX_INFO(logger, account->user << ": got buddyicon of " << who);
account->urls[who] = url;
}
static void ext_yahoo_buddyicon_uploaded(int id, const char *url) {
}
static void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who) {
LOG4CXX_INFO(logger, "got buddyicon_request");
}
static int ext_yahoo_log(const char *fmt,...)

View file

@ -48,6 +48,7 @@ class YahooLocalAccount {
int conn_tag;
std::map<int, YahooHandler *> handlers;
std::map<int, std::map<int, YahooHandler *> > handlers_per_conn;
std::map<std::string, std::string> urls;
int handler_tag;
int status;
std::string msg;