Merge branch 'master' of https://github.com/hanzz/libtransport
This commit is contained in:
commit
316a26474f
25 changed files with 815 additions and 39 deletions
|
@ -53,6 +53,9 @@ find_package(log4cxx)
|
|||
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(event)
|
||||
|
||||
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(pqxx)
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
INCLUDE(FindQt4)
|
||||
|
@ -101,6 +104,16 @@ else (MYSQL_FOUND)
|
|||
message("MySQL : no (install mysql-devel)")
|
||||
endif (MYSQL_FOUND)
|
||||
|
||||
if (PQXX_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_PQXX)
|
||||
include_directories(${PQXX_INCLUDE_DIR})
|
||||
message("PostgreSQL : yes")
|
||||
else (PQXX_FOUND)
|
||||
set(PQXX_LIBRARY "")
|
||||
set(PQ_LIBRARY "")
|
||||
message("PostgreSQL : no (install libpqxx-devel)")
|
||||
endif (PQXX_FOUND)
|
||||
|
||||
if (PROTOBUF_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_PROTOBUF)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
Version 2.0.0-beta (X-X-X):
|
||||
General:
|
||||
* Fixed registration from Pidgin.
|
||||
* Unsubscribe presence sent to some buddy doesn't disconnect the account.
|
||||
* Remote Roster requests are not sent to resources, but to bare JID.
|
||||
* Added automatic reconnection in case of non-fatal error.
|
||||
* Added more error messages.
|
||||
|
||||
version 2.0.0 alpha (2011-12-06):
|
||||
General:
|
||||
* First Spectrum 2.0.0 alpha release, check more on
|
||||
|
|
|
@ -26,6 +26,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std
|
|||
this->np = np;
|
||||
this->user = user;
|
||||
this->suffix = suffix;
|
||||
m_connected = false;
|
||||
rooms = 0;
|
||||
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
|
||||
connect(this, SIGNAL(connected()), SLOT(on_connected()));
|
||||
|
@ -33,6 +34,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std
|
|||
}
|
||||
|
||||
void MyIrcSession::on_connected() {
|
||||
m_connected = true;
|
||||
if (suffix.empty()) {
|
||||
np->handleConnected(user);
|
||||
}
|
||||
|
@ -51,6 +53,7 @@ void MyIrcSession::on_connected() {
|
|||
void MyIrcSession::on_disconnected() {
|
||||
if (suffix.empty())
|
||||
np->handleDisconnected(user, 0, "");
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
bool MyIrcSession::correctNickname(std::string &nickname) {
|
||||
|
@ -156,6 +159,9 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) {
|
|||
}
|
||||
|
||||
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
||||
QString channel;
|
||||
QStringList members;
|
||||
|
||||
IrcNumericMessage *m = (IrcNumericMessage *) message;
|
||||
switch (m->code()) {
|
||||
case 332:
|
||||
|
@ -165,8 +171,8 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
|||
np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString());
|
||||
break;
|
||||
case 353:
|
||||
QString channel = m->parameters().value(2);
|
||||
QStringList members = m->parameters().value(3).split(" ");
|
||||
channel = m->parameters().value(2);
|
||||
members = m->parameters().value(3).split(" ");
|
||||
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
bool flags = 0;
|
||||
|
@ -176,6 +182,13 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
|||
np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
|
||||
}
|
||||
break;
|
||||
case 432:
|
||||
if (m_connected) {
|
||||
np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//qDebug() << "numeric message received:" << receiver() << origin << code << params;
|
||||
|
@ -208,5 +221,6 @@ void MyIrcSession::onMessageReceived(IrcMessage *message) {
|
|||
case IrcMessage::Numeric:
|
||||
on_numericMessageReceived(message);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ protected:
|
|||
std::string m_identify;
|
||||
std::list<std::string> m_autoJoin;
|
||||
std::string m_topicData;
|
||||
bool m_connected;
|
||||
};
|
||||
|
||||
//class MyIrcBuffer : public Irc::Buffer
|
||||
|
|
|
@ -441,6 +441,16 @@ static void * requestInput(const char *title, const char *primary,const char *se
|
|||
((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me.");
|
||||
return NULL;
|
||||
}
|
||||
else if (primaryString == "Authorization Request Message:") {
|
||||
LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)");
|
||||
((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me.");
|
||||
return NULL;
|
||||
}
|
||||
else if (primaryString == "Authorization Denied Message:") {
|
||||
LOG4CXX_INFO(logger, "Authorization Deined Message: calling ok_cb(...)");
|
||||
((PurpleRequestInputCb) ok_cb)(user_data, "Authorization denied.");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
LOG4CXX_WARN(logger, "Unhandled request input. primary=" << primaryString);
|
||||
}
|
||||
|
@ -604,11 +614,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
return;
|
||||
}
|
||||
|
||||
LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
|
||||
if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL){
|
||||
|
||||
if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
|
||||
LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
|
||||
account = purple_accounts_find(name.c_str(), protocol.c_str());
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
|
||||
account = purple_account_new(name.c_str(), protocol.c_str());
|
||||
purple_accounts_add(account);
|
||||
}
|
||||
|
@ -1078,6 +1090,8 @@ static void buddyListNewNode(PurpleBlistNode *node) {
|
|||
PurpleBuddy *buddy = (PurpleBuddy *) node;
|
||||
PurpleAccount *account = purple_buddy_get_account(buddy);
|
||||
|
||||
LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy));
|
||||
|
||||
// Status
|
||||
pbnetwork::StatusType status = pbnetwork::STATUS_NONE;
|
||||
std::string message;
|
||||
|
|
16
cmake_modules/pqxxConfig.cmake
Normal file
16
cmake_modules/pqxxConfig.cmake
Normal file
|
@ -0,0 +1,16 @@
|
|||
FIND_PATH(PQXX_INCLUDE_DIR pqxx/pqxx PATHS)
|
||||
MARK_AS_ADVANCED(PQXX_INCLUDE_DIR)
|
||||
|
||||
FIND_LIBRARY(PQXX_LIBRARY pqxx )
|
||||
MARK_AS_ADVANCED(PQXX_LIBRARY)
|
||||
|
||||
FIND_LIBRARY(PQ_LIBRARY pq )
|
||||
MARK_AS_ADVANCED(PQ_LIBRARY)
|
||||
|
||||
if(PQXX_LIBRARY AND PQ_LIBRARY AND PQXX_INCLUDE_DIR)
|
||||
set( PQXX_FOUND 1 )
|
||||
message( STATUS "Found pqxx: ${PQXX_LIBRARY}, ${PQ_LIBRARY}, ${PQXX_INCLUDE_DIR}")
|
||||
else()
|
||||
message(STATUS "Could NOT find pqxx and pq library")
|
||||
endif()
|
||||
|
|
@ -18,13 +18,12 @@
|
|||
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
|
||||
#include <Swiften/Base/IDGenerator.h>
|
||||
#include <Swiften/Elements/Presence.h>
|
||||
#include <Swiften/Presence/PresenceOracle.h>
|
||||
#include <Swiften/Base/foreach.h>
|
||||
|
||||
|
||||
namespace Swift {
|
||||
|
||||
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
|
||||
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
|
||||
idGenerator = new IDGenerator();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
#include "transport/presenceoracle.h"
|
||||
|
||||
namespace Swift {
|
||||
|
||||
class JingleSessionManager;
|
||||
|
@ -30,7 +32,7 @@ class PresenceOracle;
|
|||
|
||||
class CombinedOutgoingFileTransferManager {
|
||||
public:
|
||||
CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
|
||||
CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
|
||||
~CombinedOutgoingFileTransferManager();
|
||||
|
||||
boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&);
|
||||
|
@ -46,7 +48,7 @@ private:
|
|||
IDGenerator *idGenerator;
|
||||
SOCKS5BytestreamRegistry* bytestreamRegistry;
|
||||
SOCKS5BytestreamProxy* bytestreamProxy;
|
||||
PresenceOracle* presenceOracle;
|
||||
Transport::PresenceOracle* presenceOracle;
|
||||
SOCKS5BytestreamServer *bytestreamServer;
|
||||
};
|
||||
|
||||
|
|
109
include/transport/pqxxbackend.h
Normal file
109
include/transport/pqxxbackend.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/config.h"
|
||||
#include <pqxx/pqxx>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
/// Used to store transport data into SQLite3 database.
|
||||
class PQXXBackend : public StorageBackend
|
||||
{
|
||||
public:
|
||||
/// Creates new PQXXBackend instance.
|
||||
/// \param config cofiguration, this class uses following Config values:
|
||||
/// - database.database - path to SQLite3 database file, database file is created automatically
|
||||
/// - service.prefix - prefix for tables created by createDatabase method
|
||||
PQXXBackend(Config *config);
|
||||
|
||||
/// Destructor.
|
||||
~PQXXBackend();
|
||||
|
||||
/// Connects to the database and creates it if it's needed. This method call createDatabase() function
|
||||
/// automatically.
|
||||
/// \return true if database is opened successfully.
|
||||
bool connect();
|
||||
void disconnect();
|
||||
|
||||
/// Creates database structure.
|
||||
/// \see connect()
|
||||
/// \return true if database structure has been created successfully. Note that it returns True also if database structure
|
||||
/// already exists.
|
||||
bool createDatabase();
|
||||
|
||||
/// Stores user into database.
|
||||
/// \param user user struct containing all information about user which have to be stored
|
||||
void setUser(const UserInfo &user);
|
||||
|
||||
/// Gets user data from database and stores them into user reference.
|
||||
/// \param barejid barejid of user
|
||||
/// \param user UserInfo object where user data will be stored
|
||||
/// \return true if user has been found in database
|
||||
bool getUser(const std::string &barejid, UserInfo &user);
|
||||
|
||||
/// Changes users online state variable in database.
|
||||
/// \param id id of user - UserInfo.id
|
||||
/// \param online online state
|
||||
void setUserOnline(long id, bool online);
|
||||
|
||||
/// Removes user and all connected data from database.
|
||||
/// \param id id of user - UserInfo.id
|
||||
/// \return true if user has been found in database and removed
|
||||
bool removeUser(long id);
|
||||
|
||||
/// Returns JIDs of all buddies in user's roster.
|
||||
/// \param id id of user - UserInfo.id
|
||||
/// \param roster string list used to store user's roster
|
||||
/// \return true if user has been found in database and roster has been fetched
|
||||
bool getBuddies(long id, std::list<BuddyInfo> &roster);
|
||||
|
||||
bool getOnlineUsers(std::vector<std::string> &users);
|
||||
|
||||
long addBuddy(long userId, const BuddyInfo &buddyInfo);
|
||||
|
||||
void updateBuddy(long userId, const BuddyInfo &buddyInfo);
|
||||
void removeBuddy(long id) {}
|
||||
|
||||
void getUserSetting(long userId, const std::string &variable, int &type, std::string &value);
|
||||
void updateUserSetting(long userId, const std::string &variable, const std::string &value);
|
||||
|
||||
void beginTransaction();
|
||||
void commitTransaction();
|
||||
|
||||
private:
|
||||
bool exec(const std::string &query, bool show_error = true);
|
||||
bool exec(pqxx::work &txn, const std::string &query, bool show_error = true);
|
||||
Config *m_config;
|
||||
std::string m_prefix;
|
||||
|
||||
pqxx::connection *m_conn;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
57
include/transport/presenceoracle.h
Normal file
57
include/transport/presenceoracle.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <string>
|
||||
#include <Swiften/Elements/Presence.h>
|
||||
#include <Swiften/Client/StanzaChannel.h>
|
||||
|
||||
#include <Swiften/Base/boost_bsignals.h>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class PresenceOracle {
|
||||
public:
|
||||
PresenceOracle(Swift::StanzaChannel* stanzaChannel);
|
||||
~PresenceOracle();
|
||||
|
||||
Swift::Presence::ref getLastPresence(const Swift::JID&) const;
|
||||
Swift::Presence::ref getHighestPriorityPresence(const Swift::JID& bareJID) const;
|
||||
std::vector<Swift::Presence::ref> getAllPresence(const Swift::JID& bareJID) const;
|
||||
|
||||
public:
|
||||
boost::signal<void (Swift::Presence::ref)> onPresenceChange;
|
||||
|
||||
private:
|
||||
void handleIncomingPresence(Swift::Presence::ref presence);
|
||||
void handleStanzaChannelAvailableChanged(bool);
|
||||
|
||||
private:
|
||||
typedef std::map<Swift::JID, Swift::Presence::ref> PresenceMap;
|
||||
typedef std::map<Swift::JID, PresenceMap> PresencesMap;
|
||||
PresencesMap entries_;
|
||||
Swift::StanzaChannel* stanzaChannel_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Disco/CapsManager.h"
|
||||
#include "Swiften/Disco/CapsMemoryStorage.h"
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Network/BoostTimerFactory.h"
|
||||
#include "Swiften/Network/BoostIOServiceThread.h"
|
||||
#include "Swiften/Server/UserRegistry.h"
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include <boost/bind.hpp>
|
||||
#include "transport/config.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/presenceoracle.h"
|
||||
|
||||
namespace Transport {
|
||||
// typedef enum { CLIENT_FEATURE_ROSTERX = 2,
|
||||
|
@ -92,7 +92,7 @@ namespace Transport {
|
|||
|
||||
/// You can use it to check current resource connected for particular user.
|
||||
/// \return Swift::PresenceOracle associated with this Transport::Component.
|
||||
Swift::PresenceOracle *getPresenceOracle();
|
||||
PresenceOracle *getPresenceOracle();
|
||||
|
||||
/// Returns True if the component is in server mode.
|
||||
|
||||
|
@ -179,7 +179,7 @@ namespace Transport {
|
|||
Swift::EntityCapsManager *m_entityCapsManager;
|
||||
Swift::CapsManager *m_capsManager;
|
||||
Swift::CapsMemoryStorage *m_capsMemoryStorage;
|
||||
Swift::PresenceOracle *m_presenceOracle;
|
||||
PresenceOracle *m_presenceOracle;
|
||||
Swift::StanzaChannel *m_stanzaChannel;
|
||||
Swift::IQRouter *m_iqRouter;
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <time.h>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
#include "Swiften/Disco/EntityCapsProvider.h"
|
||||
#include "storagebackend.h"
|
||||
|
@ -35,6 +34,7 @@ class Component;
|
|||
class RosterManager;
|
||||
class ConversationManager;
|
||||
class UserManager;
|
||||
class PresenceOracle;
|
||||
struct UserInfo;
|
||||
|
||||
/// Represents online XMPP user.
|
||||
|
@ -125,7 +125,7 @@ class User : public Swift::EntityCapsProvider {
|
|||
UserManager *m_userManager;
|
||||
ConversationManager *m_conversationManager;
|
||||
Swift::EntityCapsManager *m_entityCapsManager;
|
||||
Swift::PresenceOracle *m_presenceOracle;
|
||||
PresenceOracle *m_presenceOracle;
|
||||
UserInfo m_userInfo;
|
||||
void *m_data;
|
||||
bool m_connected;
|
||||
|
|
|
@ -40,6 +40,8 @@ std::string serializeGroups(const std::vector<std::string> &groups);
|
|||
|
||||
std::vector<std::string> deserializeGroups(std::string &groups);
|
||||
|
||||
int getRandomPort(const std::string &s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "transport/logger.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/mysqlbackend.h"
|
||||
#include "transport/pqxxbackend.h"
|
||||
#include "transport/userregistration.h"
|
||||
#include "transport/networkpluginserver.h"
|
||||
#include "transport/admininterface.h"
|
||||
|
@ -379,7 +380,23 @@ int main(int argc, char **argv)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3") {
|
||||
#ifdef WITH_PQXX
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
storageBackend = new PQXXBackend(&config);
|
||||
if (!storageBackend->connect()) {
|
||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
|
||||
std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
|
||||
&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
|
||||
std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
|
||||
return -2;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ port = 5222
|
|||
backend_host = localhost
|
||||
|
||||
# Port on which Spectrum listens for backends.
|
||||
backend_port=10001
|
||||
# By default Spectrum chooses random backend port and there's
|
||||
# no need to change it normally
|
||||
#backend_port=10001
|
||||
|
||||
# Full path to PKCS#12 cetficiate used for TLS in server mode.
|
||||
#cert=
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
FILE(GLOB SRC *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp)
|
||||
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp ../../src/util.cpp)
|
||||
|
||||
target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY})
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ if (CMAKE_COMPILER_IS_GNUCXX)
|
|||
endif()
|
||||
|
||||
if (WIN32)
|
||||
TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
|
||||
TARGET_LINK_LIBRARIES(transport ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
|
||||
else (WIN32)
|
||||
TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(transport ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
|
||||
endif(WIN32)
|
||||
|
||||
SET_TARGET_PROPERTIES(transport PROPERTIES
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/util.h"
|
||||
#include <fstream>
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
|
@ -120,13 +121,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
else if (opt.string_key == "service.backend_port") {
|
||||
found_backend_port = true;
|
||||
if (opt.value[0] == "0") {
|
||||
unsigned long r = 0;
|
||||
BOOST_FOREACH(char c, _jid) {
|
||||
r += (int) c;
|
||||
}
|
||||
srand(time(NULL) + r);
|
||||
int randomPort = 30000 + rand() % 10000;
|
||||
opt.value[0] = boost::lexical_cast<std::string>(randomPort);
|
||||
opt.value[0] = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
|
||||
}
|
||||
}
|
||||
else if (opt.string_key == "service.working_dir") {
|
||||
|
@ -148,14 +143,9 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
parsed.options.push_back(boost::program_options::basic_option<char>("service.pidfile", value));
|
||||
}
|
||||
if (!found_backend_port) {
|
||||
unsigned long r = 0;
|
||||
BOOST_FOREACH(char c, _jid) {
|
||||
r += (int) c;
|
||||
}
|
||||
srand(time(NULL) + r);
|
||||
int randomPort = 30000 + rand() % 10000;
|
||||
std::vector<std::string> value;
|
||||
value.push_back(boost::lexical_cast<std::string>(randomPort));
|
||||
std::string p = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
|
||||
value.push_back(p);
|
||||
parsed.options.push_back(boost::program_options::basic_option<char>("service.backend_port", value));
|
||||
}
|
||||
|
||||
|
|
373
src/pqxxbackend.cpp
Normal file
373
src/pqxxbackend.cpp
Normal file
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* libtransport -- C++ library for easy XMPP Transports development
|
||||
*
|
||||
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
|
||||
#include "transport/pqxxbackend.h"
|
||||
#include "transport/util.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include "log4cxx/logger.h"
|
||||
|
||||
using namespace log4cxx;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
static LoggerPtr logger = Logger::getLogger("PQXXBackend");
|
||||
|
||||
PQXXBackend::PQXXBackend(Config *config) {
|
||||
m_config = config;
|
||||
m_prefix = CONFIG_STRING(m_config, "database.prefix");
|
||||
}
|
||||
|
||||
PQXXBackend::~PQXXBackend(){
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void PQXXBackend::disconnect() {
|
||||
LOG4CXX_INFO(logger, "Disconnecting");
|
||||
|
||||
delete m_conn;
|
||||
}
|
||||
|
||||
bool PQXXBackend::connect() {
|
||||
LOG4CXX_INFO(logger, "Connecting PostgreSQL server " << CONFIG_STRING(m_config, "database.server") << ", user " <<
|
||||
CONFIG_STRING(m_config, "database.user") << ", database " << CONFIG_STRING(m_config, "database.database") <<
|
||||
", port " << CONFIG_INT(m_config, "database.port")
|
||||
);
|
||||
|
||||
std::string str = "dbname=";
|
||||
str += CONFIG_STRING(m_config, "database.database") + " ";
|
||||
|
||||
str += "user=" + CONFIG_STRING(m_config, "database.user") + " ";
|
||||
m_conn = new pqxx::connection(str);
|
||||
|
||||
createDatabase();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PQXXBackend::createDatabase() {
|
||||
|
||||
int exist = exec("SELECT * FROM " + m_prefix + "buddies_settings LIMIT 1;", false);
|
||||
|
||||
if (!exist) {
|
||||
exec("CREATE TABLE " + m_prefix + "buddies_settings ("
|
||||
"user_id integer NOT NULL,"
|
||||
"buddy_id integer NOT NULL,"
|
||||
"var varchar(50) NOT NULL,"
|
||||
"type smallint NOT NULL,"
|
||||
"value varchar(255) NOT NULL,"
|
||||
"PRIMARY KEY (buddy_id,var)"
|
||||
");");
|
||||
|
||||
exec("CREATE TYPE Subscription AS ENUM ('to','from','both','ask','none');");
|
||||
exec("CREATE TABLE " + m_prefix + "buddies ("
|
||||
"id SERIAL,"
|
||||
"user_id integer NOT NULL,"
|
||||
"uin varchar(255) NOT NULL,"
|
||||
"subscription Subscription NOT NULL,"
|
||||
"nickname varchar(255) NOT NULL,"
|
||||
"groups varchar(255) NOT NULL,"
|
||||
"flags smallint NOT NULL DEFAULT '0',"
|
||||
"PRIMARY KEY (id),"
|
||||
"UNIQUE (user_id,uin)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "users ("
|
||||
"id SERIAL,"
|
||||
"jid varchar(255) NOT NULL,"
|
||||
"uin varchar(4095) NOT NULL,"
|
||||
"password varchar(255) NOT NULL,"
|
||||
"language varchar(25) NOT NULL,"
|
||||
"encoding varchar(50) NOT NULL default 'utf8',"
|
||||
"last_login timestamp,"
|
||||
"vip boolean NOT NULL default '0',"
|
||||
"online boolean NOT NULL default '0',"
|
||||
"PRIMARY KEY (id),"
|
||||
"UNIQUE (jid)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "users_settings ("
|
||||
"user_id integer NOT NULL,"
|
||||
"var varchar(50) NOT NULL,"
|
||||
"type smallint NOT NULL,"
|
||||
"value varchar(255) NOT NULL,"
|
||||
"PRIMARY KEY (user_id,var)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "db_version ("
|
||||
"ver integer NOT NULL default '1',"
|
||||
"UNIQUE (ver)"
|
||||
");");
|
||||
|
||||
// exec("INSERT INTO db_version (ver) VALUES ('2');");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PQXXBackend::exec(const std::string &query, bool show_error) {
|
||||
pqxx::work txn(*m_conn);
|
||||
return exec(txn, query, show_error);
|
||||
}
|
||||
|
||||
bool PQXXBackend::exec(pqxx::work &txn, const std::string &query, bool show_error) {
|
||||
try {
|
||||
txn.exec(query);
|
||||
txn.commit();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
if (show_error)
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PQXXBackend::setUser(const UserInfo &user) {
|
||||
std::string encrypted = user.password;
|
||||
if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
|
||||
encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
|
||||
}
|
||||
pqxx::work txn(*m_conn);
|
||||
exec(txn, "UPDATE " + m_prefix + "users SET uin=" + txn.quote(user.uin) + ", password=" + txn.quote(encrypted) + ";"
|
||||
"INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES "
|
||||
"(" + txn.quote(user.jid) + ","
|
||||
+ txn.quote(user.uin) + ","
|
||||
+ txn.quote(encrypted) + ","
|
||||
+ txn.quote(user.language) + ","
|
||||
+ txn.quote(user.encoding) + ","
|
||||
+ "NOW(),"
|
||||
+ txn.quote(user.vip) +")");
|
||||
}
|
||||
|
||||
bool PQXXBackend::getUser(const std::string &barejid, UserInfo &user) {
|
||||
try {
|
||||
pqxx::work txn(*m_conn);
|
||||
|
||||
pqxx::result r = txn.exec("SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid="
|
||||
+ txn.quote(barejid));
|
||||
|
||||
if (r.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.id = r[0][0].as<int>();
|
||||
user.jid = r[0][1].as<std::string>();
|
||||
user.uin = r[0][2].as<std::string>();
|
||||
user.password = r[0][3].as<std::string>();
|
||||
user.encoding = r[0][4].as<std::string>();
|
||||
user.language = r[0][5].as<std::string>();
|
||||
user.vip = r[0][6].as<bool>();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PQXXBackend::setUserOnline(long id, bool online) {
|
||||
try {
|
||||
pqxx::work txn(*m_conn);
|
||||
exec(txn, "UPDATE " + m_prefix + "users SET online=" + txn.quote(online) + ", last_login=NOW() WHERE id=" + txn.quote(id));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool PQXXBackend::getOnlineUsers(std::vector<std::string> &users) {
|
||||
try {
|
||||
pqxx::work txn(*m_conn);
|
||||
pqxx::result r = txn.exec("SELECT jid FROM " + m_prefix + "users WHERE online=1");
|
||||
|
||||
for (pqxx::result::const_iterator it = r.begin(); it != r.end(); it++) {
|
||||
users.push_back((*it)[0].as<std::string>());
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
|
||||
// "INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
// std::string groups = Util::serializeGroups(buddyInfo.groups);
|
||||
// *m_addBuddy << userId << buddyInfo.legacyName << buddyInfo.subscription;
|
||||
// *m_addBuddy << groups;
|
||||
// *m_addBuddy << buddyInfo.alias << buddyInfo.flags;
|
||||
|
||||
// EXEC(m_addBuddy, addBuddy(userId, buddyInfo));
|
||||
|
||||
// long id = (long) mysql_insert_id(&m_conn);
|
||||
|
||||
// INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
|
||||
// if (!buddyInfo.settings.find("icon_hash")->second.s.empty()) {
|
||||
// *m_updateBuddySetting << userId << id << buddyInfo.settings.find("icon_hash")->first << (int) TYPE_STRING << buddyInfo.settings.find("icon_hash")->second.s << buddyInfo.settings.find("icon_hash")->second.s;
|
||||
// EXEC(m_updateBuddySetting, addBuddy(userId, buddyInfo));
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PQXXBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
|
||||
// "UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?"
|
||||
// std::string groups = Util::serializeGroups(buddyInfo.groups);
|
||||
// *m_updateBuddy << groups;
|
||||
// *m_updateBuddy << buddyInfo.alias << buddyInfo.flags << buddyInfo.subscription;
|
||||
// *m_updateBuddy << userId << buddyInfo.legacyName;
|
||||
|
||||
// EXEC(m_updateBuddy, updateBuddy(userId, buddyInfo));
|
||||
}
|
||||
|
||||
bool PQXXBackend::getBuddies(long id, std::list<BuddyInfo> &roster) {
|
||||
// SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC
|
||||
// *m_getBuddies << id;
|
||||
|
||||
// "SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC"
|
||||
// *m_getBuddiesSettings << id;
|
||||
|
||||
// SettingVariableInfo var;
|
||||
// long buddy_id = -1;
|
||||
// std::string key;
|
||||
|
||||
// EXEC(m_getBuddies, getBuddies(id, roster));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
// while (m_getBuddies->fetch() == 0) {
|
||||
// BuddyInfo b;
|
||||
|
||||
// std::string group;
|
||||
// *m_getBuddies >> b.id >> b.legacyName >> b.subscription >> b.alias >> group >> b.flags;
|
||||
|
||||
// if (!group.empty()) {
|
||||
// b.groups = Util::deserializeGroups(group);
|
||||
// }
|
||||
|
||||
// roster.push_back(b);
|
||||
// }
|
||||
|
||||
// EXEC(m_getBuddiesSettings, getBuddies(id, roster));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
// BOOST_FOREACH(BuddyInfo &b, roster) {
|
||||
// if (buddy_id == b.id) {
|
||||
//// std::cout << "Adding buddy info setting " << key << "\n";
|
||||
// b.settings[key] = var;
|
||||
// buddy_id = -1;
|
||||
// }
|
||||
|
||||
// while(buddy_id == -1 && m_getBuddiesSettings->fetch() == 0) {
|
||||
// std::string val;
|
||||
// *m_getBuddiesSettings >> buddy_id >> var.type >> key >> val;
|
||||
|
||||
// switch (var.type) {
|
||||
// case TYPE_BOOLEAN:
|
||||
// var.b = atoi(val.c_str());
|
||||
// break;
|
||||
// case TYPE_STRING:
|
||||
// var.s = val;
|
||||
// break;
|
||||
// default:
|
||||
// if (buddy_id == b.id) {
|
||||
// buddy_id = -1;
|
||||
// }
|
||||
// continue;
|
||||
// break;
|
||||
// }
|
||||
// if (buddy_id == b.id) {
|
||||
//// std::cout << "Adding buddy info setting " << key << "=" << val << "\n";
|
||||
// b.settings[key] = var;
|
||||
// buddy_id = -1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// while(m_getBuddiesSettings->fetch() == 0) {
|
||||
// // TODO: probably remove those settings, because there's no buddy for them.
|
||||
// // It should not happend, but one never know...
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PQXXBackend::removeUser(long id) {
|
||||
// *m_removeUser << (int) id;
|
||||
// EXEC(m_removeUser, removeUser(id));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
// *m_removeUserSettings << (int) id;
|
||||
// EXEC(m_removeUserSettings, removeUser(id));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
// *m_removeUserBuddies << (int) id;
|
||||
// EXEC(m_removeUserBuddies, removeUser(id));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
// *m_removeUserBuddiesSettings << (int) id;
|
||||
// EXEC(m_removeUserBuddiesSettings, removeUser(id));
|
||||
// if (!exec_ok)
|
||||
// return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PQXXBackend::getUserSetting(long id, const std::string &variable, int &type, std::string &value) {
|
||||
//// "SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?"
|
||||
// *m_getUserSetting << id << variable;
|
||||
// EXEC(m_getUserSetting, getUserSetting(id, variable, type, value));
|
||||
// if (m_getUserSetting->fetch() != 0) {
|
||||
//// "INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)"
|
||||
// *m_setUserSetting << id << variable << type << value;
|
||||
// EXEC(m_setUserSetting, getUserSetting(id, variable, type, value));
|
||||
// }
|
||||
// else {
|
||||
// *m_getUserSetting >> type >> value;
|
||||
// }
|
||||
}
|
||||
|
||||
void PQXXBackend::updateUserSetting(long id, const std::string &variable, const std::string &value) {
|
||||
//// "UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?"
|
||||
// *m_updateUserSetting << value << id << variable;
|
||||
// EXEC(m_updateUserSetting, updateUserSetting(id, variable, value));
|
||||
}
|
||||
|
||||
void PQXXBackend::beginTransaction() {
|
||||
// exec("START TRANSACTION;");
|
||||
}
|
||||
|
||||
void PQXXBackend::commitTransaction() {
|
||||
// exec("COMMIT;");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
136
src/presenceoracle.cpp
Normal file
136
src/presenceoracle.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* XMPP - libpurple transport
|
||||
*
|
||||
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
*/
|
||||
|
||||
#include "transport/presenceoracle.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using namespace Swift;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) {
|
||||
stanzaChannel_ = stanzaChannel;
|
||||
stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
|
||||
stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
|
||||
}
|
||||
|
||||
PresenceOracle::~PresenceOracle() {
|
||||
stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
|
||||
stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
|
||||
}
|
||||
|
||||
void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) {
|
||||
if (available) {
|
||||
entries_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
|
||||
// ignore presences for some contact, we're checking only presences for the transport itself here.
|
||||
bool isMUC = presence->getPayload<MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
|
||||
// filter out login/logout presence spam
|
||||
if (!presence->getTo().getNode().empty() && isMUC == false)
|
||||
return;
|
||||
|
||||
JID bareJID(presence->getFrom().toBare());
|
||||
if (presence->getType() == Presence::Subscribe || presence->getType() == Presence::Subscribed) {
|
||||
}
|
||||
else {
|
||||
Presence::ref passedPresence = presence;
|
||||
if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) {
|
||||
/* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */
|
||||
passedPresence = Presence::ref(new Presence());
|
||||
passedPresence->setType(Presence::Unavailable);
|
||||
passedPresence->setFrom(bareJID);
|
||||
passedPresence->setStatus(presence->getStatus());
|
||||
}
|
||||
std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID];
|
||||
if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) {
|
||||
/* Have a bare-JID only presence of offline */
|
||||
jidMap.clear();
|
||||
} else if (passedPresence->getType() == Presence::Available) {
|
||||
/* Don't have a bare-JID only offline presence once there are available presences */
|
||||
jidMap.erase(bareJID);
|
||||
}
|
||||
if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) {
|
||||
jidMap.erase(passedPresence->getFrom());
|
||||
} else {
|
||||
jidMap[passedPresence->getFrom()] = passedPresence;
|
||||
}
|
||||
entries_[bareJID] = jidMap;
|
||||
onPresenceChange(passedPresence);
|
||||
}
|
||||
}
|
||||
|
||||
Presence::ref PresenceOracle::getLastPresence(const JID& jid) const {
|
||||
PresencesMap::const_iterator i = entries_.find(jid.toBare());
|
||||
if (i == entries_.end()) {
|
||||
return Presence::ref();
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.find(jid);
|
||||
if (j != presenceMap.end()) {
|
||||
return j->second;
|
||||
}
|
||||
else {
|
||||
return Presence::ref();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Presence::ref> PresenceOracle::getAllPresence(const JID& bareJID) const {
|
||||
std::vector<Presence::ref> results;
|
||||
PresencesMap::const_iterator i = entries_.find(bareJID);
|
||||
if (i == entries_.end()) {
|
||||
return results;
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.begin();
|
||||
for (; j != presenceMap.end(); ++j) {
|
||||
Presence::ref current = j->second;
|
||||
results.push_back(current);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
Presence::ref PresenceOracle::getHighestPriorityPresence(const JID& bareJID) const {
|
||||
PresencesMap::const_iterator i = entries_.find(bareJID);
|
||||
if (i == entries_.end()) {
|
||||
return Presence::ref();
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.begin();
|
||||
Presence::ref highest;
|
||||
for (; j != presenceMap.end(); ++j) {
|
||||
Presence::ref current = j->second;
|
||||
if (!highest
|
||||
|| current->getPriority() > highest->getPriority()
|
||||
|| (current->getPriority() == highest->getPriority()
|
||||
&& StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) {
|
||||
highest = current;
|
||||
}
|
||||
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
|
||||
}
|
|
@ -71,11 +71,19 @@ bool StorageResponder::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
return true;
|
||||
}
|
||||
|
||||
StorageSerializer serializer;
|
||||
std::string value = serializer.serializePayload(boost::dynamic_pointer_cast<Storage>(payload->getPayload()));
|
||||
m_storageBackend->updateUserSetting(user->getUserInfo().id, "storage", value);
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Storing jabber:iq:storage");
|
||||
sendResponse(from, id, boost::shared_ptr<PrivateStorage>());
|
||||
boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
|
||||
|
||||
if (storage) {
|
||||
StorageSerializer serializer;
|
||||
std::string value = serializer.serializePayload(boost::dynamic_pointer_cast<Storage>(payload->getPayload()));
|
||||
m_storageBackend->updateUserSetting(user->getUserInfo().id, "storage", value);
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Storing jabber:iq:storage");
|
||||
sendResponse(from, id, boost::shared_ptr<PrivateStorage>());
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Unknown element. Libtransport does not support serialization of this.");
|
||||
sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "log4cxx/consoleappender.h"
|
||||
#include "log4cxx/patternlayout.h"
|
||||
#include "log4cxx/propertyconfigurator.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
@ -137,7 +138,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
|
||||
m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
|
||||
|
||||
m_presenceOracle = new PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
|
||||
|
||||
m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config);
|
||||
|
@ -170,7 +171,7 @@ Swift::StanzaChannel *Component::getStanzaChannel() {
|
|||
return m_stanzaChannel;
|
||||
}
|
||||
|
||||
Swift::PresenceOracle *Component::getPresenceOracle() {
|
||||
Transport::PresenceOracle *Component::getPresenceOracle() {
|
||||
return m_presenceOracle;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "transport/rostermanager.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/conversationmanager.h"
|
||||
#include "transport/presenceoracle.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Server/ServerStanzaChannel.h"
|
||||
#include "Swiften/Elements/StreamError.h"
|
||||
|
|
|
@ -286,6 +286,10 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
else if (textSingle->getName() == "encoding") {
|
||||
encoding = textSingle->getValue();
|
||||
}
|
||||
// Pidgin sends it as textSingle, not sure why...
|
||||
else if (textSingle->getName() == "password") {
|
||||
payload->setPassword(textSingle->getValue());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,15 @@ std::vector<std::string> deserializeGroups(std::string &groups) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int getRandomPort(const std::string &s) {
|
||||
unsigned long r = 0;
|
||||
BOOST_FOREACH(char c, s) {
|
||||
r += (int) c;
|
||||
}
|
||||
srand(time(NULL) + r);
|
||||
return 30000 + rand() % 10000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue