diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d7ee164d87c6b4331ca6f89231b3d59cc25f2f..b7b76671e6bdd5e3fc994c319dde2a2986b8024c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,12 +43,11 @@ set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") find_package(event) set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") -find_package(Swiften REQUIRED) +find_package(Swiften) if (CMAKE_COMPILER_IS_GNUCXX) set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") -find_package(openssl REQUIRED) -endif() +find_package(openssl) set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") if (WIN32) diff --git a/ChangeLog b/ChangeLog index fe7ded5334e7517694f22c31e3c7c65beca8b02e..9ef83b4825320a212c3561bf2510114f21b2ccf1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +Version 2.0.0-beta3 (2012-XX-XX): + General: + * Log errors related to backend spawning (Show proper log message for + example when path to backend binary is not found). + * Update buddies in database only when it's needed and do not execute + useless database statements. + * Send roster changes also when buddy's group change. + * Fixed bug when transport contact we in all groups. + * Answer to disco#info IQ with proper node (#206). + * Set SQLite3 as default database backend. + * Fixed disconnecting from server caused by sending VCard response + with bad "from" attribute. + * Added Munin plugin (Thanks to Askovpen). + * Added support for more admin_jid JIDs (Thanks to Askovpen). + * Fixed allowed_servers option. + + Libpurple: + * prpl-gg: Fetch the contact list properly (#252). + + Skype: + * Log more errors. + + Backend API: + * Added Python NetworkPlugin class, so it is now easier to write backends + in Python (Thanks to Sarang). + Version 2.0.0-beta2 (2012-03-28): General: * Fixed bug when Roster Item Exchange and subscribe stanzas were sent diff --git a/backends/libpurple/gen_dynamic_purple.py b/backends/libpurple/gen_dynamic_purple.py new file mode 100644 index 0000000000000000000000000000000000000000..2666e791d944c6476a6e660b8ba6f37a74becd9a --- /dev/null +++ b/backends/libpurple/gen_dynamic_purple.py @@ -0,0 +1,251 @@ +import sys +import os + +# intialize for methods used in libpurple macros +methods = ["purple_connection_get_state(", "purple_conversation_get_im_data(", + "purple_conversation_get_chat_data(", "purple_blist_node_get_type("] +macros = ["PURPLE_CONV_IM", "PURPLE_CONV_CHAT", "PURPLE_BLIST_NODE_IS_BUDDY", "PURPLE_CONNECTION_IS_CONNECTED"] +definitions = [] + +if len(sys.argv) != 2: + print "Usage:", sys.argv[0], "" + sys.exit(1) + + +def handle_file(cpp): + global methods + global macros + sys.stdout.write("getting used methods in " + cpp + ": ") + sys.stdout.flush() + + counter = 0 + + new_file = "" + f = open(cpp, "r") + for line in f.readlines(): + new_line = "" + index = 0 + while index < len(line): + new_line += line[index] + if line[index:].startswith("purple_") or line[index:].startswith("wpurple_") or line[index:].startswith("serv_"): + if line[index:].find("=") != -1 and line[index:].find("=") < line[index:].find("("): + index += 1 + continue + if line[index-1] == "_" or line[index:].find("(") == -1 or line[index:].startswith("purple_commands_init") or line[index:].startswith("serv_addr"): + index += 1 + continue + m = line[index:line[index:].find("(")+index] + index += len(m) + if m.find("_wrapped") != -1: + new_line += m[1:] + "(" + m = m.replace("_wrapped", "") + else: + new_line += m[1:] + "_wrapped(" + if not m + "(" in methods and len(m) != 0: + methods += [m + "("] + counter += 1 + index += 1 + + for x in macros: + if new_line.find(x + "_WRAPPED") == -1: + new_line = new_line.replace(x, x + "_WRAPPED") + new_file += new_line + f.close() + + print counter, "new methods found" + return new_file + +def handle_header(header, method): + global definitions + + f = open(os.path.join(sys.argv[1], header), "r") + + lines = f.readlines() + for i in range(len(lines)): + line = lines[i] + if line.find(method) != -1: + if line.startswith(method): + line = lines[i-1][:-1] + line + m = line[:-1] + l = unicode(m).strip() + if l.endswith(")"): + continue + + if m.find("/*") > m.find(";"): + m = m[:m.find("/*")] + m.rstrip() + if len(m) != 0: + while m[-1] == " ": + m = m[:-1] + + index = i; + while not m.endswith(";"): + index += 1 + m += " " + lines[index][:-1].lstrip() + + l = unicode(m).strip() + if (l.startswith("#") or l.startswith("*") or l.startswith("/*") or l.count("***") != 0 or l.count("&&") != 0 + or l.endswith(")")): + continue; + + m = m.replace("G_GNUC_NULL_TERMINATE", "") + + if not m in definitions: + print "found", method[:-1], "in", header + definitions += [m] + break + f.close() + +def get_raw_args(d): + return d[d.find("(")+1:-2] + +def get_args(d): + x = d[d.find("(")+1:-2] + x = x.split(",") + + args = [] + for arg in x: + y = arg.split(" ") + if len(y) == 1: + continue + args += [y[-1].replace("*", "")] + + return args + +def get_name(d): + x = d[:d.find("(")+1].lstrip() + if x.find("wpurple_") != -1: + return x[x.find("wpurple_"):] + if x.find("serv_") != -1: + return x[x.find("serv_"):] + return x[x.find("purple_"):] + +def get_rtype(d): + if d.find("wpurple_") != -1: + return d[:d.find("wpurple_")].lstrip() + if d.find("serv_") != -1: + return d[:d.find("serv_")].lstrip() + return d[:d.find("purple_")].lstrip() + +def output(): + global definitions + + header = open("purple_defs.h", "w") + print >> header, "#pragma once" + print >> header, "#ifdef WIN32" + + print >> header, """ +#include +#include + +#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE) +#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE) +#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE) +#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE) + +#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c)) +#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c)) + +#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) \ + (purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED) +""" + + for d in definitions: + #typedef void (_cdecl * purple_util_set_user_wrapped_func)(const char *dir); + print >> header, "typedef", get_rtype(d), "(_cdecl *", get_name(d)[:-1] + "_wrapped_fnc)(" + get_raw_args(d) + ");" + #extern purple_util_set_user_wrapped_func purple_util_set_user_wrapped; + print >> header, "extern", get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped;" + print >> header, "" + + print >> header, "" + print >> header, "#else" + print >> header, "" + + print >> header, """ +#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT +#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY +#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT +#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP + +#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM +#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT + +#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED +""" + + for d in definitions: + #define purple_util_set_user_wrapped purple_util_set_user + print >> header, "#define", get_name(d)[:-1] + "_wrapped", get_name(d)[:-1] + + print >> header, "#endif" + print >> header, "" + print >> header, "bool resolvePurpleFunctions();" + print >> header, "" + + + cpp = open("purple_defs.cpp", "w") + print >> cpp, "#include \"purple_defs.h\"" + print >> cpp, "" + print >> cpp, "#ifdef WIN32" + print >> cpp, "static HMODULE f_hPurple = NULL;" + for d in definitions: + #purple_util_set_user_wrapped_fnc purple_util_set_user_wrapped = NULL; + print >> cpp, get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped = NULL;" + + print >> cpp, "#endif" + + print >> cpp, "bool resolvePurpleFunctions() {" + print >> cpp, "#ifdef WIN32" + print >> cpp, "\tf_hPurple = LoadLibrary(\"libpurple.dll\");" + print >> cpp, "\tif (!f_hPurple)" + print >> cpp, "\t\t\treturn false;" + for d in definitions: + #purple_util_set_user_wrapped = (purple_util_set_user_wrapped_func)GetProcAddress(f_hPurple, "purple_util_set_user_dir"); + print >> cpp, "\t" + get_name(d)[:-1] + "_wrapped = (" + get_name(d)[:-1] + "_wrapped_fnc)GetProcAddress(f_hPurple, \"" + get_name(d)[:-1] + "\");" + #if (!purple_util_set_user_wrapped) + print >> cpp, "\tif (!" + get_name(d)[:-1] + "_wrapped)" + print >> cpp, "\t\treturn false;" + print >> cpp, "" + print >> cpp, "#endif" + + print >> cpp, "\treturn true;" + print >> cpp, "}" + print >> cpp, "" + + cpp.close() + header.close() + + +for f in os.listdir("."): + if not f.endswith(".cpp") or f.startswith("purple_defs"): + continue + new_file = handle_file(f) + + print "updating", f + fd = open(f, "w") + fd.write(new_file) + fd.close() + +for f in os.listdir(sys.argv[1]): + if not f.endswith(".h"): + continue + for m in methods: + handle_header(f, m) + +sys.argv[1] = sys.argv[1] + "/win32" +for f in os.listdir(sys.argv[1]): + if not f.endswith(".h"): + continue + for m in methods: + handle_header(f, m) + +for m in methods: + found = False + for d in definitions: + if d.find(m[:-1]) != -1: + found = True + break + if not found: + print "NOT FOUND:", m + +output() diff --git a/backends/libpurple/geventloop.cpp b/backends/libpurple/geventloop.cpp index 1dacea4005fef70baecd32b309764e0c1c99d8c4..bccf4b38c15242db3f589dc21a7e231d0145dd88 100644 --- a/backends/libpurple/geventloop.cpp +++ b/backends/libpurple/geventloop.cpp @@ -28,6 +28,8 @@ #include "event.h" #endif +#include "purple_defs.h" + #include "transport/logging.h" DEFINE_LOGGER(logger, "EventLoop"); diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index c971f2735d0c79eda07ca73544695490b482537d..74cef36336f9b9f62b9e8818c6fa412d77b4a7c6 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -27,6 +27,8 @@ #define getpid _getpid #endif +#include "purple_defs.h" + DEFINE_LOGGER(logger_libpurple, "libpurple"); DEFINE_LOGGER(logger, "backend"); @@ -653,7 +655,11 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } void sendData(const std::string &string) { +#ifdef WIN32 + ::send(main_socket, string.c_str(), string.size(), 0); +#else write(main_socket, string.c_str(), string.size()); +#endif if (writeInput == 0) writeInput = purple_input_add(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL); } @@ -789,7 +795,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)); + std::vector groups = getGroups(buddy); + LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy) << " group (" << groups.size() << ")=" << groups[0]); // Status pbnetwork::StatusType status = pbnetwork::STATUS_NONE; @@ -1424,6 +1431,8 @@ debug_init(void) REGISTER_G_LOG_HANDLER("GModule"); REGISTER_G_LOG_HANDLER("GLib-GObject"); REGISTER_G_LOG_HANDLER("GThread"); + REGISTER_G_LOG_HANDLER("GConf"); + #undef REGISTER_G_LOD_HANDLER } @@ -1447,6 +1456,9 @@ static void signed_on(PurpleConnection *gc, gpointer unused) { // force returning of memory chunks allocated by libxml2 to kernel malloc_trim(0); #endif + + // For prpl-gg + execute_purple_plugin_action(gc, "Download buddylist from Server"); } static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) { @@ -1511,6 +1523,13 @@ static void gotAttention(PurpleAccount *account, const char *who, PurpleConversa static bool initPurple() { bool ret; + if (!resolvePurpleFunctions()) { + LOG4CXX_ERROR(logger, "Unable to load libpurple.dll or some of the needed methods"); + return false; + } + + purple_plugins_add_search_path("./plugins"); + purple_util_set_user_dir("./"); remove("./accounts.xml"); remove("./blist.xml"); @@ -1586,7 +1605,11 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi if (cond & PURPLE_INPUT_READ) { char buffer[65535]; char *ptr = buffer; +#ifdef WIN32 + ssize_t n = recv(source, ptr, sizeof(buffer), 0); +#else ssize_t n = read(source, ptr, sizeof(buffer)); +#endif if (n <= 0) { LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server"); exit(errno); diff --git a/backends/libpurple/purple_defs.cpp b/backends/libpurple/purple_defs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6df1b6837397a1f9a86306fd3cb68196ac3a377 --- /dev/null +++ b/backends/libpurple/purple_defs.cpp @@ -0,0 +1,5 @@ +#include "purple_defs.h" +bool resolvePurpleFunctions() { + return true; +} + diff --git a/backends/libpurple/purple_defs.h b/backends/libpurple/purple_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..3058786cc466eebea52a12c82744db90c5225bf1 --- /dev/null +++ b/backends/libpurple/purple_defs.h @@ -0,0 +1,3 @@ +#pragma once + +bool resolvePurpleFunctions(); diff --git a/backends/libpurple/utils.cpp b/backends/libpurple/utils.cpp index 417ad67d35814884f8307647757ba9ac97ccbe45..a4ddf44b7daada6daeeea60f616ac9fa610b7de6 100644 --- a/backends/libpurple/utils.cpp +++ b/backends/libpurple/utils.cpp @@ -47,8 +47,32 @@ #include "win32/win32dep.h" #endif +#include "purple_defs.h" + static GHashTable *ui_info = NULL; +void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name) { + PurplePlugin *plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL; + if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) { + PurplePluginAction *action = NULL; + GList *actions, *l; + + actions = PURPLE_PLUGIN_ACTIONS(plugin, gc); + + for (l = actions; l != NULL; l = l->next) { + if (l->data) { + action = (PurplePluginAction *) l->data; + action->plugin = plugin; + action->context = gc; + if ((std::string) action->label == name) { + action->callback(action); + } + purple_plugin_action_free(action); + } + } + } +} + GHashTable *spectrum_ui_get_info(void) { if(NULL == ui_info) { @@ -122,8 +146,8 @@ int create_socket(char *host, int portno) { main_socket = 0; } - int flags = fcntl(main_socket, F_GETFL); - flags |= O_NONBLOCK; - fcntl(main_socket, F_SETFL, flags); +// int flags = fcntl(main_socket, F_GETFL); +// flags |= O_NONBLOCK; +// fcntl(main_socket, F_SETFL, flags); return main_socket; } diff --git a/backends/libpurple/utils.h b/backends/libpurple/utils.h index 2055b6c1f6728d95d884f0d61b1158c3dc12dd96..72d513a499db29797d2aa7d9921017b1f94f6ce7 100644 --- a/backends/libpurple/utils.h +++ b/backends/libpurple/utils.h @@ -21,10 +21,13 @@ #pragma once #include "purple.h" +#include #ifndef WIN32 void spectrum_sigchld_handler(int sig); #endif int create_socket(char *host, int portno); -GHashTable *spectrum_ui_get_info(void); \ No newline at end of file +GHashTable *spectrum_ui_get_info(void); + +void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name); diff --git a/backends/skype/main.cpp b/backends/skype/main.cpp index 1ccd81e4f0fb1d39e3e698579db7806fd35c99fa..838d9231d1bea354b681332ab961cc6d4ca1b5ea 100644 --- a/backends/skype/main.cpp +++ b/backends/skype/main.cpp @@ -165,6 +165,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { if (skype) { LOG4CXX_INFO(logger, "User wants to logout, logging out"); skype->logout(); + Logging::shutdownLogging(); exit(1); } } @@ -801,6 +802,7 @@ static int create_socket(char *host, int portno) { if ((hos = gethostbyname(host)) == NULL) { // strerror() will not work for gethostbyname() and hstrerror() // is supposedly obsolete + Logging::shutdownLogging(); exit(1); } serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]); @@ -823,6 +825,7 @@ static gboolean transportDataReceived(GIOChannel *source, GIOCondition condition ssize_t n = read(m_sock, ptr, sizeof(buffer)); if (n <= 0) { LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server"); + Logging::shutdownLogging(); exit(errno); } std::string d = std::string(buffer, n); @@ -831,6 +834,7 @@ static gboolean transportDataReceived(GIOChannel *source, GIOCondition condition } static void io_destroy(gpointer data) { + Logging::shutdownLogging(); exit(1); } diff --git a/backends/template/main.cpp b/backends/template/main.cpp index 047c54ab2b54287f53714137d33176be6c86d446..bc7bc011c1d19b88aaf8991fee786accb8b8a1ab 100644 --- a/backends/template/main.cpp +++ b/backends/template/main.cpp @@ -57,6 +57,8 @@ class TemplatePlugin : public NetworkPlugin { void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { handleConnected(user); + LOG4CXX_INFO(logger, user << ": Added buddy - Echo."); + handleBuddyChanged(user, "echo", "Echo", std::vector(), pbnetwork::STATUS_ONLINE); } void handleLogoutRequest(const std::string &user, const std::string &legacyName) { @@ -64,6 +66,9 @@ class TemplatePlugin : public NetworkPlugin { void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") { LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << "."); + if (legacyName == "echo") { + handleMessage(user, legacyName, message); + } } void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { diff --git a/backends/template/template_backend.py b/backends/template/template_backend.py new file mode 100755 index 0000000000000000000000000000000000000000..575d33106b57907ad74b68bb80803f70d8b17c19 --- /dev/null +++ b/backends/template/template_backend.py @@ -0,0 +1,103 @@ +#!/usr/bin/python + +import asyncore, argparse, protocol_pb2, socket, logging +from NetworkPlugin import NetworkPlugin + +np = None + + +logger = logging.getLogger('Template Backend') +logger.setLevel(logging.DEBUG) +ch = logging.StreamHandler() +ch.setLevel(logging.DEBUG) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +ch.setFormatter(formatter) +logger.addHandler(ch) + + +def handleTransportData(data): + """ + This function is called when data is received from the NetworkPlugin server + """ + np.handleDataRead(data) + + +class SpectrumPlugin(NetworkPlugin): + global logger + def __init__(self, iochannel): + NetworkPlugin.__init__(self) + self.iochannel = iochannel + logger.info("Starting plugin.") + + def sendData(self, string): + """ + NetworkPlugin uses this method to send the data to networkplugin server + """ + self.iochannel.sendData(string) + logger.info("Starting plugin.") + + def handleLoginRequest(self, user, legacyName, password): + self.handleConnected(user) + logger.info("Added Echo Buddy") + self.handleBuddyChanged(user, "echo", "Echo", [], protocol_pb2.STATUS_ONLINE) + + def handleLogoutRequest(self, user, legacyName): + pass + + def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""): + logger.info("Message sent from " + user + ' to ' + legacyName) + if(legacyName == "echo"): + logger.info("Message Echoed: " + message) + self.handleMessage(user, legacyName, message) + + def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups): + logger.info("Added Buddy " + buddyName) + self.handleBuddyChanged(user, buddyName, alias, groups, protocol_pb2.STATUS_ONLINE) + + def handleBuddyRemovedRequest(self, user, buddyName, groups): + pass + + + +class IOChannel(asyncore.dispatcher): + def __init__(self, host, port, readCallBack): + asyncore.dispatcher.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.connect((host, port)) + self.handleReceivedData = readCallBack + self.send_buffer = "" + + def sendData(self, data): + self.send_buffer += data + + def handle_connect(self): + pass + + def handle_close(self): + self.close() + + def handle_read(self): + data = self.recv(65536) + self.handleReceivedData(data) + + def handle_write(self): + sent = self.send(self.send_buffer) + self.send_buffer = self.send_buffer[sent:] + + def writable(self): + return (len(self.send_buffer) > 0) + + def readable(self): + return True + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--host', type=str, required=True) + parser.add_argument('--port', type=int, required=True) + parser.add_argument('config_file', type=str) + + args = parser.parse_args() + io = IOChannel(args.host, args.port, handleTransportData) + np = SpectrumPlugin(io) + asyncore.loop() diff --git a/cmake_modules/CommuniConfig.cmake b/cmake_modules/CommuniConfig.cmake index 7f8038476d949faddfb40251af15bd41391c116e..436ad61e9ed23e78813253ee8855c8849ffcc75a 100644 --- a/cmake_modules/CommuniConfig.cmake +++ b/cmake_modules/CommuniConfig.cmake @@ -1,5 +1,8 @@ -FIND_LIBRARY(IRC_LIBRARY NAMES Communi) -FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES Communi qt4/Communi ) +find_package(Qt4 REQUIRED) +include( ${QT_USE_FILE} ) + +FIND_LIBRARY(IRC_LIBRARY NAMES Communi PATHS ${QT_LIBRARY_DIR}) +FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATHS ${QT_INCLUDE_DIR} PATH_SUFFIXES Communi) # message( STATUS ${IRC_LIBRARY}) if( IRC_LIBRARY AND IRC_INCLUDE_DIR ) diff --git a/docs/Doxyfile b/docs/Doxyfile deleted file mode 100644 index 45a29656e901d8b86f114d708e3099d182a1a7fb..0000000000000000000000000000000000000000 --- a/docs/Doxyfile +++ /dev/null @@ -1,1510 +0,0 @@ -# Doxyfile 1.5.8 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = "libtransport" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = "2.0" - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = /home/hanzz/code/libtransport/docs/../docs/html - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, -# Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = /home/hanzz/code/libtransport/docs/../include/transport/ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = "_darcs" - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = "*/.*" "*/.*/*" - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = "/home/hanzz/code/libtransport/docs/examples" - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = "/home/hanzz/code/libtransport/docs" - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = /home/hanzz/code/libtransport/docs/../docs/html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. - -GENERATE_TREEVIEW = NONE - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = "" - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = "" - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = "" - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = YES - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = "/usr/bin" - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = YES - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Options related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/include/transport/localbuddy.h b/include/transport/localbuddy.h index 16bf12c14de6ff79d81fc601d048f6ff409c5e2d..492a3c70565c4c744f7239cf56bc3279ee204691 100644 --- a/include/transport/localbuddy.h +++ b/include/transport/localbuddy.h @@ -59,12 +59,7 @@ class LocalBuddy : public Buddy { } std::vector getGroups() { return m_groups; } - void setGroups(const std::vector &groups) { - bool changed = m_groups.size() != groups.size(); - m_groups = groups; - if (changed) - getRosterManager()->storeBuddy(this); - } + void setGroups(const std::vector &groups); private: std::string m_name; diff --git a/include/transport/logging.h b/include/transport/logging.h index 4abf92dd5058954f4de34423b05ac716c58ccf2b..d31031039a1d4ab3f34064ade76a2c6fd9b31206 100644 --- a/include/transport/logging.h +++ b/include/transport/logging.h @@ -35,6 +35,7 @@ #include "log4cxx/helpers/fileinputstream.h" #include "log4cxx/helpers/transcoder.h" #include "log4cxx/logger.h" +#include "log4cxx/logmanager.h" #define DEFINE_LOGGER(VAR, NAME) static log4cxx::LoggerPtr VAR = log4cxx::Logger::getLogger(NAME); @@ -55,6 +56,7 @@ namespace Logging { void initBackendLogging(Config *config); void initMainLogging(Config *config); +void shutdownLogging(); } diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 9a0dfb9be64c7bb1c1b644edbecdc21951e1c649..9f440152a6111e2e6ceb61ccd1d6a6508b0a1590 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -34,6 +34,22 @@ namespace Transport { /// development. class NetworkPlugin { public: + + class PluginConfig { + public: + PluginConfig() : m_needPassword(true) {} + virtual ~PluginConfig() {} + + void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; } + void setExtraFields(const std::vector &fields) { m_extraFields = fields; } + + private: + bool m_needPassword; + std::vector m_extraFields; + + friend class NetworkPlugin; + }; + /// Creates new NetworkPlugin and connects the Spectrum2 NetworkPluginServer. /// \param loop Event loop. /// \param host Host where Spectrum2 NetworkPluginServer runs. @@ -43,6 +59,8 @@ class NetworkPlugin { /// Destructor. virtual ~NetworkPlugin(); + void sendConfig(const PluginConfig &cfg); + /// Call this function when legacy network buddy changed. /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") /// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com") diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 8f3ac42c98a3909e6c95ba234aa22a68835e6ef5..8dddaf7e7a03b8195bbfbd08aa33b030bc17b5f3 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -44,6 +44,7 @@ message Login { required string user = 1; required string legacyName = 2; required string password = 3; + repeated string extraFields = 4; } message Logout { @@ -122,6 +123,10 @@ message FileTransferData { required bytes data = 2; } +message BackendConfig { + required string config = 1; +} + message WrapperMessage { enum Type { TYPE_CONNECTED = 1; @@ -152,6 +157,7 @@ message WrapperMessage { TYPE_FT_PAUSE = 27; TYPE_FT_CONTINUE = 28; TYPE_EXIT = 29; + TYPE_BACKEND_CONFIG = 30; } required Type type = 1; optional bytes payload = 2; diff --git a/include/transport/transport.h b/include/transport/transport.h index 4a875754fdf857285e08a57572da3df4138771e0..3d81307fff0a6e34aab2a13c50794e739da78694 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -37,6 +37,7 @@ #include "transport/config.h" #include "transport/factory.h" #include "transport/presenceoracle.h" +#include namespace Transport { // typedef enum { CLIENT_FEATURE_ROSTERX = 2, @@ -165,6 +166,7 @@ namespace Transport { private: void handleConnected(); void handleConnectionError(const Swift::ComponentError &error); + void handleServerStopped(boost::optional e); void handlePresence(Swift::Presence::ref presence); void handleDataRead(const Swift::SafeByteArray &data); void handleDataWritten(const Swift::SafeByteArray &data); diff --git a/munin/spectrum2_ b/munin/spectrum2_ new file mode 100755 index 0000000000000000000000000000000000000000..5f13e46f9ee0a6fb3a519a36f9e75ae28c9ded60 --- /dev/null +++ b/munin/spectrum2_ @@ -0,0 +1,166 @@ +#!/usr/bin/perl + +# config: +# [spectrum2_*] +# env.admin_jid tradmin@host.org +# env.password jid_password +# env.transports icq.host.org xmpp.host.org +# +# symlinks: +# spectrum2_backends spectrum2_memory spectrum2_users spectrum2_messages spectrum2_messages_sec +# +# +use AnyEvent; +use AnyEvent::XMPP::Client; +use AnyEvent::XMPP::Component; +use AnyEvent::XMPP::Ext::Disco; +use AnyEvent::XMPP::Ext::Version; +use AnyEvent::XMPP::Namespaces qw/xmpp_ns/; +use AnyEvent::XMPP::Util qw/simxml/; +use XML::Simple; +use Time::HiRes qw ( setitimer ITIMER_REAL time ); +use strict; +$|=1; + +$SIG{ALRM} = sub { exit; }; +setitimer(ITIMER_REAL, 30, 1); + + +my %config=( + users => { + title=>'Buddies online', + vlabel=>'users', + info=>'Number of users that currently use the spectrum transports.', + command=>'online_users_count', + base=>'--base 1000', + x=>'1', + }, + backends => { + title=>'Backends running', + vlabel=>'backends', + info=>'Number of backends that currently running.', + command=>'backends_count', + base=>'--base 1000', + x=>'1', + }, + memory => { + title=>'Memory usage of transports', + vlabel=>'megabytes', + info=>'Memory usage of spectrum transports.', + command=>'used_memory', + base=>'--base 1024', + x=>'1024', + }, + messages => { + title=>'Messages send over transport', + vlabel=>'messages', + info=>'Messages send over spectrum transports.', + command=>'', + base=>'--base 1000', + x=>'1', + }, + messages_sec => { + title=>'Messages send over transport', + vlabel=>'messages/sec', + info=>'Messages send per second over spectrum transports.', + command=>'', + base=>'--base 1000', + x=>'1', + }, +); +my @queue=('_out','_in'); +$0 =~ /spectrum2_(.+)*$/; +my $func = $1; +exit 2 unless defined $func; +my %tr; +my $count=0; + foreach (split(' ',$ENV{'transports'})){ + if ($func=~/messages/) + { + $tr{$_."_in"}=$count; + $count++; + $tr{$_."_out"}=$count; + $count++; + } + else + { + $tr{$_}=$count; + $count++; + } + } + +if (exists $ARGV[0] and $ARGV[0] eq "config") +{ + print "graph_title ".$config{$func}->{'title'}."\n"; + print "graph_vlabel ".$config{$func}->{'vlabel'}."\n"; + print "graph_category spectrum2\n"; + foreach (keys (%tr)){ + print "r".$tr{$_}.".label ".$_."\n"; + if ($func eq 'messages_sec') + { + print "r".$tr{$_}.".type DERIVE\n"; + print "r".$tr{$_}.".min 0\n"; + } + } + print "graph_args ".$config{$func}->{'base'}."\n"; + print "graph_info ".$config{$func}->{'info'}."\n"; + exit 0; +} + +binmode( STDOUT); +my $xs=new XML::Simple; +my $cl=AnyEvent::XMPP::Client->new(debug=>0); +my $j=AnyEvent->condvar; +$cl->add_account($ENV{'admin_jid'}.'/'.time,$ENV{'password'}); +$cl->reg_cb( + session_ready => \&cl_sess, + disconnect => \&cl_disc, + message => \&cl_msg, +); +$cl->start; +$j->wait; + + +sub cl_disc +{ +my ($cl,$acc,$h,$p,$reas)=@_; + print "disc ($h:$p) $reas\n"; +} +sub cl_sess +{ + my($cl,$acc)=@_; + foreach (keys (%tr)){ + if ($func=~/messages/) + { + if (s/_in$//) + { + $cl->send_message("messages_from_xmpp",$_,undef,'chat'); + }; + if (s/_out$//) + { + $cl->send_message("messages_to_xmpp",$_,undef,'chat'); + } + } + else + { + $cl->send_message($config{$func}->{'command'},$_,undef,'chat'); + } + } +} +sub cl_msg +{ + my ($cl,$acc,$msg)=@_; + if ($func=~/messages/) + { + print "r".$tr{$msg->from.$queue[-1]}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n"; + delete( $tr{$msg->from.$queue[-1]}); + pop(@queue); + if ($#queue==-1){@queue=("_out","_in");} + } + else + { + print "r".$tr{$msg->from}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n"; + delete( $tr{$msg->from}); + } + exit if (scalar(keys %tr)==0); +} diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 179b2f0829ad7a9cb782b3971fcd7851b7ae6993..c6d52eb7e6aa519a15e1f272e874be10a6388c5c 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -60,6 +60,25 @@ NetworkPlugin::NetworkPlugin() { NetworkPlugin::~NetworkPlugin() { } +void NetworkPlugin::sendConfig(const PluginConfig &cfg) { + std::string data = "[registration]"; + data += std::string("needPassword=") + (cfg.m_needPassword ? "1" : "0") + "\n"; + + for (std::vector::const_iterator it = cfg.m_extraFields.begin(); it != cfg.m_extraFields.end(); it++) { + data += std::string("extraField=") + (*it) + "\n"; + } + + pbnetwork::BackendConfig m; + m.set_config(data); + + std::string message; + m.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BACKEND_CONFIG); + + send(message); +} + void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml) { pbnetwork::ConversationMessage m; m.set_username(user); diff --git a/plugin/python/CMakeLists.txt b/plugin/python/CMakeLists.txt index 26ed8937f217ac9518e11328b74e3468de1b6109..a217531d10a6bd2140a796bed7f203c2b1fe3056 100644 --- a/plugin/python/CMakeLists.txt +++ b/plugin/python/CMakeLists.txt @@ -5,12 +5,12 @@ if (PROTOBUF_FOUND) set (PROTOBUF_PROTOC_EXECUTABLE protoc) endif() ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/ ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.proto + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/protocol_pb2.py + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_SOURCE_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/ ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.proto COMMENT "Running Python protocol buffer compiler on protocol.proto" DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.proto ) - ADD_CUSTOM_TARGET(pb-python ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py) + ADD_CUSTOM_TARGET(pb-python ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol_pb2.py) endif() diff --git a/plugin/python/NetworkPlugin.py b/plugin/python/NetworkPlugin.py new file mode 100644 index 0000000000000000000000000000000000000000..717731fe18d58a407e36248abd15d67ef08e06e6 --- /dev/null +++ b/plugin/python/NetworkPlugin.py @@ -0,0 +1,524 @@ +import protocol_pb2, socket, struct, sys, os + +def WRAP(MESSAGE, TYPE): + wrap = protocol_pb2.WrapperMessage() + wrap.type = TYPE + wrap.payload = MESSAGE + return wrap.SerializeToString() + +class NetworkPlugin: + """ + Creates new NetworkPlugin and connects the Spectrum2 NetworkPluginServer. + @param loop: Event loop. + @param host: Host where Spectrum2 NetworkPluginServer runs. + @param port: Port. + """ + + def __init__(self): + self.m_pingReceived = False + self.m_data = "" + self.m_init_res = 0 + + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = ""): + m = protocol_pb2.ConversationMessage() + m.userName = user + m.buddyName = legacyName + m.message = msg + m.nickname = nickname + m.xhtml = xhtml + + message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) + self.send(message) + + def handleAttention(self, user, buddyName, msg): + m = protocol_pb2.ConversationMessage() + m.userName = user + m.buddyName = buddyName + m.message = msg + + message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ATTENTION) + self.send(message) + + def handleVCard(self, user, ID, legacyName, fullName, nickname, photo): + vcard = protocol_pb2.VCard() + vcard.userName = user + vcard.buddyName = legacyName + vcard.id = ID + vcard.fullname = fullName + vcard.nickname = nickname + vcard.photo = photo + + message = WRAP(vcard.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_VCARD) + self.send(message) + + + def handleSubject(self, user, legacyName, msg, nickname = ""): + m = protocol_pb2.ConversationMessage() + m.userName = user + m.buddyName = legacyName + m.message = msg + m.nickname = nickname + + message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ROOM_SUBJECT_CHANGED) + #print "SENDING MESSAGE" + self.send(message) + + + def handleBuddyChanged(self, user, buddyName, alias, groups, status, statusMessage = "", iconHash = "", blocked = False): + buddy = protocol_pb2.Buddy() + buddy.userName = user + buddy.buddyName = buddyName + buddy.alias = alias + buddy.group.extend(groups) + buddy.status = status + buddy.statusMessage = statusMessage + buddy.iconHash = iconHash + buddy.blocked = blocked + + message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_CHANGED) + self.send(message) + + + def handleBuddyTyping(self, user, buddyName): + buddy = protocol_pb2.Buddy() + buddy.userName = user + buddy.buddyName = buddyName + + message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING) + self.send(message); + + def handleBuddyTyped(self, user, buddyName): + buddy = protocol_pb2.Buddy() + buddy.userName = user + buddy.buddyName = buddyName + + message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED) + self.send(message); + + def handleBuddyStoppedTyping(self, user, buddyName): + buddy = protocol_pb2.Buddy() + buddy.userName = user + buddy.buddyName = buddyName + + message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING) + self.send(message) + + def handleAuthorization(self, user, buddyName): + buddy = protocol_pb2.Buddy() + buddy.userName = user + buddy.buddyName = buddyName + + message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_AUTH_REQUEST) + self.send(message) + + + def handleConnected(self, user): + d = protocol_pb2.Connected() + d.user = user + + message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONNECTED) + self.send(message); + + + def handleDisconnected(self, user, error = 0, msg = ""): + d = protocol_pb2.Disconnected() + d.user = user + d.error = error + d.message = msg + + message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_DISCONNECTED) + self.send(message); + + + def handleParticipantChanged(self, user, nickname, room, flags, status, statusMessage = "", newname = ""): + d = protocol_pb2.Participant() + d.userName = user + d.nickname = nickname + d.room = room + d.flag = flags + d.newname = newname + d.status = status + d.statusMessage = statusMessage + + message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_PARTICIPANT_CHANGED) + self.send(message); + + + def handleRoomNicknameChanged(self, user, r, nickname): + room = protocol_pb2.Room() + room.userName = user + room.nickname = nickname + room.room = r + room.password = "" + + message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ROOM_NICKNAME_CHANGED) + self.send(message); + + + def handleFTStart(self, user, buddyName, fileName, size): + room = protocol_pb2.File() + room.userName = user + room.buddyName = buddyName + room.fileName = fileName + room.size = size + + message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_START) + self.send(message); + + def handleFTFinish(self, user, buddyName, fileName, size, ftid): + room = protocol_pb2.File() + room.userName = user + room.buddyName = buddyName + room.fileName = fileName + room.size = size + + # Check later + if ftid != 0: + room.ftID = ftid + + message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_FINISH) + self.send(message) + + + def handleFTData(self, ftID, data): + d = protocol_pb2.FileTransferData() + d.ftid = ftID + d.data = data + + message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA); + self.send(message) + + def handleLoginPayload(self, data): + payload = protocol_pb2.Login() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleLoginRequest(payload.user, payload.legacyName, payload.password) + + def handleLogoutPayload(self, data): + payload = protocol_pb2.Logout() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleLogoutRequest(self, payload.user, payload.legacyName) + + def handleStatusChangedPayload(data): + payload = protocol_pb2.Status() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleStatusChangeRequest(payload.userName, payload.status, payload.statusMessage) + + def handleConvMessagePayload(self, data): + payload = protocol_pb2.ConversationMessage() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml) + + def handleAttentionPayload(self, data): + payload = protocol_pb2.ConversationMessage() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleAttentionRequest(payload.userName, payload.buddyName, payload.message) + + def handleFTStartPayload(self, data): + payload = protocol_pb2.File() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleFTStartRequest(payload.userName, payload.buddyName, payload.fileName, payload.size, payload.ftID); + + def handleFTFinishPayload(self, data): + payload = protocol_pb2.File() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleFTFinishRequest(payload.userName, payload.buddyName, payload.fileName, payload.size, payload.ftID) + + def handleFTPausePayload(self, data): + payload = protocol_pb2.FileTransferData() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleFTPauseRequest(payload.ftID) + + def handleFTContinuePayload(self, data): + payload = protocol_pb2.FileTransferData() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleFTContinueRequest(payload.ftID) + + def handleJoinRoomPayload(self, data): + payload = protocol_pb2.Room() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleJoinRoomRequest(payload.userName, payload.room, payload.nickname, payload.password) + + def handleLeaveRoomPayload(self, data): + payload = protocol_pb2.Room() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleLeaveRoomRequest(payload.userName, payload.room) + + def handleVCardPayload(self, data): + payload = protocol_pb2.VCard() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + if payload.HasField('photo'): + self.handleVCardUpdatedRequest(payload.userName, payload.photo, payload.nickname) + elif len(payload.buddyName) > 0: + self.handleVCardRequest(payload.userName, payload.buddyName, payload.id) + + def handleBuddyChangedPayload(self, data): + payload = protocol_pb2.Buddy() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + if payload.HasField('blocked'): + self.handleBuddyBlockToggled(payload.userName, payload.buddyName, payload.blocked) + else: + groups = [g for g in payload.group] + self.handleBuddyUpdatedRequest(payload.userName, payload.buddyName, payload.alias, groups); + + def handleBuddyRemovedPayload(self, data): + payload = protocol_pb2.Buddy() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + groups = [g for g in payload.group] + self.handleBuddyRemovedRequest(payload.userName, payload.buddyName, groups); + + def handleChatStatePayload(self, data, msgType): + payload = protocol_pb2.Buddy() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + if msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING: + self.handleTypingRequest(payload.userName, payload.buddyName) + elif msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED: + self.handleTypedRequest(payload.userName, payload.buddyName) + elif msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING: + self.handleStoppedTypingRequest(payload.userName, payload.buddyName) + + + def handleDataRead(self, data): + self.m_data += data + while len(self.m_data) != 0: + expected_size = 0 + if (len(self.m_data) >= 4): + expected_size = struct.unpack('!I', self.m_data[0:4])[0] + if (len(self.m_data) - 4 < expected_size): + return + else: + return + + wrapper = protocol_pb2.WrapperMessage() + if (wrapper.ParseFromString(self.m_data[4:]) == False): + self.m_data = self.m_data[expected_size+4:] + return + + self.m_data = self.m_data[4+expected_size:] + + if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN: + self.handleLoginPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGOUT: + self.handleLogoutPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_PING: + self.sendPong() + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE: + self.handleConvMessagePayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_JOIN_ROOM: + self.handleJoinRoomPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_LEAVE_ROOM: + self.handleLeaveRoomPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_VCARD: + self.handleVCardPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_CHANGED: + self.handleBuddyChangedPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_REMOVED: + self.handleBuddyRemovedPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_STATUS_CHANGED: + self.handleStatusChangedPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING: + self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED: + self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING: + self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_ATTENTION: + self.handleAttentionPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_START: + self.handleFTStartPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_FINISH: + self.handleFTFinishPayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_PAUSE: + self.handleFTPausePayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_CONTINUE: + self.handleFTContinuePayload(wrapper.payload) + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_EXIT: + self.handleExitRequest() + + + def send(self, data): + header = struct.pack('!I',len(data)) + self.sendData(header + data) + + def checkPing(self): + if (self.m_pingReceived == False): + self.handleExitRequest() + self.m_pingReceived = False + + + def sendPong(self): + self.m_pingReceived = True + wrap = protocol_pb2.WrapperMessage() + wrap.type = protocol_pb2.WrapperMessage.TYPE_PONG + message = wrap.SerializeToString() + self.send(message) + self.sendMemoryUsage() + + + def sendMemoryUsage(self): + stats = protocol_pb2.Stats() + + stats.init_res = self.m_init_res + res = 0 + shared = 0 + + e_res, e_shared = self.handleMemoryUsage() + + stats.res = res + e_res + stats.shared = shared + e_shared + stats.id = str(os.getpid()) + + message = WRAP(stats.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_STATS) + self.send(message) + + + def handleLoginRequest(self, user, legacyName, password): + """ + Called when XMPP user wants to connect legacy network. + You should connect him to legacy network and call handleConnected or handleDisconnected function later. + @param user: XMPP JID of user for which this event occurs. + @param legacyName: Legacy network name of this user used for login. + @param password: Legacy network password of this user. + """ + + #\msc + #NetworkPlugin,YourNetworkPlugin,LegacyNetwork; + #NetworkPlugin->YourNetworkPlugin [label="handleLoginRequest(...)", URL="\ref NetworkPlugin::handleLoginRequest()"]; + #YourNetworkPlugin->LegacyNetwork [label="connect the legacy network"]; + #--- [label="If password was valid and user is connected and logged in"]; + #YourNetworkPlugin<-LegacyNetwork [label="connected"]; + #YourNetworkPlugin->NetworkPlugin [label="handleConnected()", URL="\ref NetworkPlugin::handleConnected()"]; + #--- [label="else"]; + #YourNetworkPlugin<-LegacyNetwork [label="disconnected"]; + #YourNetworkPlugin->NetworkPlugin [label="handleDisconnected()", URL="\ref NetworkPlugin::handleDisconnected()"]; + #\endmsc + + raise NotImplementedError, "Implement me" + + def handleLogoutRequest(self, user, legacyName): + """ + Called when XMPP user wants to disconnect legacy network. + You should disconnect him from legacy network. + @param user: XMPP JID of user for which this event occurs. + @param legacyName: Legacy network name of this user used for login. + """ + + raise NotImplementedError, "Implement me" + + def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""): + """ + Called when XMPP user sends message to legacy network. + @param user: XMPP JID of user for which this event occurs. + @param legacyName: Legacy network name of buddy or room. + @param message: Plain text message. + @param xhtml: XHTML message. + """ + + raise NotImplementedError, "Implement me" + + def handleVCardRequest(self, user, legacyName, ID): + """ Called when XMPP user requests VCard of buddy. + @param user: XMPP JID of user for which this event occurs. + @param legacyName: Legacy network name of buddy whose VCard is requested. + @param ID: ID which is associated with this request. You have to pass it to handleVCard function when you receive VCard.""" + + #\msc + #NetworkPlugin,YourNetworkPlugin,LegacyNetwork; + #NetworkPlugin->YourNetworkPlugin [label="handleVCardRequest(...)", URL="\ref NetworkPlugin::handleVCardRequest()"]; + #YourNetworkPlugin->LegacyNetwork [label="start VCard fetching"]; + #YourNetworkPlugin<-LegacyNetwork [label="VCard fetched"]; + #YourNetworkPlugin->NetworkPlugin [label="handleVCard()", URL="\ref NetworkPlugin::handleVCard()"]; + #\endmsc + + pass + + + def handleVCardUpdatedRequest(self, user, photo, nickname): + """ + Called when XMPP user updates his own VCard. + You should update the VCard in legacy network too. + @param user: XMPP JID of user for which this event occurs. + @param photo: Raw photo data. + """ + pass + + def handleJoinRoomRequest(self, user, room, nickname, pasword): + pass + + def handleLeaveRoomRequest(self, user, room): + pass + + def handleStatusChangeRequest(self, user, status, statusMessage): + pass + + def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups): + pass + + def handleBuddyRemovedRequest(self, user, buddyName, groups): + pass + + def handleBuddyBlockToggled(self, user, buddyName, blocked): + pass + + def handleTypingRequest(self, user, buddyName): + pass + + def handleTypedRequest(self, user, buddyName): + pass + + def handleStoppedTypingRequest(self, user, buddyName): + pass + + def handleAttentionRequest(self, user, buddyName, message): + pass + + def handleFTStartRequest(self, user, buddyName, fileName, size, ftID): + pass + + def handleFTFinishRequest(self, user, buddyName, fileName, size, ftID): + pass + + def handleFTPauseRequest(self, ftID): + pass + + def handleFTContinueRequest(self, ftID): + pass + + def handleMemoryUsage(self): + return (0,0) + + def handleExitRequest(self): + sys.exit(1) + + def sendData(self, data): + pass + diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 88ec12c87c6ef3fd878d148e0f04095619f473ab..5018ae8b3e57e773e9c752441744345769b8bea6 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -14,8 +14,8 @@ admin_password=test #cert_password=test #password to that certificate if any users_per_backend=10 #backend=../..//backends/libpurple/spectrum2_libpurple_backend -backend=../../backends/template/spectrum2_template_backend -protocol=prpl-xmpp +backend=../../backends/template/template_backend.py +protocol=prpl-jabber #protocol=prpl-msn #protocol=any #protocol=prpl-icq diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index c22569d0366e381b82a5cae115fad271ade1832b..1229cdb1165c5dfe9f3b1dc13652a5fbbb840d7b 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -310,12 +310,12 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; } - if (CONFIG_STRING(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) { + if (CONFIG_VECTOR(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) { std::cerr << itr->path().string() << ": service.admin_jid or service.admin_password empty. This server can't be queried over XMPP.\n"; } finished++; - Swift::Client *client = new Swift::Client(CONFIG_STRING(&cfg, "service.admin_jid"), CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories); + Swift::Client *client = new Swift::Client(CONFIG_VECTOR(&cfg, "service.admin_jid")[0], CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories); client->setAlwaysTrustCertificates(); client->onConnected.connect(boost::bind(&handleConnected, client, CONFIG_STRING(&cfg, "service.jid"))); client->onDisconnected.connect(bind(&handleDisconnected, client, _1, CONFIG_STRING(&cfg, "service.jid"))); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c3e301da2b07b2ab87eafa2835ec948073b7adf6..3fd237984d66a25e07b0b15f5486adbef37e3800 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,16 +44,11 @@ if (CMAKE_COMPILER_IS_GNUCXX) endif() endif() -if (NOT CMAKE_COMPILER_IS_GNUCXX) - include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/protobuf/libprotobuf") - TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 libprotobuf ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) -else () - if (WIN32) - TARGET_LINK_LIBRARIES(transport transport-plugin sqlite3 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARIES}) - else() - TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY}) - endif() -endif() +if (WIN32) + TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) +else (WIN32) + TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY}) +endif(WIN32) SET_TARGET_PROPERTIES(transport PROPERTIES VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION} diff --git a/src/admininterface.cpp b/src/admininterface.cpp index c79db37cb78b1f2e54999ed476206ea6d9d0f523..db3c53a6478c19da6ef85a225fceedd162a80ad1 100644 --- a/src/admininterface.cpp +++ b/src/admininterface.cpp @@ -59,11 +59,13 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { if (!message->getTo().getNode().empty()) return; - if (message->getFrom().toBare().toString() != CONFIG_STRING(m_component->getConfig(), "service.admin_jid")) { - LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString()); - return; + std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid"); + if (std::find(x.begin(), x.end(), message->getFrom().toBare().toString()) == x.end()) { + LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString()); + return; + } - + // Ignore empty messages if (message->getBody().empty()) { return; @@ -257,6 +259,14 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { } message->setBody(lst); } + else if (message->getBody() == "messages_from_xmpp") { + int msgCount = m_userManager->getMessagesToBackend(); + message->setBody(boost::lexical_cast(msgCount)); + } + else if (message->getBody() == "messages_to_xmpp") { + int msgCount = m_userManager->getMessagesToXMPP(); + message->setBody(boost::lexical_cast(msgCount)); + } else if (message->getBody().find("help") == 0) { std::string help; help += "General:\n"; @@ -267,6 +277,9 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { help += " online_users_count - number of online users\n"; help += " online_users_per_backend - shows online users per backends\n"; help += " has_online_user - returns 1 if user is online\n"; + help += "Messages:\n"; + help += " messages_from_xmpp - get number of messages received from XMPP users\n"; + help += " messages_to_xmpp - get number of messages sent to XMPP users\n"; help += "Backends:\n"; help += " backends_count - number of active backends\n"; help += " crashed_backends - returns IDs of crashed backends\n"; diff --git a/src/config.cpp b/src/config.cpp index cadf06589cf787a78904285291a6b403bc34a449..fefd782f0ee30fb07864000581853f9e94be0511 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -29,10 +29,16 @@ #endif #endif +#include "iostream" +#include "boost/version.hpp" + +#define BOOST_MAJOR_VERSION BOOST_VERSION / 100000 +#define BOOST_MINOR_VERSION BOOST_VERSION / 100 % 1000 + using namespace boost::program_options; namespace Transport { -int getRandomPort(const std::string &s) { +static int getRandomPort(const std::string &s) { unsigned long r = 0; BOOST_FOREACH(char c, s) { r += (int) c; @@ -72,14 +78,14 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.protocol", value()->default_value(""), "Protocol") ("service.pidfile", value()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file") ("service.working_dir", value()->default_value("/var/lib/spectrum2/$jid"), "Working dir") - ("service.allowed_servers", value()->default_value(""), "Only users from these servers can connect") + ("service.allowed_servers", value >()->multitoken(), "Only users from these servers can connect") ("service.server_mode", value()->default_value(false), "True if Spectrum should behave as server") ("service.users_per_backend", value()->default_value(100), "Number of users per one legacy network backend") ("service.backend_host", value()->default_value("localhost"), "Host to bind backend server to") ("service.backend_port", value()->default_value("0"), "Port to bind backend server to") ("service.cert", value()->default_value(""), "PKCS#12 Certificate.") ("service.cert_password", value()->default_value(""), "PKCS#12 Certificate password.") - ("service.admin_jid", value()->default_value(""), "Administrator jid.") + ("service.admin_jid", value >()->multitoken(), "Administrator jid.") ("service.admin_password", value()->default_value(""), "Administrator password.") ("service.reuse_old_backends", value()->default_value(true), "True if Spectrum should use old backends which were full in the past.") ("service.idle_reconnect_time", value()->default_value(0), "Time in seconds after which idle users are reconnected to let their backend die.") @@ -101,6 +107,8 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("registration.local_username_label", value()->default_value("Local username:"), "Label for local usernme field") ("registration.local_account_server", value()->default_value("localhost"), "The server on which the local accounts will be checked for validity") ("registration.local_account_server_timeout", value()->default_value(10000), "Timeout when checking local user on local_account_server (msecs)") + ("gateway_responder.prompt", value()->default_value("Contact ID"), "Value of field") + ("gateway_responder.label", value()->default_value("Enter legacy network contact ID."), "Label for add contact ID field") ("database.type", value()->default_value("none"), "Database type.") ("database.database", value()->default_value("/var/lib/spectrum2/$jid/database.sql"), "Database used to store data") ("database.server", value()->default_value("localhost"), "Database server.") @@ -195,8 +203,17 @@ bool Config::load(std::istream &ifs) { } bool Config::load(const std::string &configfile, const std::string &jid) { - options_description opts("Transport options"); - return load(configfile, opts, jid); + try { + options_description opts("Transport options"); + return load(configfile, opts, jid); + } catch ( const boost::program_options::multiple_occurrences& e ) { +#if (BOOST_MAJOR_VERSION >= 1 && BOOST_MINOR_VERSION >= 42) + std::cerr << configfile << " parsing error: " << e.what() << " from option: " << e.get_option_name() << std::endl; +#else + std::cerr << configfile << " parsing error: " << e.what() << std::endl; +#endif + return false; + } } bool Config::reload() { diff --git a/src/discoinforesponder.cpp b/src/discoinforesponder.cpp index 626953ad55ed188aeb652c49ce47d55964757cee..6d701088ede48dba537e5ea61322247938a8876e 100644 --- a/src/discoinforesponder.cpp +++ b/src/discoinforesponder.cpp @@ -88,11 +88,15 @@ bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::J // presence for transport if (to.getNode().empty()) { - sendResponse(from, id, boost::shared_ptr(new DiscoInfo(m_transportInfo))); + boost::shared_ptr res(new DiscoInfo(m_transportInfo)); + res->setNode(info->getNode()); + sendResponse(from, id, res); } // presence for buddy else { - sendResponse(from, to, id, boost::shared_ptr(new DiscoInfo(m_buddyInfo))); + boost::shared_ptr res(new DiscoInfo(m_buddyInfo)); + res->setNode(info->getNode()); + sendResponse(from, to, id, res); } return true; } diff --git a/src/gatewayresponder.cpp b/src/gatewayresponder.cpp index 2f7c0c352aabb335d31336f7c069677807f3e7c4..c7cbee99bb5eb7083a61e34826caf7a2ea06ae06 100644 --- a/src/gatewayresponder.cpp +++ b/src/gatewayresponder.cpp @@ -45,7 +45,9 @@ GatewayResponder::~GatewayResponder() { } bool GatewayResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { - sendResponse(from, id, boost::shared_ptr(new GatewayPayload(Swift::JID(), "Enter legacy network contact ID.", "Contact ID"))); + std::string prompt = CONFIG_STRING(m_userManager->getComponent()->getConfig(), "gateway_responder.prompt"); + std::string label = CONFIG_STRING(m_userManager->getComponent()->getConfig(), "gateway_responder.label"); + sendResponse(from, id, boost::shared_ptr(new GatewayPayload(Swift::JID(), label, prompt))); return true; } diff --git a/src/localbuddy.cpp b/src/localbuddy.cpp index 55f7e27cbe8f7c98090620d25b9357892ea21586..6d8d75305c9e92d3f10a4881d05a8d9453dd7c61 100644 --- a/src/localbuddy.cpp +++ b/src/localbuddy.cpp @@ -48,4 +48,24 @@ void LocalBuddy::setAlias(const std::string &alias) { } } +void LocalBuddy::setGroups(const std::vector &groups) { + bool changed = m_groups.size() != groups.size(); + if (!changed) { + for (int i = 0; i != m_groups.size(); i++) { + if (m_groups[i] != groups[i]) { + changed = true; + break; + } + } + } + + m_groups = groups; + if (changed) { + if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) { + getRosterManager()->sendBuddyRosterPush(this); + } + getRosterManager()->storeBuddy(this); + } +} + } diff --git a/src/logging.cpp b/src/logging.cpp index 3d56878f8161f23845ebb1e40c8e8de4dc6798e1..bd78eec82db11e862f6fe54d7d71ba40cb5a711a 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -139,11 +139,19 @@ void initMainLogging(Config *config) { initLogging(config, "logging.config"); } +void shutdownLogging() { + log4cxx::LogManager::shutdown(); +} + #else /* WITH_LOG4CXX */ void initBackendLogging(Config */*config*/) { } void initMainLogging(Config */*config*/) { +} + +void shutdownLogging() { + } #endif /* WITH_LOG4CXX */ diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 81a453dedbcd1a4e2ec18e932a83651e15f42790..cdb13dbc6f73cd0d43c78a7a662ed73c069886e8 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -232,7 +232,10 @@ void RosterManager::handleRemoteRosterResponse(boost::shared_ptrgetFactory()->createBuddy(this, buddyInfo); setBuddy(buddy); @@ -291,6 +295,10 @@ void RosterManager::sendRIE() { void RosterManager::handleSubscription(Swift::Presence::ref presence) { std::string legacyName = Buddy::JIDToLegacyName(presence->getTo()); + if (legacyName.empty()) { + return; + } + // For server mode the subscription changes are handler in rosterresponder.cpp // using roster pushes. if (m_component->inServerMode()) { diff --git a/src/storagebackend.cpp b/src/storagebackend.cpp index 17657a48e3196c9fe3042533ba6680744d3a9f49..2247dee9a1b5b62c8507e7920a6e22070995b533 100644 --- a/src/storagebackend.cpp +++ b/src/storagebackend.cpp @@ -10,7 +10,8 @@ namespace Transport { StorageBackend *StorageBackend::createBackend(Config *config, std::string &error) { StorageBackend *storageBackend = NULL; #ifdef WITH_SQLITE - if (CONFIG_STRING(config, "database.type") == "sqlite3") { + if (CONFIG_STRING(config, "database.type") == "sqlite3" || + (CONFIG_STRING(config, "database.type") == "none" && !CONFIG_BOOL(config, "service.server_mode"))) { storageBackend = new SQLite3Backend(config); } #else @@ -43,6 +44,7 @@ StorageBackend *StorageBackend::createBackend(Config *config, std::string &error && CONFIG_STRING(config, "database.type") != "pqxx" && CONFIG_STRING(config, "database.type") != "none") { error = "Unknown storage backend " + CONFIG_STRING(config, "database.type"); } + return storageBackend; } diff --git a/src/transport.cpp b/src/transport.cpp index 8c2633c5ac0539268e43fe6e8202cf40f42a0148..363e94c261141ff0bc3cad5a0393f717d0574643 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -216,6 +216,11 @@ void Component::start() { else if (m_server) { LOG4CXX_INFO(logger, "Starting component in server mode on port " << CONFIG_INT(m_config, "service.port")); m_server->start(); + + //Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer + //Ideally, onStopped must be defined in ConnectionServer + boost::dynamic_pointer_cast(m_server->getConnectionServer())->onStopped.connect(boost::bind(&Component::handleServerStopped, this, _1)); + // We're connected right here, because we're in server mode... handleConnected(); } @@ -239,6 +244,17 @@ void Component::handleConnected() { m_reconnectCount = 0; } +void Component::handleServerStopped(boost::optional e) { + if(e != NULL ) { + if(*e == Swift::BoostConnectionServer::Conflict) + LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server.."); + if(*e == Swift::BoostConnectionServer::UnknownError) + LOG4CXX_INFO(logger, "Unknown error occured! Stopping server.."); + exit(1); + } +} + + void Component::handleConnectionError(const ComponentError &error) { onConnectionError(error); // if (m_reconnectCount == 2) diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 671509f45614716c0bcde841534a3c16e56a4497..ee46277bd4f56a2f97623b94803a4f7f86f2d372 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -150,7 +150,10 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { // Create user class if it's not there if (!user) { // Admin user is not legacy network user, so do not create User class instance for him - if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) { + if (m_component->inServerMode()) { + std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid"); + if (std::find(x.begin(), x.end(), presence->getFrom().toBare().toString()) != x.end()) { + // Send admin contact to the user. Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); Swift::RosterItemPayload item; @@ -167,6 +170,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { response->setFrom(m_component->getJID()); m_component->getStanzaChannel()->sendPresence(response); return; + } } // No user and unavailable presence -> answer with unavailable diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 0e23217fba8be7f4bfa844af640850b462f204ce..2be05fb24cb315fae538fb8e02882e4a22616c51 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -168,7 +168,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID std::string barejid = from.toBare().toString(); if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { - std::list const &x = CONFIG_LIST(m_config,"service.allowed_servers"); + std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); @@ -275,7 +275,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID std::string barejid = from.toBare().toString(); if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { - std::list const &x = CONFIG_LIST(m_config,"service.allowed_servers"); + std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); diff --git a/src/userregistry.cpp b/src/userregistry.cpp index 81f6806ce1867feb5722186a9a92a4e014242e1e..8d8a3975bd812c0ed7d6aa8fba6b081ad43609cc 100644 --- a/src/userregistry.cpp +++ b/src/userregistry.cpp @@ -38,7 +38,8 @@ UserRegistry::UserRegistry(Config *cfg, Swift::NetworkFactories *factories) { UserRegistry::~UserRegistry() { m_removeTimer->stop(); } void UserRegistry::isValidUserPassword(const Swift::JID& user, Swift::ServerFromClientSession *session, const Swift::SafeByteArray& password) { - if (!CONFIG_STRING(config, "service.admin_jid").empty() && user.toBare().toString() == CONFIG_STRING(config, "service.admin_jid")) { + std::vector const &x = CONFIG_VECTOR(config,"service.admin_jid"); + if (std::find(x.begin(), x.end(), user.toBare().toString()) != x.end()) { if (Swift::safeByteArrayToString(password) == CONFIG_STRING(config, "service.admin_password")) { session->handlePasswordValid(); } @@ -47,7 +48,6 @@ void UserRegistry::isValidUserPassword(const Swift::JID& user, Swift::ServerFrom } return; } - std::string key = user.toBare().toString(); // Users try to connect twice diff --git a/src/vcardresponder.cpp b/src/vcardresponder.cpp index 83ff2acc275ec306bb0ac3ea4371bdfa5eaa6849..a8c7a6f49783ef617073414779fae002d548192f 100644 --- a/src/vcardresponder.cpp +++ b/src/vcardresponder.cpp @@ -101,7 +101,7 @@ bool VCardResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& LOG4CXX_INFO(logger, from.toBare().toString() << ": Requested VCard of " << name); m_queries[m_id].from = from; - m_queries[m_id].to = to_; + m_queries[m_id].to = to; m_queries[m_id].id = id; m_queries[m_id].received = time(NULL); onVCardRequired(user, name, m_id++);