User, UserRegistration, UserManager, SQLite3Backend, DiscoInfoResponder and so on... :)
This commit is contained in:
parent
99aff92566
commit
c5edfd19b1
25 changed files with 1613 additions and 55 deletions
|
@ -6,6 +6,21 @@ set(CMAKE_MODULE_PATH "cmake_modules")
|
|||
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(cppunit)
|
||||
|
||||
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||
find_package(sqlite3)
|
||||
|
||||
message("Supported features")
|
||||
message("------------------")
|
||||
|
||||
if (SQLITE3_FOUND)
|
||||
ADD_DEFINITIONS(-DWITH_SQLITE)
|
||||
include_directories(SQLITE3_INCLUDE_DIR)
|
||||
message("SQLite3 : yes")
|
||||
else (SQLITE3_FOUND)
|
||||
set(SQLITE3_LIBRARIES "")
|
||||
message("SQLite3 : no")
|
||||
endif (SQLITE3_FOUND)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
ADD_DEFINITIONS(-ggdb)
|
||||
ADD_DEFINITIONS(-DDEBUG)
|
||||
|
@ -20,7 +35,9 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
|
|||
ADD_DEFINITIONS(-Woverloaded-virtual)
|
||||
ADD_DEFINITIONS(-Wsign-promo)
|
||||
ADD_DEFINITIONS(-Wundef -Wunused)
|
||||
message(STATUS "Build type is set to Debug")
|
||||
message("Debug : yes")
|
||||
else(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message("Debug : no")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
||||
SET(TRANSPORT_VERSION 2.0)
|
||||
|
@ -29,3 +46,5 @@ include_directories(include)
|
|||
ADD_SUBDIRECTORY(src)
|
||||
ADD_SUBDIRECTORY(include)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
|
||||
message("------------------")
|
||||
|
|
49
cmake_modules/sqlite3Config.cmake
Normal file
49
cmake_modules/sqlite3Config.cmake
Normal file
|
@ -0,0 +1,49 @@
|
|||
# - find Sqlite 3
|
||||
# SQLITE3_INCLUDE_DIR - Where to find Sqlite 3 header files (directory)
|
||||
# SQLITE3_LIBRARIES - Sqlite 3 libraries
|
||||
# SQLITE3_LIBRARY_RELEASE - Where the release library is
|
||||
# SQLITE3_LIBRARY_DEBUG - Where the debug library is
|
||||
# SQLITE3_FOUND - Set to TRUE if we found everything (library, includes and executable)
|
||||
|
||||
IF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG )
|
||||
SET(SQLITE3_FIND_QUIETLY TRUE)
|
||||
ENDIF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG )
|
||||
|
||||
FIND_PATH( SQLITE3_INCLUDE_DIR sqlite3.h )
|
||||
|
||||
FIND_LIBRARY(SQLITE3_LIBRARY_RELEASE NAMES sqlite3 )
|
||||
|
||||
FIND_LIBRARY(SQLITE3_LIBRARY_DEBUG NAMES sqlite3 sqlite3d HINTS /usr/lib/debug/usr/lib/ )
|
||||
|
||||
IF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR )
|
||||
SET( SQLITE3_FOUND TRUE )
|
||||
ENDIF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR )
|
||||
|
||||
IF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
|
||||
# if the generator supports configuration types then set
|
||||
# optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value
|
||||
IF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
||||
SET( SQLITE3_LIBRARIES optimized ${SQLITE3_LIBRARY_RELEASE} debug ${SQLITE3_LIBRARY_DEBUG} )
|
||||
ELSE( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
||||
# if there are no configuration types and CMAKE_BUILD_TYPE has no value
|
||||
# then just use the release libraries
|
||||
SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} )
|
||||
ENDIF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
||||
ELSEIF( SQLITE3_LIBRARY_RELEASE )
|
||||
SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} )
|
||||
ELSE( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
|
||||
SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_DEBUG} )
|
||||
ENDIF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
|
||||
|
||||
IF( SQLITE3_FOUND )
|
||||
IF( NOT SQLITE3_FIND_QUIETLY )
|
||||
MESSAGE( STATUS "Found Sqlite3 header file in ${SQLITE3_INCLUDE_DIR}")
|
||||
MESSAGE( STATUS "Found Sqlite3 libraries: ${SQLITE3_LIBRARIES}")
|
||||
ENDIF( NOT SQLITE3_FIND_QUIETLY )
|
||||
ELSE(SQLITE3_FOUND)
|
||||
IF( SQLITE3_FIND_REQUIRED)
|
||||
MESSAGE( FATAL_ERROR "Could not find Sqlite3" )
|
||||
ELSE( SQLITE3_FIND_REQUIRED)
|
||||
MESSAGE( STATUS "Optional package Sqlite3 was not found" )
|
||||
ENDIF( SQLITE3_FIND_REQUIRED)
|
||||
ENDIF(SQLITE3_FOUND)
|
|
@ -1 +1,2 @@
|
|||
ADD_SUBDIRECTORY(server_connect)
|
||||
ADD_SUBDIRECTORY(usermanager)
|
||||
|
|
|
@ -1,25 +1,10 @@
|
|||
#include "transport/config.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/logger.h"
|
||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
static void onConnected() {
|
||||
std::cout << "Connected to Jabber Server!\n";
|
||||
}
|
||||
|
||||
static void onConnectionError(const Swift::ComponentError&) {
|
||||
std::cout << "Connection Error!\n";
|
||||
}
|
||||
|
||||
static void onXMLIn(const std::string &data) {
|
||||
std::cout << "[XML IN]" << data << "\n";
|
||||
}
|
||||
|
||||
static void onXMLOut(const std::string &data) {
|
||||
std::cout << "[XML OUT]" << data << "\n";
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Config::Variables config;
|
||||
|
@ -27,14 +12,12 @@ int main(void)
|
|||
std::cout << "Can't open sample.cfg configuration file.\n";
|
||||
return 1;
|
||||
}
|
||||
Swift::logging = true;
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
Transport::Transport transport(&eventLoop, config);
|
||||
Component transport(&eventLoop, config);
|
||||
|
||||
transport.onConnected.connect(&onConnected);
|
||||
transport.onConnectionError.connect(bind(&onConnectionError, _1));
|
||||
transport.onXMLIn.connect(bind(&onXMLIn, _1));
|
||||
transport.onXMLOut.connect(bind(&onXMLOut, _1));
|
||||
Logger logger(&transport);
|
||||
|
||||
transport.connect();
|
||||
eventLoop.run();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[service]
|
||||
jid = icq.localhost
|
||||
password = secret
|
||||
server = localhost
|
||||
port = 5347
|
||||
|
||||
server = 127.0.0.1
|
||||
port = 8888
|
||||
|
|
6
examples/usermanager/CMakeLists.txt
Normal file
6
examples/usermanager/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
FILE(GLOB SRC *.cpp)
|
||||
|
||||
ADD_EXECUTABLE(transport_usermanager ${SRC})
|
||||
|
||||
TARGET_LINK_LIBRARIES(transport_usermanager transport)
|
||||
|
37
examples/usermanager/main.cpp
Normal file
37
examples/usermanager/main.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "transport/config.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/logger.h"
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include "transport/userregistration.h"
|
||||
#include "Swiften/EventLoop/SimpleEventLoop.h"
|
||||
|
||||
using namespace Transport;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Config::Variables config;
|
||||
if (!Config::load("sample.cfg", config)) {
|
||||
std::cout << "Can't open sample.cfg configuration file.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
Component transport(&eventLoop, config);
|
||||
Logger logger(&transport);
|
||||
|
||||
SQLite3Backend sql(config);
|
||||
logger.setStorageBackend(&sql);
|
||||
if (!sql.connect()) {
|
||||
std::cout << "Can't connect to database.\n";
|
||||
}
|
||||
|
||||
transport.setStorageBackend(&sql);
|
||||
|
||||
UserManager userManager(&transport);
|
||||
|
||||
UserRegistration userRegistration(&transport, &userManager, &sql);
|
||||
|
||||
transport.connect();
|
||||
eventLoop.run();
|
||||
}
|
9
examples/usermanager/sample.cfg
Normal file
9
examples/usermanager/sample.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
[service]
|
||||
jid = icq.localhost
|
||||
password = secret
|
||||
server = 127.0.0.1
|
||||
port = 8888
|
||||
|
||||
[database]
|
||||
database = test.sql
|
||||
prefix=icq
|
61
include/transport/logger.h
Normal file
61
include/transport/logger.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
struct UserInfo;
|
||||
class User;
|
||||
class UserManager;
|
||||
class Component;
|
||||
class StorageBackend;
|
||||
class UserRegistration;
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger(Component *component);
|
||||
~Logger();
|
||||
|
||||
void setStorageBackend(StorageBackend *storage);
|
||||
void setUserRegistration(UserRegistration *userRegistration);
|
||||
|
||||
private:
|
||||
// Component
|
||||
void handleConnected();
|
||||
void handleConnectionError(const Swift::ComponentError &error);
|
||||
void handleXMLIn(const std::string &data);
|
||||
void handleXMLOut(const std::string &data);
|
||||
|
||||
// StorageBackend
|
||||
void handleStorageError(const std::string &statement, const std::string &error);
|
||||
|
||||
// UserRegistration
|
||||
void handleUserRegistered(const UserInfo &user);
|
||||
void handleUserUnregistered(const UserInfo &user);
|
||||
void handleUserUpdated(const UserInfo &user);
|
||||
};
|
||||
|
||||
}
|
56
include/transport/sqlite3backend.h
Normal file
56
include/transport/sqlite3backend.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/config.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class SQLite3Backend : public StorageBackend
|
||||
{
|
||||
public:
|
||||
SQLite3Backend(Config::Variables &config);
|
||||
~SQLite3Backend();
|
||||
|
||||
bool connect();
|
||||
bool createDatabase();
|
||||
|
||||
void setUser(const UserInfo &user);
|
||||
bool getUser(const std::string &barejid, UserInfo &user);
|
||||
void setUserOnline(long id, bool online);
|
||||
void removeUser(long id);
|
||||
|
||||
bool getBuddies(long id, std::list<std::string> &roster);
|
||||
|
||||
private:
|
||||
bool exec(const std::string &query);
|
||||
|
||||
sqlite3 *m_db;
|
||||
Config::Variables m_config;
|
||||
std::string m_prefix;
|
||||
};
|
||||
|
||||
}
|
57
include/transport/storagebackend.h
Normal file
57
include/transport/storagebackend.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Transport {
|
||||
|
||||
struct UserInfo {
|
||||
long id;
|
||||
std::string jid;
|
||||
std::string uin;
|
||||
std::string password;
|
||||
std::string language;
|
||||
std::string encoding;
|
||||
bool vip;
|
||||
};
|
||||
|
||||
class StorageBackend
|
||||
{
|
||||
public:
|
||||
virtual ~StorageBackend() {}
|
||||
|
||||
virtual bool connect() = 0;
|
||||
virtual bool createDatabase() = 0;
|
||||
|
||||
virtual void setUser(const UserInfo &user) = 0;
|
||||
virtual bool getUser(const std::string &barejid, UserInfo &user) = 0;
|
||||
virtual void setUserOnline(long id, bool online) = 0;
|
||||
virtual void removeUser(long id) = 0;
|
||||
|
||||
virtual bool getBuddies(long id, std::list<std::string> &roster) = 0;
|
||||
|
||||
boost::signal<void (const std::string &statement, const std::string &error)> onStorageError;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -29,8 +29,12 @@
|
|||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Network/BoostTimerFactory.h"
|
||||
#include "Swiften/Network/BoostIOServiceThread.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include "transport/config.h"
|
||||
|
||||
#define tr(lang,STRING) (STRING)
|
||||
#define _(STRING) (STRING)
|
||||
|
||||
namespace Transport {
|
||||
// typedef enum { CLIENT_FEATURE_ROSTERX = 2,
|
||||
// CLIENT_FEATURE_XHTML_IM = 4,
|
||||
|
@ -40,32 +44,42 @@ namespace Transport {
|
|||
//
|
||||
// class SpectrumDiscoInfoResponder;
|
||||
// class SpectrumRegisterHandler;
|
||||
class StorageBackend;
|
||||
class DiscoInfoResponder;
|
||||
|
||||
class Transport {
|
||||
class Component {
|
||||
public:
|
||||
Transport(Swift::EventLoop *loop, Config::Variables &config);
|
||||
~Transport();
|
||||
Component(Swift::EventLoop *loop, Config::Variables &config);
|
||||
~Component();
|
||||
|
||||
// Connect to server
|
||||
void connect();
|
||||
|
||||
void setStorageBackend(StorageBackend *backend);
|
||||
|
||||
void setTransportFeatures(std::list<std::string> &features);
|
||||
void setBuddyFeatures(std::list<std::string> &features);
|
||||
|
||||
Swift::JID &getJID() { return m_jid; }
|
||||
|
||||
boost::signal<void (const Swift::ComponentError&)> onConnectionError;
|
||||
boost::signal<void ()> onConnected;
|
||||
boost::signal<void (const std::string &)> onXMLOut;
|
||||
boost::signal<void (const std::string &)> onXMLIn;
|
||||
boost::signal<void (Swift::Presence::ref presence)> onUserPresenceReceived;
|
||||
|
||||
private:
|
||||
void handleConnected();
|
||||
void handleConnectionError(const Swift::ComponentError &error);
|
||||
// void handlePresenceReceived(Swift::Presence::ref presence);
|
||||
void handlePresenceReceived(Swift::Presence::ref presence);
|
||||
// void handleMessageReceived(Swift::Message::ref message);
|
||||
// void handlePresence(Swift::Presence::ref presence);
|
||||
// void handleSubscription(Swift::Presence::ref presence);
|
||||
// void handleProbePresence(Swift::Presence::ref presence);
|
||||
void handlePresence(Swift::Presence::ref presence);
|
||||
void handleSubscription(Swift::Presence::ref presence);
|
||||
void handleProbePresence(Swift::Presence::ref presence);
|
||||
void handleDataRead(const Swift::String &data);
|
||||
void handleDataWritten(const Swift::String &data);
|
||||
|
||||
// void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, const boost::optional<Swift::ErrorPayload>& error, const Swift::JID& jid);
|
||||
void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
|
||||
// void handleCapsChanged(const Swift::JID& jid);
|
||||
|
||||
Swift::BoostNetworkFactories *m_factories;
|
||||
|
@ -76,10 +90,15 @@ namespace Transport {
|
|||
Swift::CapsManager *m_capsManager;
|
||||
Swift::CapsMemoryStorage *m_capsMemoryStorage;
|
||||
Swift::PresenceOracle *m_presenceOracle;
|
||||
// SpectrumDiscoInfoResponder *m_discoInfoResponder;
|
||||
StorageBackend *m_storageBackend;
|
||||
DiscoInfoResponder *m_discoInfoResponder;
|
||||
// SpectrumRegisterHandler *m_registerHandler;
|
||||
int m_reconnectCount;
|
||||
Config::Variables m_config;
|
||||
std::string m_protocol;
|
||||
Swift::JID m_jid;
|
||||
|
||||
friend class User;
|
||||
friend class UserRegistration;
|
||||
};
|
||||
}
|
||||
|
|
49
include/transport/user.h
Normal file
49
include/transport/user.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <time.h>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Presence/PresenceOracle.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class Component;
|
||||
|
||||
// Representation of XMPP User
|
||||
class User {
|
||||
public:
|
||||
User(const Swift::JID &jid, const std::string &username, const std::string &password, Component * component);
|
||||
virtual ~User();
|
||||
|
||||
const Swift::JID &getJID();
|
||||
|
||||
const char *getLang() { return "en"; }
|
||||
|
||||
private:
|
||||
Swift::JID m_jid;
|
||||
Swift::Component *m_component;
|
||||
Swift::EntityCapsManager *m_entityCapsManager;
|
||||
Swift::PresenceOracle *m_presenceOracle;
|
||||
};
|
||||
|
||||
}
|
55
include/transport/usermanager.h
Normal file
55
include/transport/usermanager.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class User;
|
||||
class Component;
|
||||
|
||||
// Class for managing online XMPP users.
|
||||
class UserManager
|
||||
{
|
||||
public:
|
||||
UserManager(Component *component);
|
||||
~UserManager();
|
||||
|
||||
// User *
|
||||
User *getUserByJID(const std::string &barejid);
|
||||
|
||||
// Returns count of online users;
|
||||
int userCount();
|
||||
|
||||
void removeUser(User *user) {}
|
||||
|
||||
private:
|
||||
void handlePresence(Swift::Presence::ref presence);
|
||||
|
||||
long m_onlineBuddies;
|
||||
User *m_cachedUser;
|
||||
std::map<std::string, User *> m_users;
|
||||
};
|
||||
|
||||
}
|
60
include/transport/userregistration.h
Normal file
60
include/transport/userregistration.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Queries/GetResponder.h"
|
||||
#include "Swiften/Queries/SetResponder.h"
|
||||
#include "Swiften/Elements/InBandRegistrationPayload.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
struct UserInfo;
|
||||
class Component;
|
||||
class StorageBackend;
|
||||
class UserManager;
|
||||
|
||||
class UserRegistration : Swift::GetResponder<Swift::InBandRegistrationPayload>, Swift::SetResponder<Swift::InBandRegistrationPayload> {
|
||||
public:
|
||||
UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
|
||||
~UserRegistration();
|
||||
|
||||
// Registers new user, returns false if user was already registered.
|
||||
bool registerUser(const UserInfo &user);
|
||||
|
||||
// Unregisters user, returns true if user was successfully unregistered.
|
||||
bool unregisterUser(const std::string &barejid);
|
||||
|
||||
boost::signal<void (const UserInfo &user)> onUserRegistered;
|
||||
boost::signal<void (const UserInfo &user)> onUserUnregistered;
|
||||
boost::signal<void (const UserInfo &user)> onUserUpdated;
|
||||
|
||||
private:
|
||||
bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
|
||||
|
||||
Component *m_component;
|
||||
StorageBackend *m_storageBackend;
|
||||
UserManager *m_userManager;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ FILE(GLOB HEADERS ../../include/transport/*.h)
|
|||
ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC})
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
|
||||
TARGET_LINK_LIBRARIES(transport -lSwiften -lresolv -lidn -lz -lpthread -lexpat -lidn -lboost_date_time -lboost_system -lboost_filesystem -lboost_program_options -lboost_regex -lboost_thread-mt -lboost_signals -lz -lssl -lcrypto -lexpat -lresolv -lc -lxml2 -export-dynamic)
|
||||
TARGET_LINK_LIBRARIES(transport -lSwiften -lresolv -lidn -lz -lpthread -lexpat -lidn -lboost_date_time -lboost_system -lboost_filesystem -lboost_program_options -lboost_regex -lboost_thread-mt -lboost_signals -lz -lssl -lcrypto -lexpat -lresolv -lc -lxml2 ${SQLITE3_LIBRARIES})
|
||||
|
||||
SET_TARGET_PROPERTIES(transport PROPERTIES
|
||||
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
|
||||
|
|
|
@ -36,6 +36,8 @@ bool load(const std::string &configfile, Variables &variables, boost::program_op
|
|||
("service.server", value<std::string>(), "set compression level")
|
||||
("service.password", value<std::string>(), "set compression level")
|
||||
("service.port", value<int>(), "set compression level")
|
||||
("database.database", value<std::string>(), "set compression level")
|
||||
("database.prefix", value<std::string>(), "set compression level")
|
||||
;
|
||||
|
||||
|
||||
|
|
92
src/discoinforesponder.cpp
Normal file
92
src/discoinforesponder.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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 "discoinforesponder.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include "Swiften/Disco/DiscoInfoResponder.h"
|
||||
#include "Swiften/Queries/IQRouter.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router) : Swift::GetResponder<DiscoInfo>(router) {
|
||||
m_transportInfo.addIdentity(DiscoInfo::Identity("libtransport", "gateway", "identity"));
|
||||
|
||||
m_buddyInfo.addIdentity(DiscoInfo::Identity("libtransport", "client", "pc"));
|
||||
std::list<std::string> features;
|
||||
features.push_back("jabber:iq:register");
|
||||
features.push_back("jabber:iq:gateway");
|
||||
features.push_back("http://jabber.org/protocol/disco#info");
|
||||
features.push_back("http://jabber.org/protocol/commands");
|
||||
setTransportFeatures(features);
|
||||
|
||||
features.clear();
|
||||
features.push_back("http://jabber.org/protocol/disco#items");
|
||||
features.push_back("http://jabber.org/protocol/disco#info");
|
||||
setBuddyFeatures(features);
|
||||
}
|
||||
|
||||
DiscoInfoResponder::~DiscoInfoResponder() {
|
||||
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setTransportFeatures(std::list<std::string> &features) {
|
||||
for (std::list<std::string>::iterator it = features.begin(); it != features.end(); it++) {
|
||||
if (!m_transportInfo.hasFeature(*it)) {
|
||||
m_transportInfo.addFeature(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
|
||||
for (std::list<std::string>::iterator it = f.begin(); it != f.end(); it++) {
|
||||
if (!m_buddyInfo.hasFeature(*it)) {
|
||||
m_buddyInfo.addFeature(*it);
|
||||
}
|
||||
}
|
||||
|
||||
CapsInfoGenerator caps("");
|
||||
onBuddyCapsInfoChanged(caps.generateCapsInfo(m_buddyInfo));
|
||||
}
|
||||
|
||||
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::DiscoInfo> info) {
|
||||
if (!info->getNode().isEmpty()) {
|
||||
sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
// presence for transport
|
||||
if (to.getNode().isEmpty()) {
|
||||
sendResponse(from, id, boost::shared_ptr<DiscoInfo>(new DiscoInfo(m_transportInfo)));
|
||||
}
|
||||
// presence for buddy
|
||||
else {
|
||||
sendResponse(from, id, boost::shared_ptr<DiscoInfo>(new DiscoInfo(m_buddyInfo)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
48
src/discoinforesponder.h
Normal file
48
src/discoinforesponder.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
#include <vector>
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Queries/GetResponder.h"
|
||||
#include "Swiften/Elements/DiscoInfo.h"
|
||||
#include "Swiften/Elements/CapsInfo.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
|
||||
public:
|
||||
DiscoInfoResponder(Swift::IQRouter *router);
|
||||
~DiscoInfoResponder();
|
||||
|
||||
void setTransportFeatures(std::list<std::string> &features);
|
||||
void setBuddyFeatures(std::list<std::string> &features);
|
||||
|
||||
boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
|
||||
|
||||
private:
|
||||
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::DiscoInfo> payload);
|
||||
|
||||
Swift::DiscoInfo m_transportInfo;
|
||||
Swift::DiscoInfo m_buddyInfo;
|
||||
};
|
||||
|
||||
}
|
95
src/logger.cpp
Normal file
95
src/logger.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "transport/logger.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/userregistration.h"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
Logger::Logger(Component *component) {
|
||||
component->onConnected.connect(bind(&Logger::handleConnected, this));
|
||||
component->onConnectionError.connect(bind(&Logger::handleConnectionError, this, _1));
|
||||
component->onXMLIn.connect(bind(&Logger::handleXMLIn, this, _1));
|
||||
component->onXMLOut.connect(bind(&Logger::handleXMLOut, this, _1));
|
||||
}
|
||||
|
||||
Logger::~Logger(){
|
||||
}
|
||||
|
||||
void Logger::setStorageBackend(StorageBackend *storage) {
|
||||
storage->onStorageError.connect(bind(&Logger::handleStorageError, this, _1, _2));
|
||||
}
|
||||
|
||||
void Logger::setUserRegistration(UserRegistration *userRegistration) {
|
||||
userRegistration->onUserRegistered.connect(bind(&Logger::handleUserRegistered, this, _1));
|
||||
userRegistration->onUserUnregistered.connect(bind(&Logger::handleUserUnregistered, this, _1));
|
||||
userRegistration->onUserUpdated.connect(bind(&Logger::handleUserUpdated, this, _1));
|
||||
}
|
||||
|
||||
|
||||
void Logger::handleConnected() {
|
||||
std::cout << "[COMPONENT] Connected to Jabber Server!\n";
|
||||
}
|
||||
|
||||
void Logger::handleConnectionError(const Swift::ComponentError &error) {
|
||||
std::cout << "[COMPONENT] Connection Error!\n";
|
||||
switch (error.getType()) {
|
||||
case Swift::ComponentError::UnknownError: std::cout << "[COMPONENT] Disconnect reason: UnknownError\n"; break;
|
||||
case Swift::ComponentError::ConnectionError: std::cout << "[COMPONENT] Disconnect reason: ConnectionError\n"; break;
|
||||
case Swift::ComponentError::ConnectionReadError: std::cout << "[COMPONENT] Disconnect reason: ConnectionReadError\n"; break;
|
||||
case Swift::ComponentError::ConnectionWriteError: std::cout << "[COMPONENT] Disconnect reason: ConnectionWriteError\n"; break;
|
||||
case Swift::ComponentError::XMLError: std::cout << "[COMPONENT] Disconnect reason: XMLError\n"; break;
|
||||
case Swift::ComponentError::AuthenticationFailedError: std::cout << "[COMPONENT] Disconnect reason: AuthenticationFailedError\n"; break;
|
||||
case Swift::ComponentError::UnexpectedElementError: std::cout << "[COMPONENT] Disconnect reason: UnexpectedElementError\n"; break;
|
||||
};
|
||||
}
|
||||
|
||||
void Logger::handleXMLIn(const std::string &data) {
|
||||
std::cout << "[XML IN] " << data << "\n";
|
||||
}
|
||||
|
||||
void Logger::handleXMLOut(const std::string &data) {
|
||||
std::cout << "[XML OUT] " << data << "\n";
|
||||
}
|
||||
|
||||
void Logger::handleStorageError(const std::string &statement, const std::string &error) {
|
||||
std::cout << "[SQL ERROR] \"" << error << "\" during statement \"" << statement << "\"\n";
|
||||
}
|
||||
|
||||
void Logger::handleUserRegistered(const UserInfo &user) {
|
||||
std::cout << "[REGISTRATION] User \"" << user.jid << "\" registered as \"" << user.uin << "\"\n";
|
||||
}
|
||||
|
||||
void Logger::handleUserUnregistered(const UserInfo &user) {
|
||||
std::cout << "[REGISTRATION] User \"" << user.jid << "\" unregistered \"" << user.uin << "\"\n";
|
||||
}
|
||||
|
||||
void Logger::handleUserUpdated(const UserInfo &user) {
|
||||
std::cout << "[REGISTRATION] User \"" << user.jid << "\" updated \"" << user.uin << "\"\n";
|
||||
}
|
||||
|
||||
}
|
138
src/sqlite3backend.cpp
Normal file
138
src/sqlite3backend.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "transport/sqlite3backend.h"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#define SQLITE_DB_VERSION 3
|
||||
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
SQLite3Backend::SQLite3Backend(Config::Variables &config) {
|
||||
m_config = config;
|
||||
m_db = NULL;
|
||||
m_prefix = m_config["database.prefix"].as<std::string>();
|
||||
}
|
||||
|
||||
SQLite3Backend::~SQLite3Backend(){
|
||||
if (m_db) {
|
||||
sqlite3_close(m_db);
|
||||
}
|
||||
}
|
||||
|
||||
bool SQLite3Backend::connect() {
|
||||
if (sqlite3_open(m_config["database.database"].as<std::string>().c_str(), &m_db)) {
|
||||
sqlite3_close(m_db);
|
||||
return false;
|
||||
}
|
||||
return createDatabase();
|
||||
}
|
||||
|
||||
bool SQLite3Backend::createDatabase() {
|
||||
int not_exist = exec("CREATE TABLE " + m_prefix + "buddies ("
|
||||
" id INTEGER PRIMARY KEY NOT NULL,"
|
||||
" user_id int(10) NOT NULL,"
|
||||
" uin varchar(255) NOT NULL,"
|
||||
" subscription varchar(20) NOT NULL,"
|
||||
" nickname varchar(255) NOT NULL,"
|
||||
" groups varchar(255) NOT NULL,"
|
||||
" flags int(4) NOT NULL DEFAULT '0'"
|
||||
");");
|
||||
|
||||
if (not_exist) {
|
||||
exec("CREATE UNIQUE INDEX IF NOT EXISTS user_id ON " + m_prefix + "buddies (user_id, uin);");
|
||||
|
||||
exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "buddies_settings ("
|
||||
" user_id int(10) NOT NULL,"
|
||||
" buddy_id int(10) NOT NULL,"
|
||||
" var varchar(50) NOT NULL,"
|
||||
" type int(4) NOT NULL,"
|
||||
" value varchar(255) NOT NULL,"
|
||||
" PRIMARY KEY (buddy_id, var)"
|
||||
");");
|
||||
|
||||
exec("CREATE INDEX IF NOT EXISTS user_id02 ON " + m_prefix + "buddies_settings (user_id);");
|
||||
|
||||
exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "users ("
|
||||
" id INTEGER PRIMARY KEY NOT NULL,"
|
||||
" 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 datetime,"
|
||||
" vip int(1) NOT NULL DEFAULT '0',"
|
||||
" online int(1) NOT NULL DEFAULT '0'"
|
||||
");");
|
||||
|
||||
exec("CREATE UNIQUE INDEX IF NOT EXISTS jid ON " + m_prefix + "users (jid);");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "users_settings ("
|
||||
" user_id int(10) NOT NULL,"
|
||||
" var varchar(50) NOT NULL,"
|
||||
" type int(4) NOT NULL,"
|
||||
" value varchar(255) NOT NULL,"
|
||||
" PRIMARY KEY (user_id, var)"
|
||||
");");
|
||||
|
||||
exec("CREATE INDEX IF NOT EXISTS user_id03 ON " + m_prefix + "users_settings (user_id);");
|
||||
|
||||
exec("CREATE TABLE IF NOT EXISTS " + m_prefix + "db_version ("
|
||||
" ver INTEGER NOT NULL DEFAULT '3'"
|
||||
");");
|
||||
exec("REPLACE INTO " + m_prefix + "db_version (ver) values(3)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SQLite3Backend::exec(const std::string &query) {
|
||||
char *errMsg = 0;
|
||||
int rc = sqlite3_exec(m_db, query.c_str(), NULL, 0, &errMsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
onStorageError(query, errMsg);
|
||||
sqlite3_free(errMsg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SQLite3Backend::setUser(const UserInfo &user) {
|
||||
|
||||
}
|
||||
|
||||
bool SQLite3Backend::getUser(const std::string &barejid, UserInfo &user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SQLite3Backend::setUserOnline(long id, bool online) {
|
||||
|
||||
}
|
||||
|
||||
bool SQLite3Backend::getBuddies(long id, std::list<std::string> &roster) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SQLite3Backend::removeUser(long id) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -20,15 +20,18 @@
|
|||
|
||||
#include "transport/transport.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include "transport/storagebackend.h"
|
||||
#include "discoinforesponder.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
Transport::Transport(Swift::EventLoop *loop, Config::Variables &config) {
|
||||
Component::Component(Swift::EventLoop *loop, Config::Variables &config) {
|
||||
m_reconnectCount = 0;
|
||||
m_config = config;
|
||||
m_storageBackend = NULL;
|
||||
|
||||
for (Config::Variables::iterator i = config.begin() ; i != config.end() ; ++i )
|
||||
{
|
||||
|
@ -40,33 +43,33 @@ Transport::Transport(Swift::EventLoop *loop, Config::Variables &config) {
|
|||
m_factories = new BoostNetworkFactories(loop);
|
||||
|
||||
m_reconnectTimer = m_factories->getTimerFactory()->createTimer(1000);
|
||||
m_reconnectTimer->onTick.connect(bind(&Transport::connect, this));
|
||||
m_reconnectTimer->onTick.connect(bind(&Component::connect, this));
|
||||
|
||||
m_component = new Component(loop, m_factories, m_jid, m_config["service.password"].as<std::string>());
|
||||
m_component = new Swift::Component(loop, m_factories, m_jid, m_config["service.password"].as<std::string>());
|
||||
m_component->setSoftwareVersion("", "");
|
||||
m_component->onConnected.connect(bind(&Transport::handleConnected, this));
|
||||
m_component->onError.connect(bind(&Transport::handleConnectionError, this, _1));
|
||||
m_component->onDataRead.connect(bind(&Transport::handleDataRead, this, _1));
|
||||
m_component->onDataWritten.connect(bind(&Transport::handleDataWritten, this, _1));
|
||||
// m_component->onPresenceReceived.connect(bind(&Transport::handlePresenceReceived, this, _1));
|
||||
// m_component->onMessageReceived.connect(bind(&Transport::handleMessageReceived, this, _1));
|
||||
m_component->onConnected.connect(bind(&Component::handleConnected, this));
|
||||
m_component->onError.connect(bind(&Component::handleConnectionError, this, _1));
|
||||
m_component->onDataRead.connect(bind(&Component::handleDataRead, this, _1));
|
||||
m_component->onDataWritten.connect(bind(&Component::handleDataWritten, this, _1));
|
||||
m_component->onPresenceReceived.connect(bind(&Component::handlePresenceReceived, this, _1));
|
||||
// m_component->onMessageReceived.connect(bind(&Component::handleMessageReceived, this, _1));
|
||||
|
||||
m_capsMemoryStorage = new CapsMemoryStorage();
|
||||
m_capsManager = new CapsManager(m_capsMemoryStorage, m_component->getStanzaChannel(), m_component->getIQRouter());
|
||||
m_entityCapsManager = new EntityCapsManager(m_capsManager, m_component->getStanzaChannel());
|
||||
// m_entityCapsManager->onCapsChanged.connect(boost::bind(&Transport::handleCapsChanged, this, _1));
|
||||
// m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
|
||||
|
||||
m_presenceOracle = new PresenceOracle(m_component->getStanzaChannel());
|
||||
// m_presenceOracle->onPresenceChange.connect(bind(&Transport::handlePresence, this, _1));
|
||||
m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
|
||||
|
||||
// m_discoInfoResponder = new SpectrumDiscoInfoResponder(m_component->getIQRouter());
|
||||
// m_discoInfoResponder->start();
|
||||
m_discoInfoResponder = new DiscoInfoResponder(m_component->getIQRouter());
|
||||
m_discoInfoResponder->start();
|
||||
//
|
||||
// m_registerHandler = new SpectrumRegisterHandler(m_component);
|
||||
// m_registerHandler->start();
|
||||
}
|
||||
|
||||
Transport::~Transport() {
|
||||
Component::~Component() {
|
||||
delete m_presenceOracle;
|
||||
delete m_entityCapsManager;
|
||||
delete m_capsManager;
|
||||
|
@ -77,31 +80,176 @@ Transport::~Transport() {
|
|||
delete m_factories;
|
||||
}
|
||||
|
||||
void Transport::connect() {
|
||||
void Component::setStorageBackend(StorageBackend *backend) {
|
||||
m_storageBackend = backend;
|
||||
}
|
||||
|
||||
void Component::setTransportFeatures(std::list<std::string> &features) {
|
||||
m_discoInfoResponder->setTransportFeatures(features);
|
||||
}
|
||||
|
||||
void Component::setBuddyFeatures(std::list<std::string> &features) {
|
||||
// TODO: handle caps change
|
||||
m_discoInfoResponder->setBuddyFeatures(features);
|
||||
}
|
||||
|
||||
void Component::connect() {
|
||||
m_reconnectCount++;
|
||||
m_component->connect(m_config["service.server"].as<std::string>(), m_config["service.port"].as<int>());
|
||||
m_reconnectTimer->stop();
|
||||
}
|
||||
|
||||
void Transport::handleConnected() {
|
||||
void Component::handleConnected() {
|
||||
onConnected();
|
||||
m_reconnectCount = 0;
|
||||
}
|
||||
|
||||
void Transport::handleConnectionError(const ComponentError &error) {
|
||||
void Component::handleConnectionError(const ComponentError &error) {
|
||||
onConnectionError(error);
|
||||
// if (m_reconnectCount == 2)
|
||||
// Transport::instance()->userManager()->removeAllUsers();
|
||||
// Component::instance()->userManager()->removeAllUsers();
|
||||
|
||||
m_reconnectTimer->start();
|
||||
}
|
||||
|
||||
void Transport::handleDataRead(const String &data) {
|
||||
void Component::handleDataRead(const String &data) {
|
||||
onXMLIn(data.getUTF8String());
|
||||
}
|
||||
|
||||
void Transport::handleDataWritten(const String &data) {
|
||||
void Component::handleDataWritten(const String &data) {
|
||||
onXMLOut(data.getUTF8String());
|
||||
}
|
||||
|
||||
void Component::handlePresenceReceived(Swift::Presence::ref presence) {
|
||||
switch(presence->getType()) {
|
||||
case Swift::Presence::Subscribe:
|
||||
case Swift::Presence::Subscribed:
|
||||
case Swift::Presence::Unsubscribe:
|
||||
case Swift::Presence::Unsubscribed:
|
||||
handleSubscription(presence);
|
||||
break;
|
||||
case Swift::Presence::Available:
|
||||
case Swift::Presence::Unavailable:
|
||||
break;
|
||||
case Swift::Presence::Probe:
|
||||
handleProbePresence(presence);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void Component::handlePresence(Swift::Presence::ref presence) {
|
||||
bool isMUC = presence->getPayload<MUCPayload>() != NULL;
|
||||
|
||||
// filter out login/logout presence spam
|
||||
if (!presence->getTo().getNode().isEmpty() && isMUC == false)
|
||||
return;
|
||||
|
||||
// filter out bad presences
|
||||
if (!presence->getFrom().isValid()) {
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setTo(presence->getFrom());
|
||||
response->setFrom(presence->getTo());
|
||||
response->setType(Swift::Presence::Error);
|
||||
|
||||
response->addPayload(boost::shared_ptr<Payload>(new ErrorPayload(ErrorPayload::JIDMalformed, ErrorPayload::Modify)));
|
||||
|
||||
m_component->sendPresence(response);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if we have this client's capabilities and ask for them
|
||||
bool haveFeatures = false;
|
||||
if (presence->getType() != Swift::Presence::Unavailable) {
|
||||
boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
|
||||
if (capsInfo && capsInfo->getHash() == "sha-1") {
|
||||
haveFeatures = m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
|
||||
std::cout << "has capsInfo " << haveFeatures << "\n";
|
||||
}
|
||||
else {
|
||||
GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_component->getIQRouter());
|
||||
discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
|
||||
discoInfoRequest->send();
|
||||
}
|
||||
}
|
||||
|
||||
onUserPresenceReceived(presence);
|
||||
}
|
||||
|
||||
void Component::handleProbePresence(Swift::Presence::ref presence) {
|
||||
|
||||
}
|
||||
|
||||
void Component::handleSubscription(Swift::Presence::ref presence) {
|
||||
// answer to subscibe
|
||||
if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().isEmpty()) {
|
||||
// Log(presence->getFrom().toString().getUTF8String(), "Subscribe presence received => sending subscribed");
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(presence->getTo());
|
||||
response->setTo(presence->getFrom());
|
||||
response->setType(Swift::Presence::Subscribed);
|
||||
m_component->sendPresence(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_protocol == "irc") {
|
||||
return;
|
||||
}
|
||||
|
||||
// User *user;
|
||||
// std::string barejid = presence->getTo().toBare().toString().getUTF8String();
|
||||
// std::string userkey = presence->getFrom().toBare().toString().getUTF8String();
|
||||
// if (Transport::instance()->protocol()->tempAccountsAllowed()) {
|
||||
// std::string server = barejid.substr(barejid.find("%") + 1, barejid.length() - barejid.find("%"));
|
||||
// userkey += server;
|
||||
// }
|
||||
|
||||
// user = (User *) Transport::instance()->userManager()->getUserByJID(userkey);
|
||||
// if (user) {
|
||||
// user->handleSubscription(presence);
|
||||
// }
|
||||
// else if (presence->getType() == Swift::Presence::Unsubscribe) {
|
||||
// Swift::Presence::ref response = Swift::Presence::create();
|
||||
// response->setFrom(presence->getTo());
|
||||
// response->setTo(presence->getFrom());
|
||||
// response->setType(Swift::Presence::Unsubscribed);
|
||||
// m_component->sendPresence(response);
|
||||
// }
|
||||
// else {
|
||||
// // Log(presence->getFrom().toString().getUTF8String(), "Subscribe presence received, but this user is not logged in");
|
||||
// }
|
||||
}
|
||||
|
||||
void Component::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> discoInfo, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
|
||||
// AbstractUser *user = Transport::instance()->userManager()->getUserByJID(jid.toBare().toString().getUTF8String());
|
||||
//
|
||||
// std::string resource = jid.getResource().getUTF8String();
|
||||
// if (user && user->hasResource(resource)) {
|
||||
// if (user->getResource(resource).caps == 0) {
|
||||
// int capabilities = 0;
|
||||
//
|
||||
// for (std::vector< String >::const_iterator it = discoInfo->getFeatures().begin(); it != discoInfo->getFeatures().end(); ++it) {
|
||||
// if (*it == "http://jabber.org/protocol/rosterx") {
|
||||
// capabilities |= CLIENT_FEATURE_ROSTERX;
|
||||
// }
|
||||
// else if (*it == "http://jabber.org/protocol/xhtml-im") {
|
||||
// capabilities |= CLIENT_FEATURE_XHTML_IM;
|
||||
// }
|
||||
// else if (*it == "http://jabber.org/protocol/si/profile/file-transfer") {
|
||||
// capabilities |= CLIENT_FEATURE_FILETRANSFER;
|
||||
// }
|
||||
// else if (*it == "http://jabber.org/protocol/chatstates") {
|
||||
// capabilities |= CLIENT_FEATURE_CHATSTATES;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// user->setResource(resource, -256, capabilities);
|
||||
// if (user->readyForConnect()) {
|
||||
// user->connect();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
44
src/user.cpp
Normal file
44
src/user.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "transport/user.h"
|
||||
#include "transport/transport.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
User::User(const Swift::JID &jid, const std::string &username, const std::string &password, Component *component) {
|
||||
m_jid = jid;
|
||||
|
||||
m_component = component->m_component;
|
||||
m_presenceOracle = component->m_presenceOracle;
|
||||
m_entityCapsManager = component->m_entityCapsManager;
|
||||
// m_activeResource = m_jid.getResource();
|
||||
|
||||
}
|
||||
User::~User(){
|
||||
|
||||
}
|
||||
|
||||
const Swift::JID &User::getJID() {
|
||||
return m_jid;
|
||||
}
|
||||
|
||||
}
|
162
src/usermanager.cpp
Normal file
162
src/usermanager.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/user.h"
|
||||
#include "transport/transport.h"
|
||||
|
||||
namespace Transport {
|
||||
|
||||
UserManager::UserManager(Component *component) {
|
||||
m_cachedUser = NULL;
|
||||
m_onlineBuddies = 0;
|
||||
|
||||
component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1));
|
||||
}
|
||||
|
||||
UserManager::~UserManager(){
|
||||
}
|
||||
|
||||
User *UserManager::getUserByJID(const std::string &barejid){
|
||||
if (m_cachedUser && barejid == m_cachedUser->getJID().toBare().toString().getUTF8String()) {
|
||||
return m_cachedUser;
|
||||
}
|
||||
|
||||
if (m_users.find(barejid) != m_users.end()) {
|
||||
User *user = m_users[barejid];
|
||||
m_cachedUser = user;
|
||||
return user;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int UserManager::userCount() {
|
||||
return m_users.size();
|
||||
}
|
||||
|
||||
void UserManager::handlePresence(Swift::Presence::ref presence) {
|
||||
// std::string barejid = presence->getTo().toBare().toString().getUTF8String();
|
||||
// std::string userkey = presence->getFrom().toBare().toString().getUTF8String();
|
||||
// // if (Transport::instance()->protocol()->tempAccountsAllowed()) {
|
||||
// // std::string server = barejid.substr(barejid.find("%") + 1, barejid.length() - barejid.find("%"));
|
||||
// // userkey += server;
|
||||
// // }
|
||||
//
|
||||
// User *user = getUserByJID(userkey);
|
||||
// if (user ) {
|
||||
// user->handlePresence(presence);
|
||||
// }
|
||||
// else {
|
||||
// // // No user, unavailable presence... nothing to do
|
||||
// // if (presence->getType() == Swift::Presence::Unavailable) {
|
||||
// // Swift::Presence::ref response = Swift::Presence::create();
|
||||
// // response->setTo(presence->getFrom());
|
||||
// // response->setFrom(Swift::JID(Transport::instance()->jid()));
|
||||
// // response->setType(Swift::Presence::Unavailable);
|
||||
// // m_component->sendPresence(response);
|
||||
// //
|
||||
// // // UserRow res = Transport::instance()->sql()->getUserByJid(userkey);
|
||||
// // // if (res.id != -1) {
|
||||
// // // Transport::instance()->sql()->setUserOnline(res.id, false);
|
||||
// // // }
|
||||
// // return;
|
||||
// // }
|
||||
// // UserRow res = Transport::instance()->sql()->getUserByJid(userkey);
|
||||
// // if (res.id == -1 && !Transport::instance()->protocol()->tempAccountsAllowed()) {
|
||||
// // // presence from unregistered user
|
||||
// // Log(presence->getFrom().toString().getUTF8String(), "This user is not registered");
|
||||
// // return;
|
||||
// // }
|
||||
// // else {
|
||||
// // if (res.id == -1 && Transport::instance()->protocol()->tempAccountsAllowed()) {
|
||||
// // res.jid = userkey;
|
||||
// // res.uin = presence->getFrom().toBare().toString().getUTF8String();
|
||||
// // res.password = "";
|
||||
// // res.language = "en";
|
||||
// // res.encoding = CONFIG().encoding;
|
||||
// // res.vip = 0;
|
||||
// // Transport::instance()->sql()->addUser(res);
|
||||
// // res = Transport::instance()->sql()->getUserByJid(userkey);
|
||||
// // }
|
||||
// //
|
||||
// // bool isVip = res.vip;
|
||||
// // std::list<std::string> const &x = CONFIG().allowedServers;
|
||||
// // if (CONFIG().onlyForVIP && !isVip && std::find(x.begin(), x.end(), presence->getFrom().getDomain().getUTF8String()) == x.end()) {
|
||||
// // Log(presence->getFrom().toString().getUTF8String(), "This user is not VIP, can't login...");
|
||||
// // return;
|
||||
// // }
|
||||
// //
|
||||
// // Log(presence->getFrom().toString().getUTF8String(), "Creating new User instance");
|
||||
// //
|
||||
// // if (Transport::instance()->protocol()->tempAccountsAllowed()) {
|
||||
// // std::string server = barejid.substr(barejid.find("%") + 1, barejid.length() - barejid.find("%"));
|
||||
// // res.uin = presence->getTo().getResource().getUTF8String() + "@" + server;
|
||||
// // }
|
||||
// // else {
|
||||
// // if (purple_accounts_find(res.uin.c_str(), Transport::instance()->protocol()->protocol().c_str()) != NULL) {
|
||||
// // PurpleAccount *act = purple_accounts_find(res.uin.c_str(), Transport::instance()->protocol()->protocol().c_str());
|
||||
// // user = Transport::instance()->userManager()->getUserByAccount(act);
|
||||
// // if (user) {
|
||||
// // Log(presence->getFrom().toString().getUTF8String(), "This account is already connected by another jid " << user->jid());
|
||||
// // return;
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // user = (AbstractUser *) new User(res, userkey, m_component, m_presenceOracle, m_entityCapsManager);
|
||||
// // user->setFeatures(isVip ? CONFIG().VIPFeatures : CONFIG().transportFeatures);
|
||||
// // // if (c != NULL)
|
||||
// // // if (Transport::instance()->hasClientCapabilities(c->findAttribute("ver")))
|
||||
// // // user->setResource(stanza.from().resource(), stanza.priority(), Transport::instance()->getCapabilities(c->findAttribute("ver")));
|
||||
// // //
|
||||
// // Transport::instance()->userManager()->addUser(user);
|
||||
// // user->receivedPresence(presence);
|
||||
// // // if (protocol()->tempAccountsAllowed()) {
|
||||
// // // std::string server = stanza.to().username().substr(stanza.to().username().find("%") + 1, stanza.to().username().length() - stanza.to().username().find("%"));
|
||||
// // // server = stanza.from().bare() + server;
|
||||
// // // purple_timeout_add_seconds(15, &connectUser, g_strdup(server.c_str()));
|
||||
// // // }
|
||||
// // // else
|
||||
// // // purple_timeout_add_seconds(15, &connectUser, g_strdup(stanza.from().bare().c_str()));
|
||||
// // // }
|
||||
// // }
|
||||
// // // if (stanza.presence() == Presence::Unavailable && stanza.to().username() == ""){
|
||||
// // // Log(stanza.from().full(), "User is already logged out => sending unavailable presence");
|
||||
// // // Tag *tag = new Tag("presence");
|
||||
// // // tag->addAttribute( "to", stanza.from().bare() );
|
||||
// // // tag->addAttribute( "type", "unavailable" );
|
||||
// // // tag->addAttribute( "from", jid() );
|
||||
// // // j->send( tag );
|
||||
// // // }
|
||||
// }
|
||||
//
|
||||
// if (presence->getType() == Swift::Presence::Unavailable) {
|
||||
// if (user) {
|
||||
// Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(presence->getFrom().toBare());
|
||||
// if (presence->getType() == Swift::Presence::Unavailable && (!highest || (highest && highest->getType() == Swift::Presence::Unavailable))) {
|
||||
// Transport::instance()->userManager()->removeUser(user);
|
||||
// }
|
||||
// }
|
||||
// else if (user && Transport::instance()->protocol()->tempAccountsAllowed() && !((User *) user)->hasOpenedMUC()) {
|
||||
// Transport::instance()->userManager()->removeUser(user);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
369
src/userregistration.cpp
Normal file
369
src/userregistration.cpp
Normal file
|
@ -0,0 +1,369 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "transport/userregistration.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/storagebackend.h"
|
||||
#include "transport/transport.h"
|
||||
#include "transport/user.h"
|
||||
#include "Swiften/Elements/ErrorPayload.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
using namespace Swift;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
UserRegistration::UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend) : Swift::GetResponder<Swift::InBandRegistrationPayload>(component->m_component->getIQRouter()), Swift::SetResponder<Swift::InBandRegistrationPayload>(component->m_component->getIQRouter()) {
|
||||
m_component = component;
|
||||
m_storageBackend = storageBackend;
|
||||
m_userManager = userManager;
|
||||
Swift::GetResponder<Swift::InBandRegistrationPayload>::start();
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::start();
|
||||
}
|
||||
|
||||
UserRegistration::~UserRegistration(){
|
||||
}
|
||||
|
||||
bool UserRegistration::registerUser(const UserInfo &row) {
|
||||
// TODO: move this check to sql()->addUser(...) and let it return bool
|
||||
UserInfo user;
|
||||
bool registered = m_storageBackend->getUser(row.jid, user);
|
||||
// This user is already registered
|
||||
if (registered)
|
||||
return false;
|
||||
|
||||
m_storageBackend->setUser(row);
|
||||
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(m_component->getJID());
|
||||
response->setTo(Swift::JID(row.jid));
|
||||
response->setType(Swift::Presence::Subscribe);
|
||||
|
||||
m_component->m_component->sendPresence(response);
|
||||
|
||||
onUserRegistered(row);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserRegistration::unregisterUser(const std::string &barejid) {
|
||||
UserInfo userInfo;
|
||||
bool registered = m_storageBackend->getUser(barejid, userInfo);
|
||||
// This user is not registered
|
||||
if (!registered)
|
||||
return false;
|
||||
|
||||
onUserUnregistered(userInfo);
|
||||
|
||||
Swift::Presence::ref response;
|
||||
|
||||
User *user = m_userManager->getUserByJID(barejid);
|
||||
|
||||
// roster contains already escaped jids
|
||||
std::list <std::string> roster;
|
||||
m_storageBackend->getBuddies(userInfo.id, roster);
|
||||
|
||||
for(std::list<std::string>::iterator u = roster.begin(); u != roster.end() ; u++){
|
||||
std::string name = *u;
|
||||
|
||||
response = Swift::Presence::create();
|
||||
response->setTo(Swift::JID(barejid));
|
||||
response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString()));
|
||||
response->setType(Swift::Presence::Unsubscribe);
|
||||
m_component->m_component->sendPresence(response);
|
||||
|
||||
response = Swift::Presence::create();
|
||||
response->setTo(Swift::JID(barejid));
|
||||
response->setFrom(Swift::JID(name + "@" + m_component->getJID().toString()));
|
||||
response->setType(Swift::Presence::Unsubscribed);
|
||||
m_component->m_component->sendPresence(response);
|
||||
}
|
||||
|
||||
// Remove user from database
|
||||
m_storageBackend->removeUser(userInfo.id);
|
||||
|
||||
// Disconnect the user
|
||||
if (user) {
|
||||
m_userManager->removeUser(user);
|
||||
}
|
||||
|
||||
response = Swift::Presence::create();
|
||||
response->setTo(Swift::JID(barejid));
|
||||
response->setFrom(m_component->getJID());
|
||||
response->setType(Swift::Presence::Unsubscribe);
|
||||
m_component->m_component->sendPresence(response);
|
||||
|
||||
response = Swift::Presence::create();
|
||||
response->setTo(Swift::JID(barejid));
|
||||
response->setFrom(m_component->getJID());
|
||||
response->setType(Swift::Presence::Unsubscribed);
|
||||
m_component->m_component->sendPresence(response);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload) {
|
||||
if (m_component->m_config["service.protocol"].as<std::string>() == "irc") {
|
||||
Swift::GetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string barejid = from.toBare().toString().getUTF8String();
|
||||
|
||||
// User *user = m_userManager->getUserByJID(barejid);
|
||||
if (!m_component->m_config["registration.enable_public_registration"].as<bool>()) {
|
||||
std::list<std::string> const &x = m_component->m_config["registration.enable_public_registration"].as<std::list<std::string> >();
|
||||
if (std::find(x.begin(), x.end(), from.getDomain().getUTF8String()) == x.end()) {
|
||||
// Log("UserRegistration", "This user has no permissions to register an account");
|
||||
Swift::GetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// const char *_language = user ? user->getLang() : m_component->m_config["registration.language"].as<std::string>().c_str();
|
||||
|
||||
boost::shared_ptr<InBandRegistrationPayload> reg(new InBandRegistrationPayload());
|
||||
|
||||
UserInfo res;
|
||||
bool registered = m_storageBackend->getUser(barejid, res);
|
||||
|
||||
std::string instructions = m_component->m_config["registration.reg_instructions"].as<std::string>();
|
||||
|
||||
reg->setInstructions(instructions);
|
||||
reg->setRegistered(res.id != -1);
|
||||
reg->setUsername(res.uin);
|
||||
if (m_component->m_config["service.protocol"].as<std::string>() != "twitter" && m_component->m_config["service.protocol"].as<std::string>() != "bonjour")
|
||||
reg->setPassword(res.password);
|
||||
|
||||
std::string usernameField = m_component->m_config["registration.reg_username_field"].as<std::string>();
|
||||
|
||||
Form::ref form(new Form(Form::FormType));
|
||||
form->setTitle(tr(_language, _("Registration")));
|
||||
form->setInstructions(tr(_language, instructions));
|
||||
|
||||
HiddenFormField::ref type = HiddenFormField::create();
|
||||
type->setName("FORM_TYPE");
|
||||
type->setValue("jabber:iq:register");
|
||||
form->addField(type);
|
||||
|
||||
TextSingleFormField::ref username = TextSingleFormField::create();
|
||||
username->setName("username");
|
||||
username->setLabel(tr(_language, usernameField));
|
||||
username->setValue(res.uin);
|
||||
username->setRequired(true);
|
||||
form->addField(username);
|
||||
|
||||
if (m_component->m_config["service.protocol"].as<std::string>() != "twitter" && m_component->m_config["service.protocol"].as<std::string>() != "bonjour") {
|
||||
TextPrivateFormField::ref password = TextPrivateFormField::create();
|
||||
password->setName("password");
|
||||
password->setLabel(tr(_language, _("Password")));
|
||||
password->setRequired(true);
|
||||
form->addField(password);
|
||||
}
|
||||
|
||||
ListSingleFormField::ref language = ListSingleFormField::create();
|
||||
language->setName("language");
|
||||
language->setLabel(tr(_language, _("Language")));
|
||||
if (registered)
|
||||
language->setValue(res.language);
|
||||
else
|
||||
language->setValue(m_component->m_config["registration.language"].as<std::string>());
|
||||
// std::map <std::string, std::string> languages = localization.getLanguages();
|
||||
// for (std::map <std::string, std::string>::iterator it = languages.begin(); it != languages.end(); it++) {
|
||||
// language->addOption(FormField::Option((*it).second, (*it).first));
|
||||
// }
|
||||
form->addField(language);
|
||||
|
||||
TextSingleFormField::ref encoding = TextSingleFormField::create();
|
||||
encoding->setName("encoding");
|
||||
encoding->setLabel(tr(_language, _("Encoding")));
|
||||
if (registered)
|
||||
encoding->setValue(res.encoding);
|
||||
else
|
||||
encoding->setValue(m_component->m_config["registration.encoding"].as<std::string>());
|
||||
form->addField(encoding);
|
||||
|
||||
if (registered) {
|
||||
BooleanFormField::ref boolean = BooleanFormField::create();
|
||||
boolean->setName("unregister");
|
||||
boolean->setLabel(tr(_language, _("Remove your registration")));
|
||||
boolean->setValue(0);
|
||||
form->addField(boolean);
|
||||
}
|
||||
|
||||
reg->setForm(form);
|
||||
|
||||
Swift::GetResponder<Swift::InBandRegistrationPayload>::sendResponse(from, id, reg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const Swift::String& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload) {
|
||||
if (m_component->m_config["service.protocol"].as<std::string>() == "irc") {
|
||||
Swift::GetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string barejid = from.toBare().toString().getUTF8String();
|
||||
|
||||
// AbstractUser *user = m_component->userManager()->getUserByJID(barejid);
|
||||
if (!m_component->m_config["registration.enable_public_registration"].as<bool>()) {
|
||||
std::list<std::string> const &x = m_component->m_config["registration.enable_public_registration"].as<std::list<std::string> >();
|
||||
if (std::find(x.begin(), x.end(), from.getDomain().getUTF8String()) == x.end()) {
|
||||
// Log("UserRegistration", "This user has no permissions to register an account");
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UserInfo res;
|
||||
bool registered = m_storageBackend->getUser(barejid, res);
|
||||
|
||||
std::string encoding;
|
||||
std::string language;
|
||||
|
||||
Form::ref form = payload->getForm();
|
||||
if (form) {
|
||||
const std::vector<FormField::ref> fields = form->getFields();
|
||||
for (std::vector<FormField::ref>::const_iterator it = fields.begin(); it != fields.end(); it++) {
|
||||
TextSingleFormField::ref textSingle = boost::dynamic_pointer_cast<TextSingleFormField>(*it);
|
||||
if (textSingle) {
|
||||
if (textSingle->getName() == "username") {
|
||||
payload->setUsername(textSingle->getValue());
|
||||
}
|
||||
else if (textSingle->getName() == "encoding") {
|
||||
encoding = textSingle->getValue().getUTF8String();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
TextPrivateFormField::ref textPrivate = boost::dynamic_pointer_cast<TextPrivateFormField>(*it);
|
||||
if (textPrivate) {
|
||||
if (textPrivate->getName() == "password") {
|
||||
payload->setPassword(textPrivate->getValue());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ListSingleFormField::ref listSingle = boost::dynamic_pointer_cast<ListSingleFormField>(*it);
|
||||
if (listSingle) {
|
||||
if (listSingle->getName() == "language") {
|
||||
language = listSingle->getValue().getUTF8String();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
BooleanFormField::ref boolean = boost::dynamic_pointer_cast<BooleanFormField>(*it);
|
||||
if (boolean) {
|
||||
if (boolean->getName() == "unregister") {
|
||||
if (boolean->getValue()) {
|
||||
payload->setRemove(true);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (payload->isRemove()) {
|
||||
unregisterUser(barejid);
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendResponse(from, id, InBandRegistrationPayload::ref());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!payload->getUsername() || !payload->getPassword()) {
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Register or change password
|
||||
if (payload->getUsername()->isEmpty() ||
|
||||
(payload->getPassword()->isEmpty() && m_component->m_config["service.protocol"].as<std::string>() != "twitter" && m_component->m_config["service.protocol"].as<std::string>() != "bonjour")
|
||||
// || localization.getLanguages().find(language) == localization.getLanguages().end()
|
||||
)
|
||||
{
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_component->m_config["service.protocol"].as<std::string>() == "xmpp") {
|
||||
// User tries to register himself.
|
||||
if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) {
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
|
||||
// User tries to register someone who's already registered.
|
||||
UserInfo user_row;
|
||||
bool registered = m_storageBackend->getUser(Swift::JID(*payload->getUsername()).toBare().toString().getUTF8String(), user_row);
|
||||
if (registered) {
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string username = payload->getUsername()->getUTF8String();
|
||||
// m_component->protocol()->prepareUsername(username);
|
||||
|
||||
std::string newUsername(username);
|
||||
if (!m_component->m_config["registration.username_mask"].as<std::string>().empty()) {
|
||||
newUsername = m_component->m_config["registration.username_mask"].as<std::string>();
|
||||
// replace(newUsername, "$username", username.c_str());
|
||||
}
|
||||
|
||||
// if (!m_component->protocol()->isValidUsername(newUsername)) {
|
||||
// Log("UserRegistration", "This is not valid username: "<< newUsername);
|
||||
// Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// #if GLIB_CHECK_VERSION(2,14,0)
|
||||
// if (!m_component->m_config["registration.reg_allowed_usernames"].as<std::string>().empty() &&
|
||||
// !g_regex_match_simple(m_component->m_config["registration.reg_allowed_usernames"].as<std::string>(), newUsername.c_str(),(GRegexCompileFlags) (G_REGEX_CASELESS | G_REGEX_EXTENDED), (GRegexMatchFlags) 0)) {
|
||||
// Log("UserRegistration", "This is not valid username: "<< newUsername);
|
||||
// Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
// return true;
|
||||
// }
|
||||
// #endif
|
||||
if (!registered) {
|
||||
res.jid = barejid;
|
||||
res.uin = username;
|
||||
res.password = payload->getPassword()->getUTF8String();
|
||||
res.language = language;
|
||||
res.encoding = encoding;
|
||||
res.vip = 0;
|
||||
|
||||
registerUser(res);
|
||||
}
|
||||
else {
|
||||
// change passwordhttp://soumar.jabbim.cz/phpmyadmin/index.php
|
||||
// Log("UserRegistration", "changing user password: "<< barejid << ", " << username);
|
||||
res.jid = barejid;
|
||||
res.password = payload->getPassword()->getUTF8String();
|
||||
res.language = language;
|
||||
res.encoding = encoding;
|
||||
m_storageBackend->setUser(res);
|
||||
onUserUpdated(res);
|
||||
}
|
||||
|
||||
Swift::SetResponder<Swift::InBandRegistrationPayload>::sendResponse(from, id, InBandRegistrationPayload::ref());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue