Changeset - 51533ef87b89
[Not reviewed]
Merge
! ! !
Daniel Henninger - 13 years ago 2012-11-30 16:47:18
daniel@vorpalcloud.org
Merge remote branch 'upstream/master'
79 files changed with 2033 insertions and 1012 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -12,12 +12,29 @@ message(STATUS "|- boost   : -DBOOST_INCLUDEDIR,     -DBOOST_LIBRARYDIR")
 
message(STATUS "|- protobuf: -DPROTOBUF_INCLUDE_DIR, -DPROTOBUF_LIBRARY")
 
message(STATUS "           : -DPROTOBUF_PROTOC_EXECUTABLE")
 
message(STATUS "|- log4cxx : -DLOG4CXX_INCLUDE_DIR,  -DLOG4CXX_LIBRARY")
 
message(STATUS "|- purple  : -DPURPLE_INCLUDE_DIR,   -DPURPLE_LIBRARY")
 
message(STATUS "           : -DPURPLE_NOT_RUNTIME - enables compilation with libpurple.lib")
 

	
 
option(ENABLE_SQLITE3 "Build with SQLite3 support" ON)
 
option(ENABLE_MYSQL "Build with MySQL support" ON)
 
option(ENABLE_PQXX "Build with Postgres supoort" ON)
 

	
 
option(ENABLE_FROTZ "Build Frotz plugin" ON)
 
option(ENABLE_IRC "Build IRC plugin" ON)
 
option(ENABLE_PURPLE "Build Libpurple plugin" ON)
 
option(ENABLE_SMSTOOLS3 "Build SMSTools3 plugin" ON)
 
option(ENABLE_SKYPE "Build Skype plugin" ON)
 
option(ENABLE_SWIFTEN "Build Swiften plugin" ON)
 
option(ENABLE_TWITTER "Build Twitter plugin" ON)
 
option(ENABLE_YAHOO2 "Build Libyahoo2 plugin" ON)
 

	
 
option(ENABLE_DOCS "Build Docs" ON)
 
option(ENABLE_LOG "Build with logging using Log4cxx" ON)
 
option(ENABLE_TESTS "Build Tests using CppUnit" OFF)
 

	
 
MACRO(LIST_CONTAINS var value)
 
	SET(${var})
 
	FOREACH (value2 ${ARGN})
 
		IF (${value} STREQUAL ${value2})
 
		SET(${var} TRUE)
 
		ENDIF (${value} STREQUAL ${value2})
 
@@ -27,75 +44,120 @@ ENDMACRO(LIST_CONTAINS)
 
if(NOT LIB_INSTALL_DIR)
 
	set(LIB_INSTALL_DIR "lib")
 
endif()
 

	
 
set(CMAKE_MODULE_PATH "cmake_modules")
 

	
 
# FIND CPPUNIT
 
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(cppunit)
 
###### Prerequisites ######
 

	
 
if(NOT CPPUNIT_FOUND AND CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
 
	set(CCPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
 
	set(CPPUNIT_FOUND 1)
 
	message(STATUS "Using cppunit: ${CPPUNIT_INCLUDE_DIR} ${CPPUNIT_LIBRARIES}")
 
else()
 
# FIND BOOST
 
set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
if (WIN32)
 
	set(Boost_USE_STATIC_LIBS      ON)
 
	set(Boost_USE_MULTITHREADED      ON)
 
	set(Boost_USE_STATIC_RUNTIME    OFF)
 
	find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
else(WIN32)
 
	LIST_CONTAINS(contains -lboost_program_options ${SWIFTEN_LIBRARY})
 
	if(contains)
 
		message(STATUS "Using non-multithreaded boost")
 
		set(Boost_USE_MULTITHREADED 0)
 
	endif(contains)
 
	set(Boost_FIND_QUIETLY ON)
 
	find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals)
 
	if (NOT Boost_FOUND)
 
		set(Boost_FIND_QUIETLY OFF)
 
		find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
	endif()
 
endif(WIN32)
 

	
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

	
 
# FIND POPT
 
if (NOT WIN32)
 
	set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(popt REQUIRED)
 
endif()
 

	
 
###### Database ######
 

	
 
# FIND SQLITE3
 
if (NOT CMAKE_COMPILER_IS_GNUCXX)
 
ADD_SUBDIRECTORY(msvc-deps)
 
else()
 
if (WIN32)
 
ADD_SUBDIRECTORY(msvc-deps/sqlite3)
 
else()
 
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(sqlite3)
 
endif()
 
if (ENABLE_SQLITE3)
 
	if (NOT CMAKE_COMPILER_IS_GNUCXX)
 
		ADD_SUBDIRECTORY(msvc-deps)
 
	else()
 
		if (WIN32)
 
			ADD_SUBDIRECTORY(msvc-deps/sqlite3)
 
		else()
 
			set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
			find_package(sqlite3)
 
		endif()
 
	endif()
 
endif()
 

	
 
# FIND MYSQL
 
set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(mysql)
 
if(ENABLE_MYSQL)
 
	set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(mysql)
 
endif()
 

	
 
# FIND LIBPURPLE
 
set(purple_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(purple)
 
# FIND PQXX
 
if(ENABLE_PQXX)
 
	set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(pqxx)
 
endif()
 

	
 
if (WIN32)
 
	if (PURPLE_NOT_RUNTIME)
 
###### Plugins ######
 

	
 
# FIND LIBPURPLE
 
if(ENABLE_PURPLE)
 
	set(purple_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(purple)
 

	
 
	if (WIN32)
 
		if (PURPLE_NOT_RUNTIME)
 
			add_definitions(-DPURPLE_RUNTIME=0)
 
		else(PURPLE_NOT_RUNTIME)
 
			add_definitions(-DPURPLE_RUNTIME=1)
 
		endif(PURPLE_NOT_RUNTIME)
 
	else()
 
		add_definitions(-DPURPLE_RUNTIME=0)
 
	else(PURPLE_NOT_RUNTIME)
 
		add_definitions(-DPURPLE_RUNTIME=1)
 
	endif(PURPLE_NOT_RUNTIME)
 
else()
 
	add_definitions(-DPURPLE_RUNTIME=0)
 
	endif()
 

	
 
	# FIND LIBEVENT
 
	set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(event)
 
endif()
 

	
 
# FIND GLIB
 
# if (GLIB2_INCLUDE_DIR AND GLIB2_LIBRARIES)
 
# 	set(GLIB2_FOUND TRUE)
 
# else()
 
	set(glib_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(glib)
 
# endif()
 
if(ENABLE_SKYPE OR ENABLE_PURPLE)
 
#	if (GLIB2_INCLUDE_DIR AND GLIB2_LIBRARIES)
 
#		set(GLIB2_FOUND TRUE)
 
#	else()
 
		set(glib_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
		find_package(glib)
 
#	endif()
 
endif()
 

	
 
# FIND LIBXML2
 
# set(libxml2_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
# find_package(libxml2)
 

	
 
# FIND POPT
 
if (NOT WIN32)
 
	set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(popt)
 
endif()
 
# FIND PROTOBUF
 
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Protobuf REQUIRED)
 

	
 
# FIND LIBEVENT
 
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(event)
 
if (NOT PROTOBUF_FOUND AND PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY)
 
	set(PROTOBUF_FOUND 1)
 
	set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
 
	if (PROTOBUF_PROTOC_EXECUTABLE)
 
	else()
 
		set(PROTOBUF_PROTOC_EXECUTABLE protoc)
 
	endif()
 
	message(STATUS "Using protobuf: ${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_LIBRARY}")
 
endif()
 

	
 
# FIND SWIFTEN
 

	
 
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Swiften)
 

	
 
@@ -129,84 +191,64 @@ endif()
 

	
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(openssl)
 
endif()
 

	
 
# FIND BOOST
 
set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
if (WIN32)
 
	set(Boost_USE_STATIC_LIBS      ON)
 
	set(Boost_USE_MULTITHREADED      ON)
 
	set(Boost_USE_STATIC_RUNTIME    OFF)
 
	find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
else(WIN32)
 
	LIST_CONTAINS(contains -lboost_program_options ${SWIFTEN_LIBRARY})
 
	if(contains)
 
		message(STATUS "Using non-multithreaded boost")
 
		set(Boost_USE_MULTITHREADED 0)
 
	endif(contains)
 
	set(Boost_FIND_QUIETLY ON)
 
	find_package(Boost COMPONENTS program_options date_time system filesystem regex thread-mt signals)
 
	if (NOT Boost_FOUND)
 
		set(Boost_FIND_QUIETLY OFF)
 
		find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
	endif()
 
endif(WIN32)
 
if(ENABLE_IRC)
 
	set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(Communi)
 

	
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

	
 
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Protobuf)
 

	
 
# FIND PROTOBUF
 
if (NOT PROTOBUF_FOUND AND PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY)
 
	set(PROTOBUF_FOUND 1)
 
	set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
 
	if (PROTOBUF_PROTOC_EXECUTABLE)
 
	else()
 
		set(PROTOBUF_PROTOC_EXECUTABLE protoc)
 
	endif()
 
	message(STATUS "Using protobuf: ${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_LIBRARY}")
 
endif()
 

	
 

	
 
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Communi)
 

	
 
if(LOG4CXX_INCLUDE_DIR AND LOG4CXX_LIBRARY)
 
	set(LOG4CXX_LIBRARIES ${LOG4CXX_LIBRARY})
 
	set(LOG4CXX_FOUND 1)
 
	message(STATUS "Using log4cxx: ${CPPUNIT_INCLUDE_DIR} ${LOG4CXX_INCLUDE_DIR}")
 
else()
 
	set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(log4cxx)
 
	INCLUDE(FindQt4)
 
	FIND_PACKAGE(Qt4 COMPONENTS QtCore QtNetwork)
 
	# ADD_DEFINITIONS(${SWIFTEN_CFLAGS})
 
	ADD_DEFINITIONS(-DSUPPORT_LEGACY_CAPS)
 
	# ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2)
 
endif()
 

	
 
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(event)
 

	
 
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(pqxx)
 

	
 
if (NOT WIN32)
 
if (NOT WIN32 AND ENABLE_SKYPE)
 
set(dbus_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(dbus)
 
endif()
 

	
 
set(yahoo2_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(yahoo2)
 
if(ENABLE_YAHOO2)
 
	set(yahoo2_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(yahoo2)
 
endif()
 

	
 
find_package(Doxygen)
 
####### Miscallanous ######
 

	
 
INCLUDE(FindQt4)
 
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtNetwork)
 
if(ENABLE_DOCS)
 
	find_package(Doxygen)
 
endif()
 

	
 
# ADD_DEFINITIONS(${SWIFTEN_CFLAGS})
 
ADD_DEFINITIONS(-DSUPPORT_LEGACY_CAPS)
 
# ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2)
 
if(ENABLE_LOG)
 
	if(LOG4CXX_INCLUDE_DIR AND LOG4CXX_LIBRARY)
 
		set(LOG4CXX_LIBRARIES ${LOG4CXX_LIBRARY})
 
		set(LOG4CXX_FOUND 1)
 
		message(STATUS "Using log4cxx: ${CPPUNIT_INCLUDE_DIR} ${LOG4CXX_INCLUDE_DIR}")
 
	else()
 
		set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
		find_package(log4cxx)
 
	endif()
 
endif()
 

	
 
# FIND CPPUNIT
 
if(ENABLE_TESTS)
 
	set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(cppunit)
 

	
 
	if(NOT CPPUNIT_FOUND AND CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
 
		set(CCPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
 
		set(CPPUNIT_FOUND 1)
 
		message(STATUS "Using cppunit: ${CPPUNIT_INCLUDE_DIR} ${CPPUNIT_LIBRARIES}")
 
	endif()
 
endif()
 

	
 
message("  Supported features")
 
message("-----------------------")
 

	
 
if (SPECTRUM_VERSION)
 
	ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
 
@@ -231,98 +273,143 @@ message("Version           : " ${SPECTRUM_VERSION})
 

	
 
if (SQLITE3_FOUND)
 
	ADD_DEFINITIONS(-DWITH_SQLITE)
 
	include_directories(${SQLITE3_INCLUDE_DIR})
 
	message("SQLite3           : yes")
 
else (SQLITE3_FOUND)
 
if (WIN32)
 
	ADD_DEFINITIONS(-DWITH_SQLITE)
 
	include_directories(msvc-deps/sqlite3)
 
	message("SQLite3           : bundled")
 
else()
 
	set(SQLITE3_LIBRARIES "")
 
	message("SQLite3           : no")
 
endif()
 
	if (WIN32)
 
		ADD_DEFINITIONS(-DWITH_SQLITE)
 
		include_directories(msvc-deps/sqlite3)
 
		message("SQLite3           : bundled")
 
	else()
 
		set(SQLITE3_LIBRARIES "")
 
		if(ENABLE_SQLITE3)
 
			message("SQLite3           : no (install sqlite3)")
 
		else(ENABLE_SQLITE3)
 
			message("SQLite3           : no (user disabled)")
 
		endif()
 
	endif()
 
endif (SQLITE3_FOUND)
 

	
 
if (MYSQL_FOUND)
 
	ADD_DEFINITIONS(-DWITH_MYSQL)
 
	include_directories(${MYSQL_INCLUDE_DIR})
 
	message("MySQL             : yes")
 
else (MYSQL_FOUND)
 
	set(MYSQL_LIBRARIES "")
 
	message("MySQL             : no (install mysql-devel)")
 
	if(ENABLE_MYSQL)
 
		message("MySQL             : no (install mysql-devel)")
 
	else(ENABLE_MYSQL)
 
		message("MySQL             : no (user disabled)")
 
	endif()
 
endif (MYSQL_FOUND)
 

	
 
if (PQXX_FOUND)
 
	ADD_DEFINITIONS(-DWITH_PQXX)
 
	include_directories(${PQXX_INCLUDE_DIR})
 
	message("PostgreSQL        : yes")
 
else (PQXX_FOUND)
 
	set(PQXX_LIBRARY "")
 
	set(PQ_LIBRARY "")
 
	message("PostgreSQL        : no (install libpqxx-devel)")
 
	if(ENABLE_PQXX)
 
		message("PostgreSQL        : no (install libpqxx-devel)")
 
	else(ENABLE_PQXX)
 
		message("PostgreSQL        : no (user disabled)")
 
	endif()
 
endif (PQXX_FOUND)
 

	
 
if (PROTOBUF_FOUND)
 
	ADD_DEFINITIONS(-DWITH_PROTOBUF)
 
	include_directories(${PROTOBUF_INCLUDE_DIRS})
 
	message("Network plugins   : yes")
 

	
 
	if(PURPLE_FOUND)
 
		message("Libpurple plugin  : yes")
 
		include_directories(${PURPLE_INCLUDE_DIR})
 
		include_directories(${GLIB2_INCLUDE_DIR})
 
	else()
 
		message("Libpurple plugin  : no (install libpurple)")
 
		if(ENABLE_PURPLE)
 
			message("Libpurple plugin  : no (install libpurple)")
 
		else(ENABLE_PURPLE)
 
			message("Libpurple plugin  : no (user disabled)")
 
		endif()
 
	endif()
 

	
 
	if (HAVE_EVENT)
 
		ADD_DEFINITIONS(-DWITH_LIBEVENT)
 
		include_directories(${EVENT_INCLUDE_DIRS})
 
		message("  libev eventloop : yes")
 
	else()
 
		message("  libev eventloop : no (install libev-devel)")
 
		if(ENABLE_PURPLE)
 
			message("  libev eventloop : no (install libev-devel)")
 
		endif()
 
	endif()
 

	
 
	if(IRC_FOUND)
 
		ADD_DEFINITIONS(-DCOMMUNI_SHARED)
 
		message("IRC plugin        : yes")
 
		include_directories(${QT_QTNETWORK_INCLUDE_DIR})
 
		include_directories(${IRC_INCLUDE_DIR})
 
		include(${QT_USE_FILE})
 
	else()
 
		message("IRC plugin        : no (install libCommuni and libprotobuf-dev)")
 
		if(ENABLE_IRC)
 
			message("IRC plugin        : no (install libCommuni and libprotobuf-dev)")
 
		else(ENABLE_IRC)
 
			message("IRC plugin        : no (user disabled)")
 
		endif()
 
	endif()
 

	
 
if (NOT WIN32)
 
	message("Frotz plugin      : yes")
 
	message("SMSTools3 plugin  : yes")
 
	if(${LIBDBUSGLIB_FOUND})
 
		message("Skype plugin      : yes")
 
		include_directories(${LIBDBUSGLIB_INCLUDE_DIRS})
 
	if (NOT WIN32)
 
		if(ENABLE_FROTZ)
 
			message("Frotz plugin      : yes")
 
		else()
 
			message("Frotz plugin      : no (user disabled)")
 
		endif()
 
		if(ENABLE_SMSTOOLS3)
 
			message("SMSTools3 plugin  : yes")
 
		else()
 
			message("SMSTools3 plugin  : no (user disabled)")
 
		endif()
 
		if(${LIBDBUSGLIB_FOUND})
 
			message("Skype plugin      : yes")
 
			include_directories(${LIBDBUSGLIB_INCLUDE_DIRS})
 
		else()
 
			if(ENABLE_SKYPE)
 
				message("Skype plugin      : no (install dbus-glib-devel)")
 
			else(ENABLE_SKYPE)
 
				message("Skype plugin      : no (user disabled)")
 
			endif()
 
		endif()
 
		if(ENABLE_TWITTER)
 
			message("Twitter plugin    : yes")
 
		else(ENABLE_TWITTER)
 
			message("Twitter plugin    : no (user disabled)")
 
		endif()
 
	else()
 
		message("Skype plugin      : no (install dbus-glib-devel)")
 
		message("Frotz plugin      : no (does not run on Win32)")
 
		message("SMSTools3 plugin  : no (does not run on Win32)")
 
		message("Skype plugin      : no (does not run on Win32)")
 
		message("Twitter plugin    : no (does not run on Win32)")
 
	endif()
 
else()
 
	message("Frotz plugin      : no")
 
	message("SMSTools3 plugin  : no")
 
	message("Skype plugin      : no")
 
endif()
 

	
 
#	We have our own copy now...
 
# 	if(YAHOO2_FOUND)
 
 	if(YAHOO2_FOUND)
 
		message("Libyahoo2 plugin  : yes")
 
# 		include_directories(${YAHOO2_INCLUDE_DIR})
 
# 	else()
 
# 		message("Libyahoo2 plugin  : no (install libyahoo2-devel)")
 
# 	endif()
 

	
 
	message("Swiften plugin    : yes")
 
    message("Twitter plugin    : yes")
 
 		include_directories(${YAHOO2_INCLUDE_DIR})
 
	else()
 
		if(ENABLE_YAHOO2)
 
			message("Libyahoo2 plugin  : no (install libyahoo2-devel)")
 
		else(ENABLE_YAHOO2)
 
			message("Libyahoo2 plugin  : no (user disabled)")
 
		endif()
 
 	endif()
 

	
 
	if(ENABLE_SWIFTEN)
 
		message("Swiften plugin    : yes")
 
	else()
 
		message("Swiften plugin    : no (user disabled)")
 
	endif()
 
else()
 
	message("Network plugins   : no (install libprotobuf-dev)")
 
	message("Libpurple plugin  : no (install libpurple and libprotobuf-dev)")
 
	message("IRC plugin        : no (install libircclient-qt and libprotobuf-dev)")
 
	message("Frotz plugin      : no (install libprotobuf-dev)")
 
	message("SMSTools3 plugin  : no (install libprotobuf-dev)")
 
@@ -333,28 +420,32 @@ endif()
 
if (LOG4CXX_FOUND)
 
	message("Log4cxx           : yes")
 
	include_directories(${LOG4CXX_INCLUDE_DIR})
 
	ADD_DEFINITIONS(-DWITH_LOG4CXX)
 
else()
 
	set(LOG4CXX_LIBRARIES "")
 
	message("Log4cxx           : no (install log4cxx-devel)")
 
	if(ENABLE_LOG)
 
		message("Log4cxx           : no (install log4cxx-devel)")
 
	else(ENABLE_LOG)
 
		message("Log4cxx           : no (user disabled)")
 
	endif()
 
endif()
 

	
 
if (WIN32)
 
ADD_DEFINITIONS(-DLOG4CXX_STATIC)
 
ADD_DEFINITIONS(-D_WIN32_WINNT=0x501)
 
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
 
ADD_DEFINITIONS(-DBOOST_USE_WINDOWS_H)
 
ADD_DEFINITIONS(-DBOOST_THREAD_USE_LIB)
 
	ADD_DEFINITIONS(-DLOG4CXX_STATIC)
 
	ADD_DEFINITIONS(-D_WIN32_WINNT=0x501)
 
	ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
 
	ADD_DEFINITIONS(-DBOOST_USE_WINDOWS_H)
 
	ADD_DEFINITIONS(-DBOOST_THREAD_USE_LIB)
 
endif()
 

	
 
if(CMAKE_BUILD_TYPE MATCHES Debug)
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
	ADD_DEFINITIONS(-O0)
 
	ADD_DEFINITIONS(-ggdb)
 
endif()
 
	if (CMAKE_COMPILER_IS_GNUCXX)
 
		ADD_DEFINITIONS(-O0)
 
		ADD_DEFINITIONS(-ggdb)
 
	endif()
 
	ADD_DEFINITIONS(-DDEBUG)
 
	message("Debug             : yes")
 
else(CMAKE_BUILD_TYPE MATCHES Debug)
 
	message("Debug             : no (run \"cmake . -DCMAKE_BUILD_TYPE=Debug\")")
 
endif(CMAKE_BUILD_TYPE MATCHES Debug)
 

	
 
@@ -383,17 +474,34 @@ if (NOT WIN32)
 
endif()
 

	
 
if (CPPUNIT_FOUND)
 
	message("tests             : yes")
 
	include_directories(${CPPUNIT_INCLUDE_DIR})
 
else()
 
	message("tests             : no (install CPPUnit)")
 
	if(ENABLE_TESTS)
 
		message("tests             : no (install CPPUnit)")
 
	else(ENABLE_TESTS)
 
		message("tests             : no (user disabled)")
 
	endif()
 
endif()
 

	
 
if(DOXYGEN_FOUND)
 
	message("Docs              : yes")
 
	ADD_SUBDIRECTORY(docs)
 
else(DOXYGEN_FOUND)
 
	message("Docs              : no (install doxygen)")
 
	if(ENABLE_DOCS)
 
		message("Docs              : no (install doxygen)")
 
	else(ENABLE_DOCS)
 
		message("Docs              : no (user disabled)")
 
	endif()
 
endif(DOXYGEN_FOUND)
 

	
 
message("----------------------")
 

	
 
if(NOT SQLITE3_FOUND AND NOT MYSQL_FOUND AND NOT PQXX_FOUND)
 
	if(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
 
		message("Could not find any database - Please install at least one of sqlite3-devel, mysql-devel or pqxx-devel if you want to use transport mode.")
 
	else(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
 
		message("Please enable at least one of SQLITE3, MYSQL, PQXX databases to use transport mode.")
 
	endif()
 
endif()
 

	
backends/CMakeLists.txt
Show inline comments
 
@@ -4,24 +4,30 @@ if (PROTOBUF_FOUND)
 
	endif()
 

	
 
	if (IRC_FOUND)
 
		ADD_SUBDIRECTORY(libcommuni)
 
	endif()
 

	
 
	ADD_SUBDIRECTORY(swiften)
 
	if (ENABLE_SWIFTEN)
 
		ADD_SUBDIRECTORY(swiften)
 
	endif()
 

	
 
	ADD_SUBDIRECTORY(template)
 

	
 

	
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(smstools3)
 
	ADD_SUBDIRECTORY(frotz)
 
# 	if(YAHOO2_FOUND)
 
		ADD_SUBDIRECTORY(libyahoo2)
 
# 	endif()
 
	ADD_SUBDIRECTORY(twitter)
 
	if (${LIBDBUSGLIB_FOUND})
 
		ADD_SUBDIRECTORY(skype)
 
	if (NOT WIN32)
 
		if(ENABLE_SMSTOOLS3)
 
			ADD_SUBDIRECTORY(smstools3)
 
		endif()
 
		if(ENABLE_FROTZ)
 
			ADD_SUBDIRECTORY(frotz)
 
		endif()
 
 		if(YAHOO2_FOUND)
 
			ADD_SUBDIRECTORY(libyahoo2)
 
	 	endif()
 
		if(ENABLE_TWITTER)
 
			ADD_SUBDIRECTORY(twitter)
 
		endif()
 
		if (${LIBDBUSGLIB_FOUND})
 
			ADD_SUBDIRECTORY(skype)
 
		endif()
 
	endif()
 
endif()
 

	
 
endif()
backends/libcommuni/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
FILE(GLOB HEADERS *.h)
 
QT4_WRAP_CPP(SRC ${HEADERS})
 
QT4_WRAP_CPP(SRC ${HEADERS} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
 
ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC})
 
 
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport pthread)
 
if (NOT WIN32)
 
	target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport pthread)
 
else ()
 
	target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport)
 
endif()
 
 
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)
 
backends/libcommuni/ircnetworkplugin.cpp
Show inline comments
 
@@ -8,12 +8,13 @@ DEFINE_LOGGER(logger, "IRCNetworkPlugin");
 
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
 
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
 

	
 
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
 
	this->config = config;
 
	m_currentServer = 0;
 
	m_firstPing = true;
 
	m_socket = new QTcpSocket();
 
	m_socket->connectToHost(FROM_UTF8(host), port);
 
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
 

	
 
	std::string server = CONFIG_STRING_DEFAULTED(config, "service.irc_server", "");
 
	if (!server.empty()) {
 
@@ -45,12 +46,23 @@ void IRCNetworkPlugin::tryNextServer() {
 

	
 
void IRCNetworkPlugin::readData() {
 
	size_t availableBytes = m_socket->bytesAvailable();
 
	if (availableBytes == 0)
 
		return;
 

	
 
	if (m_firstPing) {
 
		m_firstPing = false;
 
		// Users can join the network without registering if we allow
 
		// one user to connect multiple IRC networks.
 
		if (m_servers.empty()) {
 
			NetworkPlugin::PluginConfig cfg;
 
			cfg.setNeedRegistration(false);
 
			sendConfig(cfg);
 
		}
 
	}
 

	
 
	std::string d = std::string(m_socket->readAll().data(), availableBytes);
 
	handleDataRead(d);
 
}
 

	
 
void IRCNetworkPlugin::sendData(const std::string &string) {
 
	m_socket->write(string.c_str(), string.size());
 
@@ -139,13 +151,19 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s
 
		return;
 
	}
 

	
 
	std::string target = getTargetName(legacyName);
 

	
 
	LOG4CXX_INFO(logger, user << ": Session name: " << session << ", message to " << target);
 
	m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message)));
 

	
 
	if (message.find("/me") == 0) {
 
		m_sessions[session]->sendCommand(IrcCommand::createCtcpAction(FROM_UTF8(target), FROM_UTF8(message.substr(4))));
 
	}
 
	else {
 
		m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message)));
 
	}
 

	
 
	if (target.find("#") == 0) {
 
		handleMessage(user, legacyName, message, TO_UTF8(m_sessions[session]->nickName()));
 
	}
 
}
 

	
backends/libcommuni/ircnetworkplugin.h
Show inline comments
 
@@ -43,7 +43,8 @@ class IRCNetworkPlugin : public QObject, public NetworkPlugin {
 
		Config *config;
 
		QTcpSocket *m_socket;
 
		std::map<std::string, MyIrcSession *> m_sessions;
 
		std::vector<std::string> m_servers;
 
		int m_currentServer;
 
		std::string m_identify;
 
		bool m_firstPing;
 
};
 
\ No newline at end of file
backends/libcommuni/session.cpp
Show inline comments
 
@@ -20,12 +20,14 @@
 
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
 

	
 
#include "transport/logging.h"
 

	
 
DEFINE_LOGGER(logger, "IRCSession");
 

	
 
static bool sentList;
 

	
 
MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent)
 
{
 
	this->np = np;
 
	this->user = user;
 
	this->suffix = suffix;
 
	m_connected = false;
 
@@ -37,14 +39,20 @@ MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const
 
}
 

	
 
void MyIrcSession::on_connected() {
 
	m_connected = true;
 
	if (suffix.empty()) {
 
		np->handleConnected(user);
 
// 		if (!sentList) {
 
// 			sendCommand(IrcCommand::createList("", ""));
 
// 			sentList = true;
 
// 		}
 
	}
 

	
 
	sendCommand(IrcCommand::createCapability("REQ", QStringList("away-notify")));
 

	
 
	for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
 
		sendCommand(IrcCommand::createJoin(FROM_UTF8(it->second->getChannel()), FROM_UTF8(it->second->getPassword())));
 
	}
 

	
 
	if (getIdentify().find(" ") != std::string::npos) {
 
		std::string to = getIdentify().substr(0, getIdentify().find(" "));
 
@@ -77,14 +85,14 @@ bool MyIrcSession::correctNickname(std::string &nickname) {
 

	
 
void MyIrcSession::on_joined(IrcMessage *message) {
 
	IrcJoinMessage *m = (IrcJoinMessage *) message;
 
	bool flags = 0;
 
	std::string nickname = TO_UTF8(m->sender().name());
 
	flags = correctNickname(nickname);
 
	np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()), (int) flags, pbnetwork::STATUS_ONLINE);
 
	LOG4CXX_INFO(logger, user << ": Joined " << TO_UTF8(m->parameters()[0]));
 
	np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix, (int) flags, pbnetwork::STATUS_ONLINE);
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " joined " << TO_UTF8(m->channel()) + suffix);
 
}
 

	
 

	
 
void MyIrcSession::on_parted(IrcMessage *message) {
 
	IrcPartMessage *m = (IrcPartMessage *) message;
 
	bool flags = 0;
 
@@ -155,40 +163,62 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) {
 
		if (request == "PING" || request == "TIME" || request == "VERSION") {
 
			LOG4CXX_INFO(logger, user << ": " << TO_UTF8(request) << " received and has been answered");
 
			return;
 
		}
 
	}
 

	
 
	QString msg = m->message();
 
	if (m->isAction()) {
 
		msg = QString("/me ") + msg;
 
	}
 

	
 
	std::string target = TO_UTF8(m->target());
 
	LOG4CXX_INFO(logger, user << ": Message from " << target);
 
	if (target.find("#") == 0) {
 
		bool flags = 0;
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		flags = correctNickname(nickname);
 
		np->handleMessage(user, target + suffix, TO_UTF8(m->message()), nickname);
 
		np->handleMessage(user, target + suffix, TO_UTF8(msg), nickname);
 
	}
 
	else {
 
		bool flags = 0;
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		flags = correctNickname(nickname);
 
		LOG4CXX_INFO(logger, nickname + suffix);
 
		np->handleMessage(user, nickname + suffix, TO_UTF8(m->message()));
 
		np->handleMessage(user, nickname + suffix, TO_UTF8(msg));
 
	}
 
}
 

	
 
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
 
	QString channel;
 
	QStringList members;
 
	std::string nick;
 

	
 
	IrcNumericMessage *m = (IrcNumericMessage *) message;
 
	switch (m->code()) {
 
		case 301:
 
			break;
 
		case 332:
 
			m_topicData = TO_UTF8(m->parameters().value(2));
 
			break;
 
		case 333:
 
			 np->handleSubject(user, TO_UTF8(m->parameters().value(1)) + suffix, m_topicData, TO_UTF8(m->parameters().value(2)));
 
			nick = TO_UTF8(m->parameters().value(2));
 
			if (nick.find("!") != std::string::npos) {
 
				nick = nick.substr(0, nick.find("!"));
 
			}
 
			if (nick.find("/") != std::string::npos) {
 
				nick = nick.substr(0, nick.find("/"));
 
			}
 
			np->handleSubject(user, TO_UTF8(m->parameters().value(1)) + suffix, m_topicData, nick);
 
			break;
 
		case 352:
 
			channel = m->parameters().value(1);
 
			nick = TO_UTF8(m->parameters().value(5));
 
			if (m->parameters().value(6).toUpper().startsWith("G")) {
 
				np->handleParticipantChanged(user, nick, TO_UTF8(channel) + suffix, m_modes[TO_UTF8(channel) + nick], pbnetwork::STATUS_AWAY);
 
			}
 
			break;
 
		case 353:
 
			channel = m->parameters().value(2);
 
			members = m->parameters().value(3).split(" ");
 

	
 
			LOG4CXX_INFO(logger, user << ": Received members for " << TO_UTF8(channel) << suffix);
 
@@ -196,16 +226,30 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
 
				bool flags = 0;
 
				std::string nickname = TO_UTF8(members.at(i));
 
				flags = correctNickname(nickname);
 
				m_modes[TO_UTF8(channel) + nickname] = flags;
 
				np->handleParticipantChanged(user, nickname, TO_UTF8(channel) + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
 
			}
 

	
 
			// ask /who to get away states
 
			sendCommand(IrcCommand::createWho(channel));
 
			break;
 
		case 432:
 
			np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
 
			break;
 
		case 321:
 
			m_rooms.clear();
 
			m_names.clear();
 
			break;
 
		case 322:
 
			m_rooms.push_back(TO_UTF8(m->parameters().value(1)));
 
			m_names.push_back(TO_UTF8(m->parameters().value(1)));
 
			break;
 
		case 323:
 
			np->handleRoomList("", m_rooms, m_names);
 
			break;
 
		default:
 
			break;
 
	}
 

	
 
	//qDebug() << "numeric message received:" << receiver() << origin << code << params;
 
}
backends/libcommuni/session.h
Show inline comments
 
@@ -38,12 +38,13 @@ public:
 
	};
 

	
 
	typedef std::map<std::string, boost::shared_ptr<AutoJoinChannel> > AutoJoinMap;
 

	
 
	MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
 
	std::map<std::string, bool> m_modes;
 
	std::map<std::string, bool> m_away;
 
	std::string suffix;
 
	int rooms;
 

	
 
	void addAutoJoinChannel(const std::string &channel, const std::string &password) {
 
		m_autoJoin[channel] = boost::make_shared<AutoJoinChannel>(channel, password);
 
	}
 
@@ -82,42 +83,11 @@ protected:
 
	IRCNetworkPlugin *np;
 
	std::string user;
 
	std::string m_identify;
 
	AutoJoinMap m_autoJoin;
 
	std::string m_topicData;
 
	bool m_connected;
 
	std::list<std::string> m_rooms;
 
	std::list<std::string> m_names;
 
};
 

	
 
//class MyIrcBuffer : public Irc::Buffer
 
//{
 
//    Q_OBJECT
 

	
 
//public:
 
//	MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent);
 
//	NetworkPlugin *np;
 
//	std::string user;
 
//	MyIrcSession *p;
 
//	std::string m_topicData;
 
//		std::string suffix;
 

	
 
//protected Q_SLOTS:
 
//    void on_receiverChanged(const QString& receiver);
 
//    void on_joined(const QString& origin);
 
//    void on_parted(const QString& origin, const QString& message);
 
//    void on_quit(const QString& origin, const QString& message);
 
//    void on_nickChanged(const QString& origin, const QString& nick);
 
//    void on_modeChanged(const QString& origin, const QString& mode, const QString& args);
 
//    void on_topicChanged(const QString& origin, const QString& topic);
 
//    void on_invited(const QString& origin, const QString& receiver, const QString& channel);
 
//    void on_kicked(const QString& origin, const QString& nick, const QString& message);
 
//    void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags);
 
//    void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags);
 
//    void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params);
 
//    void on_unknownMessageReceived(const QString& origin, const QStringList& params);
 

	
 
//	bool correctNickname(std::string &nickname);
 
//};
 

	
 
#endif // SESSION_H
backends/libpurple/main.cpp
Show inline comments
 
@@ -930,20 +930,27 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
 
	}
 

	
 
	if (xhtml_ == message_) {
 
		xhtml_ = "";
 
	}
 

	
 
	std::string timestamp;
 
	if (mtime && (unsigned long) time(NULL)-10 > (unsigned long) mtime/* && (unsigned long) time(NULL) - 31536000 < (unsigned long) mtime*/) {
 
		char buf[80];
 
		strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", gmtime(&mtime));
 
		timestamp = buf;
 
	}
 

	
 
// 	LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
 

	
 
	if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
		np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
 
		np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_, timestamp);
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name_wrapped(conv) << "' " << w);
 
		np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, w, xhtml_);
 
		np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, w, xhtml_, timestamp);
 
	}
 
}
 

	
 
static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {
 
	PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
 

	
backends/libpurple/utils.cpp
Show inline comments
 
@@ -33,20 +33,20 @@
 
#include "errno.h"
 
#include <string.h>
 

	
 
#ifndef WIN32 
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <netinet/if_ether.h>
 
#include <netinet/ip.h>
 
#include <netinet/ip6.h>
 
#include <netinet/udp.h>
 
#include <netinet/tcp.h>
 
#include <netinet/ether.h>
 
#include "sys/socket.h"
 
#include <sys/types.h>
 
#include <sys/socket.h>
 
#include <netinet/in.h>
 
#include <netdb.h>
 
#include <arpa/inet.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
#else 
 
#include <process.h>
 
#define getpid _getpid 
 
#define ssize_t SSIZE_T
 
@@ -134,36 +134,38 @@ void spectrum_sigchld_handler(int sig)
 
		perror(errmsg);
 
	}
 
}
 
#endif
 

	
 
int create_socket(const char *host, int portno) {
 
	struct sockaddr_in serv_addr;
 
	
 
	int main_socket = socket(AF_INET, SOCK_STREAM, 0);
 
	memset((char *) &serv_addr, 0, sizeof(serv_addr));
 
	serv_addr.sin_family = AF_INET;
 
	serv_addr.sin_port = htons(portno);
 

	
 
	hostent *hos;  // Resolve name
 
	struct sockaddr_in stSockAddr;
 
	int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 

	
 
	if (-1 == SocketFD) {
 
		return 0;
 
	}
 

	
 
	hostent *hos;
 
	if ((hos = gethostbyname(host)) == NULL) {
 
		// strerror() will not work for gethostbyname() and hstrerror() 
 
		// is supposedly obsolete
 
		exit(1);
 
		return 0;
 
	}
 
	serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
 

	
 
	if (connect(main_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 
		close(main_socket);
 
		main_socket = 0;
 
	memset(&stSockAddr, 0, sizeof(stSockAddr));
 

	
 
	stSockAddr.sin_family = AF_INET;
 
	stSockAddr.sin_port = htons(portno);
 
	memcpy(&(stSockAddr.sin_addr.s_addr), hos->h_addr,  hos->h_length);
 

	
 
	if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) {
 
		close(SocketFD);
 
		return 0;
 
	}
 

	
 
// 	int flags = fcntl(main_socket, F_GETFL);
 
// 	flags |= O_NONBLOCK;
 
// 	fcntl(main_socket, F_SETFL, flags);
 
	return main_socket;
 
	return SocketFD;
 
}
 

	
 
#ifdef _WIN32
 
std::wstring utf8ToUtf16(const std::string& str)
 
{
 
	try
backends/skype/main.cpp
Show inline comments
 
@@ -16,13 +16,15 @@
 
#include "transport/networkplugin.h"
 
#include "transport/logger.h"
 
#include <boost/filesystem.hpp>
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
// #include "valgrind/memcheck.h"
 
#ifndef __FreeBSD__
 
#include "malloc.h"
 
#endif
 
#include <dbus-1.0/dbus/dbus-glib-lowlevel.h>
 

	
 

	
 
DEFINE_LOGGER(logger, "backend");
 

	
 
using namespace Transport;
backends/swiften/main.cpp
Show inline comments
 
@@ -11,14 +11,16 @@
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#endif
 

	
 
#ifndef __FreeBSD__
 
// malloc_trim
 
#include "malloc.h"
 
#endif
 

	
 
// Boost
 
#include <boost/algorithm/string.hpp>
 
using namespace boost::filesystem;
 
using namespace boost::program_options;
 
using namespace Transport;
 
@@ -58,20 +60,21 @@ class SwiftenPlugin : public NetworkPlugin {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleSwiftDisconnected(const std::string &user, const boost::optional<Swift::ClientError> &error) {
 
			std::string message = "";
 
			bool reconnect = false;
 
			if (error) {
 
				switch(error->getType()) {
 
					case Swift::ClientError::UnknownError: message = ("Unknown Error"); break;
 
					case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break;
 
					case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break;
 
					case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break;
 
					case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); break;
 
					case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); break;
 
					case Swift::ClientError::XMLError: message = ("Error parsing server data"); break;
 
					case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break;
 
					case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break;
 
					case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break;
 
					case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break;
 
					case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break;
 
					case Swift::ClientError::ServerVerificationFailedError: message = ("Server verification failed"); break;
 
					case Swift::ClientError::NoSupportedAuthMechanismsError: message = ("Authentication mechanisms not supported"); break;
 
					case Swift::ClientError::UnexpectedElementError: message = ("Unexpected response"); break;
 
					case Swift::ClientError::ResourceBindError: message = ("Error binding resource"); break;
 
@@ -92,25 +95,27 @@ class SwiftenPlugin : public NetworkPlugin {
 
					case Swift::ClientError::InvalidCertificateSignatureError: message = ("Invalid certificate signature"); break;
 
					case Swift::ClientError::InvalidCAError: message = ("Invalid Certificate Authority"); break;
 
					case Swift::ClientError::InvalidServerIdentityError: message = ("Certificate does not match the host identity"); break;
 
				}
 
			}
 
			LOG4CXX_INFO(logger, user << ": Disconnected " << message);
 
			handleDisconnected(user, 3, message);
 
			handleDisconnected(user, reconnect ? 0 : 3, message);
 

	
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
 
				client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
 
				client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
 
				m_users.erase(user);
 
			}
 

	
 
#ifndef WIN32
 
#ifndef __FreeBSD__
 
			// force returning of memory chunks allocated by libxml2 to kernel
 
			malloc_trim(0);
 
#endif
 
#endif
 
		}
 

	
 
		void handleSwiftConnected(const std::string &user) {
 
			LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
 
			handleConnected(user);
backends/twitter/TwitterPlugin.cpp
Show inline comments
 
@@ -319,13 +319,13 @@ void TwitterPlugin::handleVCardRequest(const std::string &user, const std::strin
 
void TwitterPlugin::pollForTweets()
 
{
 
	boost::mutex::scoped_lock lock(userlock);
 
	std::set<std::string>::iterator it = onlineUsers.begin();
 
	while(it != onlineUsers.end()) {
 
		std::string user = *it;
 
		tp->runAsThread(new TimelineRequest(userdb[user].sessions, user, "", userdb[user].mostRecentTweetID,
 
		tp->runAsThread(new TimelineRequest(userdb[user].sessions, user, "", getMostRecentTweetIDUnsafe(user),
 
											boost::bind(&TwitterPlugin::displayTweets, this, _1, _2, _3, _4)));
 
		it++;
 
	}
 
	tweet_timer->start();
 
}
 

	
 
@@ -514,22 +514,47 @@ void TwitterPlugin::pinExchangeComplete(const std::string user, const std::strin
 
}	
 

	
 
void TwitterPlugin::updateLastTweetID(const std::string user, const std::string ID)
 
{
 
	boost::mutex::scoped_lock lock(userlock);	
 
	userdb[user].mostRecentTweetID = ID;
 

	
 
	UserInfo info;
 
	if(storagebackend->getUser(user, info) == false) {
 
		LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!")
 
		return;
 
	}
 

	
 
	storagebackend->updateUserSetting((long)info.id, "twitter_last_tweet", ID);
 
}
 

	
 
std::string TwitterPlugin::getMostRecentTweetID(const std::string user)
 
{
 
	boost::mutex::scoped_lock lock(userlock);	
 
	std::string ID = "-1";
 
	if(onlineUsers.count(user)) ID = userdb[user].mostRecentTweetID;
 
std::string TwitterPlugin::getMostRecentTweetIDUnsafe(const std::string user)
 
{	
 
	std::string ID = "";
 
	if(onlineUsers.count(user)) {
 
		ID = userdb[user].mostRecentTweetID;
 
		if (ID.empty()) {
 
			int type;
 
			UserInfo info;
 
			if(storagebackend->getUser(user, info) == false) {
 
				LOG4CXX_ERROR(logger, "Didn't find entry for " << user << " in the database!")
 
			}
 
			else {
 
				storagebackend->getUserSetting(info.id, "twitter_last_tweet", type, ID);
 
			}
 
		}
 
	}
 
	return ID;
 
}
 

	
 
std::string TwitterPlugin::getMostRecentTweetID(const std::string user)
 
{	
 
	boost::mutex::scoped_lock lock(userlock);
 
	return getMostRecentTweetIDUnsafe(user);
 
}
 

	
 
void TwitterPlugin::updateLastDMID(const std::string user, const std::string ID)
 
{
 
	boost::mutex::scoped_lock lock(userlock);	
 
	userdb[user].mostRecentDirectMessageID = ID;
 
}
 

	
 
@@ -619,22 +644,23 @@ void TwitterPlugin::displayTweets(std::string &user, std::string &userRequested,
 
	if(errMsg.getMessage().length() == 0) {
 
		
 
		std::string timeline = "";
 
		std::map<std::string, int> lastTweet;
 
		std::map<std::string, int>::iterator it;
 

	
 
		for(int i=0 ; i<tweets.size() ; i++) {
 
		for(int i = tweets.size() - 1 ; i >= 0 ; i--) {
 
			if(userdb[user].twitterMode != CHATROOM) {
 
				timeline += " - " + tweets[i].getUserData().getScreenName() + ": " + tweets[i].getTweet() + " (MsgId: " + tweets[i].getID() + ")\n";
 
				std::string m = " - " + tweets[i].getUserData().getScreenName() + ": " + tweets[i].getTweet() + " (MsgId: " + tweets[i].getID() + ")\n";
 
				handleMessage(user, adminLegacyName, m, "", "", tweets[i].getCreationTime());
 

	
 
				std::string scrname = tweets[i].getUserData().getScreenName();
 
				if(lastTweet.count(scrname) == 0 || cmp(tweets[lastTweet[scrname]].getID(), tweets[i].getID()) <= 0) lastTweet[scrname] = i;
 

	
 
			} else {
 
				handleMessage(user, userdb[user].twitterMode == CHATROOM ? adminChatRoom : adminLegacyName,
 
									tweets[i].getTweet() + " (MsgId: " + tweets[i].getID() + ")", tweets[i].getUserData().getScreenName());
 
									tweets[i].getTweet() + " (MsgId: " + tweets[i].getID() + ")", tweets[i].getUserData().getScreenName(), "", tweets[i].getCreationTime());
 
			}
 
		}
 
		
 
		if(userdb[user].twitterMode == MULTIPLECONTACT) {
 
			//Set as status user's last tweet
 
			for(it=lastTweet.begin() ; it!=lastTweet.end() ; it++) {
backends/twitter/TwitterPlugin.h
Show inline comments
 
@@ -131,12 +131,14 @@ class TwitterPlugin : public NetworkPlugin {
 
		void RetweetResponse(std::string &user, Error &errMsg);
 
		
 
		void profileImageResponse(std::string &user, std::string &buddy, std::string &img, unsigned int reqID, Error &errMsg);
 
		/***********************************************************************************/
 

	
 
	private:
 
		std::string getMostRecentTweetIDUnsafe(const std::string user);
 

	
 
		enum status {NEW, WAITING_FOR_PIN, CONNECTED, DISCONNECTED};
 
		enum mode {SINGLECONTACT, MULTIPLECONTACT, CHATROOM};
 

	
 
		Config *config;
 
		std::string adminLegacyName;
 
		std::string adminChatRoom;
backends/twitter/TwitterResponseParser.cpp
Show inline comments
 
#include "TwitterResponseParser.h"
 
#include "transport/logging.h"
 
#include "boost/algorithm/string.hpp"
 
#include <cctype>
 

	
 
DEFINE_LOGGER(logger, "TwitterResponseParser")
 

	
 
static std::string tolowercase(std::string inp)
 
{
 
	std::string out = inp;
 
	for(int i=0 ; i<out.size() ; i++) out[i] = tolower(out[i]);
 
	return out;
 
}
 

	
 
static std::string unescape(std::string data) {
 
	using boost::algorithm::replace_all;
 
	replace_all(data, "&amp;",  "&");
 
	replace_all(data, "&quot;", "\"");
 
	replace_all(data, "&apos;", "\'");
 
	replace_all(data, "&lt;",   "<");
 
	replace_all(data, "&gt;",   ">");
 
	return data;
 
}
 

	
 
static std::string toIsoTime(std::string in) {
 
	time_t now = time(0);
 
	struct tm *mtime = gmtime(&now);
 
	strptime(in.c_str(), "%a %b %d %H:%M:%S %z %Y", mtime);
 
	char buf[80];
 
	strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", mtime);
 
	return buf;
 
}
 

	
 
EmbeddedStatus getEmbeddedStatus(const Swift::ParserElement::ref &element, const std::string xmlns)
 
{
 
	EmbeddedStatus status;
 
	if(element->getName() != TwitterReponseTypes::status) {
 
		LOG4CXX_ERROR(logger, "Not a status element!")
 
		return status;
 
	}
 

	
 
	status.setCreationTime( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) );
 
	status.setCreationTime( toIsoTime(std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) ) );
 

	
 
	status.setID( std::string( element->getChild(TwitterReponseTypes::id, xmlns)->getText() ) );
 
	status.setTweet( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) );
 
	status.setTweet( unescape (std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) ) );
 
	status.setTruncated( std::string( element->getChild(TwitterReponseTypes::truncated, xmlns)->getText() )=="true" );
 
	status.setReplyToStatusID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_status_id, xmlns)->getText() ) );
 
	status.setReplyToUserID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_user_id, xmlns)->getText() ) );
 
	status.setReplyToScreenName( std::string( element->getChild(TwitterReponseTypes::in_reply_to_screen_name, xmlns)->getText() ) );
 
	status.setRetweetCount( atoi( element->getChild(TwitterReponseTypes::retweet_count, xmlns)->getText().c_str() ) );
 
	status.setFavorited( std::string( element->getChild(TwitterReponseTypes::favorited, xmlns)->getText() )=="true" );
 
@@ -57,15 +78,15 @@ Status getStatus(const Swift::ParserElement::ref &element, const std::string xml
 
	Status status;
 
	if(element->getName() != "status") {
 
		LOG4CXX_ERROR(logger, "Not a status element!")
 
		return status;
 
	}
 

	
 
	status.setCreationTime( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) );
 
	status.setCreationTime( toIsoTime ( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) ) );
 
	status.setID( std::string( element->getChild(TwitterReponseTypes::id, xmlns)->getText() ) );
 
	status.setTweet( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) );
 
	status.setTweet( unescape ( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) ) );
 
	status.setTruncated( std::string( element->getChild(TwitterReponseTypes::truncated, xmlns)->getText() )=="true" );
 
	status.setReplyToStatusID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_status_id, xmlns)->getText() ) );
 
	status.setReplyToUserID( std::string( element->getChild(TwitterReponseTypes::in_reply_to_user_id, xmlns)->getText() ) );
 
	status.setReplyToScreenName( std::string( element->getChild(TwitterReponseTypes::in_reply_to_screen_name, xmlns)->getText() ) );
 
	status.setUserData( getUser(element->getChild(TwitterReponseTypes::user, xmlns), xmlns) );
 
	status.setRetweetCount( atoi( element->getChild(TwitterReponseTypes::retweet_count, xmlns)->getText().c_str() ) );
 
@@ -79,15 +100,15 @@ DirectMessage getDirectMessage(const Swift::ParserElement::ref &element, const s
 
	DirectMessage DM;
 
	if(element->getName() != TwitterReponseTypes::direct_message) {
 
		LOG4CXX_ERROR(logger, "Not a direct_message element!")
 
		return DM;
 
	}
 

	
 
	DM.setCreationTime( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) );
 
	DM.setCreationTime( toIsoTime ( std::string( element->getChild(TwitterReponseTypes::created_at, xmlns)->getText() ) ) );
 
	DM.setID( std::string( element->getChild(TwitterReponseTypes::id, xmlns)->getText() ) );
 
	DM.setMessage( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) );
 
	DM.setMessage( unescape ( std::string( element->getChild(TwitterReponseTypes::text, xmlns)->getText() ) ) );
 
	DM.setSenderID( std::string( element->getChild(TwitterReponseTypes::sender_id, xmlns)->getText() ) );
 
	DM.setRecipientID( std::string( element->getChild(TwitterReponseTypes::recipient_id, xmlns)->getText() ) );
 
	DM.setSenderScreenName( std::string( element->getChild(TwitterReponseTypes::sender_screen_name, xmlns)->getText() ) );
 
	DM.setRecipientScreenName( std::string( element->getChild(TwitterReponseTypes::recipient_screen_name, xmlns)->getText() ) );
 
	DM.setSenderData( getUser(element->getChild(TwitterReponseTypes::sender, xmlns), xmlns) );
 
	DM.setRecipientData( getUser(element->getChild(TwitterReponseTypes::recipient, xmlns), xmlns) );
backends/twitter/main.cpp
Show inline comments
 
@@ -24,75 +24,35 @@ int main (int argc, char* argv[]) {
 

	
 
	if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
		std::cout << "SIGCHLD handler can't be set\n";
 
		return -1;
 
	}
 

	
 
	std::string configFile;
 
	boost::program_options::variables_map vm;
 
	boost::program_options::options_description desc("Usage: spectrum <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("help", "help")
 
		("host,h", boost::program_options::value<std::string>(&host)->default_value(""), "Host to connect to")
 
		("port,p", boost::program_options::value<int>(&port)->default_value(10000), "Port to connect to")
 
		("config", boost::program_options::value<std::string>(&configFile)->default_value(""), "Config file")
 
		;
 

	
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
 
			options(desc).positional(p).allow_unregistered().run(), vm);
 
		boost::program_options::notify(vm);
 
			
 
		if(vm.count("help"))
 
		{
 
			std::cout << desc << "\n";
 
			return 1;
 
		}
 

	
 
		if(vm.count("config") == 0) {
 
			std::cout << desc << "\n";
 
			return 1;
 
		}
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		return 1;
 
	}
 
	catch (...)
 
	{
 
		std::cout << desc << "\n";
 
	std::string error;
 
	Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
 
	if (cfg == NULL) {
 
		std::cerr << error;
 
		return 1;
 
	}
 

	
 
	Config config(argc, argv);
 
	if (!config.load(configFile)) {
 
		std::cerr << "Can't open " << argv[1] << " configuration file.\n";
 
		return 1;
 
	}
 
	Logging::initBackendLogging(cfg);
 

	
 
	Logging::initBackendLogging(&config);
 
	
 
	std::string error;
 
	StorageBackend *storagebackend;
 
	
 
	storagebackend = StorageBackend::createBackend(&config, error);
 
	storagebackend = StorageBackend::createBackend(cfg, error);
 
	if (storagebackend == NULL) {
 
		LOG4CXX_ERROR(logger, "Error creating StorageBackend! " << error)
 
		return -2;
 
		LOG4CXX_ERROR(logger, "Error creating StorageBackend! " << error);
 
		LOG4CXX_ERROR(logger, "Twitter backend needs storage backend configured to work! " << error);
 
		return NetworkPlugin::StorageBackendNeeded;
 
	}
 

	
 
	else if (!storagebackend->connect()) {
 
		LOG4CXX_ERROR(logger, "Can't connect to database!")
 
		return -1;
 
	}
 

	
 
	Swift::SimpleEventLoop eventLoop;
 
	loop_ = &eventLoop;
 
	np = new TwitterPlugin(&config, &eventLoop, storagebackend, host, port);
 
	np = new TwitterPlugin(cfg, &eventLoop, storagebackend, host, port);
 
	loop_->run();
 

	
 
	return 0;
 
}
docs/guide/debian_ubuntu.textile
Show inline comments
 
@@ -30,10 +30,10 @@ Don’t worry about the warnings that the packages can’t be identified, they w
 

	
 
h2. Install spectrum2 - development version
 

	
 
After you have done that, simply do:
 

	
 
<pre>
 
apt-get install spectrum2-git spectrum2-backend-libpurple-git
 
apt-get install spectrum2 spectrum2-backend-libpurple
 
</pre>
 

	
 
Note that these repositories pull in quite a few dependencies, depending on the distribution you use.
docs/guide/libcommuni.textile
Show inline comments
 
@@ -29,13 +29,13 @@ To use this mode, you have to configure irc_server variable like this:
 
[service]
 
irc_server=irc.freenode.org
 
</pre>
 

	
 
h3. 2.2 One transport for more IRC networks
 

	
 
In this mode users can connect more IRC networks, but they can't connect the network without being in the room. Currently this mode is not finished yet in Spectrum 2.
 
In this mode users can connect more IRC networks, but they can't connect the network without being in the room. To connect the network, user has to join the room in following format: #room%irc.freenode.org@irc.domain.tld. The nickname used in the first join request is used as a nickname for the IRC connection.
 

	
 
h2. 3. All configuration variables
 

	
 
|_. Key |_. Type |_. Default |_. Description |
 
| irc_server | string | | IRC server hostname for "One transport per one IRC network" mode. |
 
| irc_identify | string | NickServ identify $name $password | The fiirst word is nickname of service used for identifying. After the nickname there's a message sent to that service. $name is replaced by the username defined by user in the registration. $password is replaced by password. |
docs/guide/logging.textile
Show inline comments
 
@@ -92,24 +92,43 @@ log4j.category.Component.XML = debug, XML
 
# Do not add XML category into "R" logger, so XML category will be logged only to spectrum2_xml.log, but not to spectrum2.log.
 
# If you want to have XML category also in spectrum2.log, set this value to "true"
 
log4j.additivity.Component.XML=false
 

	
 
# Create new RollingFileAppender logger and set the file name
 
log4j.appender.XML=org.apache.log4j.RollingFileAppender
 
log4j.appender.XML.File=/var/log/spectrum2/${jid}/spectrum2.log
 
log4j.appender.XML.File=/var/log/spectrum2/${jid}/spectrum2_xml.log
 

	
 
# Set MaxFileSize. Log will be rotated automatically when this limit is reached
 
log4j.appender.XML.MaxFileSize=100000KB
 
# Keep one backup file
 
log4j.appender.XML.MaxBackupIndex=4
 

	
 
# Define the output pattern. Characters are mentioned here: http://logging.apache.org/log4cxx/apidocs/classlog4cxx_1_1_pattern_layout.html
 
log4j.appender.XML.layout=org.apache.log4j.PatternLayout
 
log4j.appender.XML.layout.ConversionPattern=%d %-5p %c: %m%n
 
</pre>
 

	
 
h3. Disable XML logging
 

	
 
<pre>
 
# We create two rootLoggers:
 
#   - "debug" is internal logger used by log4cxx
 
#   - "stdout" is name of our ConsoleAppender logger
 
log4j.rootLogger=debug, stdout
 

	
 
# Create new ConsoleAppender logger with custom PatternLayout
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 

	
 
# Define the output pattern. Characters are mentioned here: http://logging.apache.org/log4cxx/apidocs/classlog4cxx_1_1_pattern_layout.html
 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c: %m%n
 

	
 
# Disable XML category
 
log4j.category.Component.XML = OFF
 
</pre>
 

	
 
h3. Disable logging
 

	
 
To disable logging, you still *must have* one logger created (probably the ConsoleAppender), but you can set log4j.threshold = OFF to not log everything later:
 

	
 
<pre>
 
# We create two rootLoggers:
include/transport/conversation.h
Show inline comments
 
@@ -145,9 +145,11 @@ class Conversation {
 
		std::string m_nickname;
 
		std::string m_room;
 
		bool m_muc;
 
		Swift::JID m_jid;
 
		std::list<Swift::JID> m_jids;
 
		std::map<std::string, Participant> m_participants;
 
		boost::shared_ptr<Swift::Message> m_subject;
 
		bool m_sentInitialPresence;
 
};
 

	
 
}
include/transport/conversationmanager.h
Show inline comments
 
@@ -66,12 +66,14 @@ class ConversationManager {
 

	
 
		/// Removes Conversation from the manager.
 

	
 
		/// \param conv Conversation.
 
		void removeConversation(Conversation *conv);
 

	
 
		void deleteAllConversations();
 

	
 
		void resetResources();
 
		void removeJID(const Swift::JID &jid);
 

	
 
	private:
 
		void handleMessageReceived(Swift::Message::ref message);
 

	
include/transport/discoitemsresponder.h
Show inline comments
 
@@ -25,24 +25,33 @@
 
#include "Swiften/Queries/GetResponder.h"
 
#include "Swiften/Elements/DiscoItems.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class DiscoInfoResponder;
 

	
 
class DiscoItemsResponder : public Swift::GetResponder<Swift::DiscoItems> {
 
	public:
 
		DiscoItemsResponder(Component *component);
 
		~DiscoItemsResponder();
 

	
 
		Swift::CapsInfo &getBuddyCapsInfo();
 

	
 
		void addAdHocCommand(const std::string &node, const std::string &name);
 
// 		void removeAdHocCommand(const std::string &node);
 

	
 
		void addRoom(const std::string &node, const std::string &name);
 
		void clearRooms();
 

	
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoItems> payload);
 

	
 
	private:
 
		Component *m_component;
 
		boost::shared_ptr<Swift::DiscoItems> m_commands;
 
		boost::shared_ptr<Swift::DiscoItems> m_rooms;
 
		DiscoInfoResponder *m_discoInfoResponder;
 
};
 

	
 
}
 
\ No newline at end of file
include/transport/factory.h
Show inline comments
 
@@ -37,12 +37,12 @@ class Buddy;
 
class ConversationManager;
 
class RosterManager;
 

	
 
class Factory {
 
	public:
 
		
 
		virtual Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) = 0;
 
		virtual Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMuc = false) = 0;
 

	
 
		virtual Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) = 0;
 
};
 

	
 
}
include/transport/networkplugin.h
Show inline comments
 
@@ -21,22 +21,24 @@
 
#pragma once
 

	
 
#include <time.h>
 
#include "transport/protocol.pb.h"
 
// #include "conversation.h"
 
#include <iostream>
 
#include <list>
 

	
 
namespace Transport {
 

	
 
/// Represents Spectrum2 legacy network plugin.
 

	
 
/// This class is base class for all C++ legacy network plugins. It provides a way to connect 
 
/// Spectrum2 NetworkPluginServer and allows to use high-level API for legacy network plugins
 
/// development.
 
class NetworkPlugin {
 
	public:
 
		enum ExitCode { StorageBackendNeeded = -2 };
 

	
 
		class PluginConfig {
 
			public:
 
				PluginConfig() : m_needPassword(true), m_needRegistration(false) {}
 
				virtual ~PluginConfig() {}
 

	
 
@@ -106,13 +108,13 @@ class NetworkPlugin {
 
		/// Call this function when new message is received from legacy network for user.
 
		/// \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 legacyName Name of legacy network buddy or name of room. (eg. "user2@gmail.com")
 
		/// \param message Plain text message.
 
		/// \param nickname Nickname of buddy in room. Empty if it's normal chat message.
 
		/// \param xhtml XHTML message.
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "");
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string &timestamp = "");
 

	
 
		/// Call this function when subject in room 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 legacyName Name of room. (eg. "#spectrum")
 
		/// \param message Subject message.
 
		/// \param nickname Nickname of user who changed subject.
 
@@ -161,12 +163,14 @@ class NetworkPlugin {
 

	
 
		void handleFTStart(const std::string &user, const std::string &buddyName, const std::string fileName, unsigned long size);
 
		void handleFTFinish(const std::string &user, const std::string &buddyName, const std::string fileName, unsigned long size, unsigned long ftid);
 

	
 
		void handleFTData(unsigned long ftID, const std::string &data);
 

	
 
		void handleRoomList(const std::string &user, const std::list<std::string> &rooms, const std::list<std::string> &names);
 

	
 
		/// 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.
 
		/**
include/transport/networkpluginserver.h
Show inline comments
 
@@ -40,12 +40,13 @@ class Config;
 
class NetworkConversation;
 
class VCardResponder;
 
class RosterResponder;
 
class BlockResponder;
 
class DummyReadBytestream;
 
class AdminInterface;
 
class DiscoItemsResponder;
 

	
 
class NetworkPluginServer {
 
	public:
 
		struct Backend {
 
			int pongReceived;
 
			std::list<User *> users;
 
@@ -57,16 +58,18 @@ class NetworkPluginServer {
 
			bool acceptUsers;
 
			bool longRun;
 
			bool willDie;
 
			std::string id;
 
		};
 

	
 
		NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager);
 
		NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder);
 

	
 
		virtual ~NetworkPluginServer();
 

	
 
		void start();
 

	
 
		void setAdminInterface(AdminInterface *adminInterface) {
 
			m_adminInterface = adminInterface;
 
		}
 

	
 
		int getBackendCount() {
 
			return m_clients.size();
 
@@ -83,13 +86,13 @@ class NetworkPluginServer {
 
		void collectBackend();
 

	
 
		bool moveToLongRunBackend(User *user);
 

	
 
		void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr<Swift::Message> &message);
 

	
 
	private:
 
	public:
 
		void handleNewClientConnection(boost::shared_ptr<Swift::Connection> c);
 
		void handleSessionFinished(Backend *c);
 
		void handlePongReceived(Backend *c);
 
		void handleDataRead(Backend *c, boost::shared_ptr<Swift::SafeByteArray> data);
 

	
 
		void handleConnectedPayload(const std::string &payload);
 
@@ -106,12 +109,13 @@ class NetworkPluginServer {
 
		void handleStatsPayload(Backend *c, const std::string &payload);
 
		void handleFTStartPayload(const std::string &payload);
 
		void handleFTFinishPayload(const std::string &payload);
 
		void handleFTDataPayload(Backend *b, const std::string &payload);
 
		void handleQueryPayload(Backend *b, const std::string &payload);
 
		void handleBackendConfigPayload(const std::string &payload);
 
		void handleRoomListPayload(const std::string &payload);
 

	
 
		void handleUserCreated(User *user);
 
		void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password);
 
		void handleRoomLeft(User *user, const std::string &room);
 
		void handleUserReadyToConnect(User *user);
 
		void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
 
@@ -128,12 +132,13 @@ class NetworkPluginServer {
 

	
 
		void handleFTStateChanged(Swift::FileTransfer::State state, const std::string &userName, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long id);
 
		void handleFTAccepted(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID);
 
		void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size);
 
		void handleFTDataNeeded(Backend *b, unsigned long ftid);
 

	
 
	private:
 
		void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
 

	
 
		void pingTimeout();
 
		void sendPing(Backend *c);
 
		Backend *getFreeClient(bool acceptUsers = true, bool longRun = false);
 

	
 
@@ -151,9 +156,10 @@ class NetworkPluginServer {
 
		bool m_isNextLongRun;
 
		std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
 
		FileTransferManager *m_ftManager;
 
		std::vector<std::string> m_crashedBackends;
 
		AdminInterface *m_adminInterface;
 
		bool m_startingBackend;
 
		DiscoItemsResponder *m_discoItemsResponder;
 
};
 

	
 
}
include/transport/protocol.proto
Show inline comments
 
@@ -66,21 +66,27 @@ message Buddy {
 
message ConversationMessage {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required string message = 3;
 
	optional string nickname = 4;
 
	optional string xhtml = 5;
 
	optional string timestamp = 6;
 
}
 

	
 
message Room {
 
	required string userName = 1;
 
	required string nickname = 2;
 
	required string room = 3;
 
	optional string password = 4;
 
}
 

	
 
message RoomList {
 
	repeated string room = 1;
 
	repeated string name = 2;
 
}
 

	
 
message Participant {
 
	required string userName = 1;
 
	required string room = 2;
 
	required string nickname = 3;
 
	required int32 flag = 4;
 
	required StatusType status = 5;
 
@@ -156,11 +162,12 @@ message WrapperMessage {
 
		TYPE_FT_DATA				= 26;
 
		TYPE_FT_PAUSE				= 27;
 
		TYPE_FT_CONTINUE			= 28;
 
		TYPE_EXIT					= 29;
 
		TYPE_BACKEND_CONFIG			= 30;
 
		TYPE_QUERY					= 31;
 
		TYPE_ROOM_LIST				= 32;
 
	}
 
	required Type type = 1;
 
	optional bytes payload = 2;
 
}
 
;
include/transport/storagebackend.h
Show inline comments
 
@@ -83,12 +83,20 @@ struct BuddyInfo {
 
class Config;
 

	
 
/// Abstract class defining storage backends.
 
class StorageBackend
 
{
 
	public:
 
		static std::string encryptPassword(const std::string &password, const std::string &key);
 

	
 
		static std::string decryptPassword(std::string &encrypted, const std::string &key);
 

	
 
		static std::string serializeGroups(const std::vector<std::string> &groups);
 

	
 
		static std::vector<std::string> deserializeGroups(std::string &groups);
 

	
 
		/// Virtual desctructor.
 
		virtual ~StorageBackend() {}
 

	
 
		static StorageBackend *createBackend(Config *config, std::string &error);
 

	
 
		/// connect
include/transport/transport.h
Show inline comments
 
@@ -44,13 +44,12 @@ namespace Transport {
 
	// 				CLIENT_FEATURE_XHTML_IM = 4,
 
	// 				CLIENT_FEATURE_FILETRANSFER = 8,
 
	// 				CLIENT_FEATURE_CHATSTATES = 16
 
	// 				} SpectrumImportantFeatures;
 
	// 
 
	class StorageBackend;
 
	class DiscoInfoResponder;
 
	class Factory;
 
	class UserRegistry;
 

	
 
	/// Represents one transport instance.
 

	
 
	/// It's used to connect the Jabber server and provides transaction layer
 
@@ -78,14 +77,12 @@ namespace Transport {
 
			/// Returns Swift::StanzaChannel associated with this Transport::Component.
 

	
 
			/// It can be used to send presences and other stanzas.
 
			/// \return Swift::StanzaChannel associated with this Transport::Component.
 
			Swift::StanzaChannel *getStanzaChannel();
 

	
 
			Swift::CapsInfo &getBuddyCapsInfo();
 

	
 
			/// Returns Swift::IQRouter associated with this Component.
 

	
 
			/// \return Swift::IQRouter associated with this Component.
 
			Swift::IQRouter *getIQRouter() { return m_iqRouter; }
 

	
 
			/// Returns Swift::PresenceOracle associated with this Transport::Component.
 
@@ -101,24 +98,12 @@ namespace Transport {
 

	
 
			/// Connects the Jabber server.
 

	
 
			void start();
 
			void stop();
 

	
 
			/// Sets disco#info features which are sent as answer to disco#info IQ-get.
 
			
 
			/// This sets features of transport contact (For example "j2j.domain.tld").
 
			/// \param features list of features as sent in disco#info response
 
			void setTransportFeatures(std::list<std::string> &features);
 

	
 
			/// Sets disco#info features which are sent as answer to disco#info IQ-get.
 
			
 
			/// This sets features of legacy network buddies (For example "me\40gmail.com@j2j.domain.tld").
 
			/// \param features list of features as sent in disco#info response
 
			void setBuddyFeatures(std::list<std::string> &features);
 

	
 
			/// Returns Jabber ID of this transport.
 

	
 
			/// \return Jabber ID of this transport
 
			Swift::JID &getJID() { return m_jid; }
 

	
 
			/// Returns Swift::NetworkFactories which can be used to create new connections.
 
@@ -183,13 +168,12 @@ namespace Transport {
 
			PresenceOracle *m_presenceOracle;
 
			Swift::StanzaChannel *m_stanzaChannel;
 
			Swift::IQRouter *m_iqRouter;
 
			
 
			Transport::UserRegistry *m_userRegistry;
 
			StorageBackend *m_storageBackend;
 
 			DiscoInfoResponder *m_discoInfoResponder;
 
			int m_reconnectCount;
 
			Config* m_config;
 
			std::string m_protocol;
 
			Swift::JID m_jid;
 
			Factory *m_factory;
 
			Swift::EventLoop *m_loop;
include/transport/user.h
Show inline comments
 
@@ -68,18 +68,20 @@ class User : public Swift::EntityCapsProvider {
 
		RosterManager *getRosterManager() { return m_rosterManager; }
 

	
 
		ConversationManager *getConversationManager() { return m_conversationManager; }
 

	
 
		Component *getComponent() { return m_component; }
 

	
 
		UserManager *getUserManager() { return m_userManager; }
 

	
 
		void setData(void *data) { m_data = data; }
 
		void *getData() { return m_data; }
 

	
 
		/// Handles presence from XMPP JID associated with this user.
 
		/// \param presence Swift::Presence.
 
		void handlePresence(Swift::Presence::ref presence);
 
		void handlePresence(Swift::Presence::ref presence, bool forceJoin = false);
 

	
 
		void handleSubscription(Swift::Presence::ref presence);
 

	
 
		void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
 

	
 
		time_t &getLastActivity() {
 
@@ -139,9 +141,10 @@ class User : public Swift::EntityCapsProvider {
 
		boost::shared_ptr<Swift::Connection> connection;
 
		time_t m_lastActivity;
 
		std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
 
		std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
 
		int m_resources;
 
		int m_reconnectCounter;
 
		std::list<Swift::Presence::ref> m_joinedRooms;
 
};
 

	
 
}
include/transport/usermanager.h
Show inline comments
 
@@ -29,12 +29,13 @@ namespace Transport {
 

	
 
class User;
 
class Component;
 
class StorageBackend;
 
class StorageResponder;
 
class RosterResponder;
 
class DiscoItemsResponder;
 

	
 
/// Manages online XMPP Users.
 

	
 
/// This class handles presences and creates User classes when new user connects.
 
/// It also removes the User class once the last user's resource disconnected.
 

	
 
@@ -52,13 +53,13 @@ class RosterResponder;
 
*/
 
class UserManager : public Swift::EntityCapsProvider {
 
	public:
 
		/// Creates new UserManager.
 
		/// \param component Component which's presence will be handled
 
		/// \param storageBackend Storage backend used to fetch UserInfos
 
		UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL);
 
		UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend = NULL);
 

	
 
		/// Destroys UserManager.
 
		~UserManager();
 

	
 
		/// Returns user according to his bare JID.
 
		/// \param barejid bare JID of user
 
@@ -81,12 +82,14 @@ class UserManager : public Swift::EntityCapsProvider {
 
		void removeUser(User *user, bool onUserBehalf = true);
 

	
 
		void removeAllUsers(bool onUserBehalf = true);
 

	
 
		Swift::DiscoInfo::ref getCaps(const Swift::JID&) const;
 

	
 
		DiscoItemsResponder *getDiscoResponder() { return m_discoItemsResponder; }
 

	
 
		/// Called when new User class is created.
 
		/// \param user newly created User class
 
		boost::signal<void (User *user)> onUserCreated;
 

	
 
		/// Called when User class is going to be removed
 
		/// \param user removed User class
 
@@ -125,12 +128,13 @@ class UserManager : public Swift::EntityCapsProvider {
 

	
 
	private:
 
		void handlePresence(Swift::Presence::ref presence);
 
		void handleMessageReceived(Swift::Message::ref message);
 
		void handleGeneralPresenceReceived(Swift::Presence::ref presence);
 
		void handleProbePresence(Swift::Presence::ref presence);
 
		void handleErrorPresence(Swift::Presence::ref presence);
 
		void handleSubscription(Swift::Presence::ref presence);
 
		void handleRemoveTimeout(const std::string jid, User *user, bool reconnect);
 
		void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
 
		void addUser(User *user);
 

	
 
		long m_onlineBuddies;
 
@@ -140,10 +144,11 @@ class UserManager : public Swift::EntityCapsProvider {
 
		StorageBackend *m_storageBackend;
 
		StorageResponder *m_storageResponder;
 
		UserRegistry *m_userRegistry;
 
		Swift::Timer::ref m_removeTimer;
 
		unsigned long m_sentToXMPP;
 
		unsigned long m_sentToBackend;
 
		DiscoItemsResponder *m_discoItemsResponder;
 
		friend class RosterResponder;
 
};
 

	
 
}
include/transport/util.h
Show inline comments
 
@@ -23,25 +23,22 @@
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <vector>
 
#include <string>
 
#include "Swiften/StringCodecs/Base64.h"
 

	
 
#include <boost/filesystem.hpp>
 
#include "transport/config.h"
 

	
 
namespace Transport {
 

	
 
namespace Util {
 

	
 
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t);
 

	
 
std::string encryptPassword(const std::string &password, const std::string &key);
 
void createDirectories(Transport::Config *config, const boost::filesystem::path& ph);
 

	
 
std::string decryptPassword(std::string &encrypted, const std::string &key);
 

	
 
std::string serializeGroups(const std::vector<std::string> &groups);
 

	
 
std::vector<std::string> deserializeGroups(std::string &groups);
 
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t);
 

	
 
int getRandomPort(const std::string &s);
 

	
 
#ifdef _WIN32
 
	std::wstring utf8ToUtf16(const std::string& str);
 
#endif
plugin/cpp/CMakeLists.txt
Show inline comments
 
@@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.h)
 
FILE(GLOB HEADERS ../include/transport/*.h)
 
 
set(EXTRA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../src/memoryusage.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/logging.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/config.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/util.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc)
 
 
if (NOT WIN32)
 
	ADD_LIBRARY(transport-plugin SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ${EXTRA_SOURCES})
 
else()
 
	ADD_LIBRARY(transport-plugin STATIC ${HEADERS} ${SRC} ${EXTRA_SOURCES} )
plugin/cpp/networkplugin.cpp
Show inline comments
 
@@ -60,13 +60,13 @@ NetworkPlugin::NetworkPlugin() {
 
}
 

	
 
NetworkPlugin::~NetworkPlugin() {
 
}
 

	
 
void NetworkPlugin::sendConfig(const PluginConfig &cfg) {
 
	std::string data = "[registration]";
 
	std::string data = "[registration]\n";
 
	data += std::string("needPassword=") + (cfg.m_needPassword ? "1" : "0") + "\n";
 
	data += std::string("needRegistration=") + (cfg.m_needRegistration ? "1" : "0") + "\n";
 

	
 
	for (std::vector<std::string>::const_iterator it = cfg.m_extraFields.begin(); it != cfg.m_extraFields.end(); it++) {
 
		data += std::string("extraField=") + (*it) + "\n";
 
	}
 
@@ -79,19 +79,20 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) {
 

	
 
	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) {
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string &timestamp) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message(msg);
 
	m.set_nickname(nickname);
 
	m.set_xhtml(xhtml);
 
	m.set_timestamp(timestamp);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 

	
 
@@ -333,12 +334,30 @@ void NetworkPlugin::handleFTData(unsigned long ftID, const std::string &data) {
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_FT_DATA);
 
 
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleRoomList(const std::string &user, const std::list<std::string> &rooms, const std::list<std::string> &names) {
 
	pbnetwork::RoomList d;
 
	for (std::list<std::string>::const_iterator it = rooms.begin(); it != rooms.end(); it++) {
 
		d.add_room(*it);
 
	}
 

	
 
	for (std::list<std::string>::const_iterator it = names.begin(); it != names.end(); it++) {
 
		d.add_name(*it);
 
	}
 

	
 
	std::string message;
 
	d.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ROOM_LIST);
 
 
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleLoginPayload(const std::string &data) {
 
	pbnetwork::Login payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
spectrum/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
 
# if (WIN32)
 
# FILE(GLOB WIN_SRC win32/*.cpp)
 
# include_directories(win32)
 
# ADD_EXECUTABLE(spectrum2 ${SRC} ${WIN_SRC})
 
# else()
 
if (WIN32)
 
FILE(GLOB WIN_SRC win32/*.cpp)
 
include_directories(win32)
 
ADD_EXECUTABLE(spectrum2 ${SRC} ${WIN_SRC})
 
else()
 
ADD_EXECUTABLE(spectrum2 ${SRC})
 
# endif()
 
endif()
 
 
 
 
ADD_DEPENDENCIES(spectrum2 spectrum2_libpurple_backend)
 
ADD_DEPENDENCIES(spectrum2 spectrum2_libircclient-qt_backend)
 
spectrum/src/main.cpp
Show inline comments
 
@@ -19,32 +19,42 @@
 
#include "transport/settingsadhoccommand.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include "sys/stat.h"
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#ifndef __FreeBSD__
 
#include <malloc.h>
 
#endif
 
#else
 
#include <process.h>
 
#define getpid _getpid
 
// #include "win32/SpectrumService.h"
 
#include "win32/ServiceWrapper.h"
 
#endif
 
#include <sys/stat.h>
 

	
 
using namespace Transport;
 
using namespace Transport::Util;
 

	
 
DEFINE_LOGGER(logger, "Spectrum");
 

	
 
Swift::SimpleEventLoop *eventLoop_ = NULL;
 
Component *component_ = NULL;
 
UserManager *userManager_ = NULL;
 
Config *config_ = NULL;
 

	
 
void stop() {
 
	userManager_->removeAllUsers(false);
 
	component_->stop();
 
	eventLoop_->stop();
 
}
 

	
 
static void stop_spectrum() {
 
	userManager_->removeAllUsers(false);
 
	component_->stop();
 
	eventLoop_->stop();
 
}
 
@@ -116,26 +126,163 @@ static void daemonize(const char *cwd, const char *lock_file) {
 
		exit(1);
 
	}
 
}
 

	
 
#endif
 

	
 
int mainloop() {
 

	
 
#ifndef WIN32
 
	mode_t old_cmask = umask(0007);
 
#endif
 

	
 
	Logging::initMainLogging(config_);
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(config_, "service.group").empty() ||!CONFIG_STRING(config_, "service.user").empty() ) {
 
		struct rlimit limit;
 
		getrlimit(RLIMIT_CORE, &limit);
 

	
 
		if (!CONFIG_STRING(config_, "service.group").empty()) {
 
			struct group *gr;
 
			if ((gr = getgrnam(CONFIG_STRING(config_, "service.group").c_str())) == NULL) {
 
				std::cerr << "Invalid service.group name " << CONFIG_STRING(config_, "service.group") << "\n";
 
				return 1;
 
			}
 

	
 
			if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(config_, "service.user").c_str(), gr->gr_gid) != 0)) {
 
				std::cerr << "Failed to set service.group name " << CONFIG_STRING(config_, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
		}
 

	
 
		if (!CONFIG_STRING(config_, "service.user").empty()) {
 
			struct passwd *pw;
 
			if ((pw = getpwnam(CONFIG_STRING(config_, "service.user").c_str())) == NULL) {
 
				std::cerr << "Invalid service.user name " << CONFIG_STRING(config_, "service.user") << "\n";
 
				return 1;
 
			}
 

	
 
			if ((setuid(pw->pw_uid)) != 0) {
 
				std::cerr << "Failed to set service.user name " << CONFIG_STRING(config_, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
		}
 
		setrlimit(RLIMIT_CORE, &limit);
 
	}
 

	
 
	struct rlimit limit;
 
	limit.rlim_max = RLIM_INFINITY;
 
	limit.rlim_cur = RLIM_INFINITY;
 
	setrlimit(RLIMIT_CORE, &limit);
 
#endif
 

	
 
	Swift::SimpleEventLoop eventLoop;
 

	
 
	Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop);
 
	UserRegistry userRegistry(config_, factories);
 

	
 
	Component transport(&eventLoop, factories, config_, NULL, &userRegistry);
 
	component_ = &transport;
 
// 	Logger logger(&transport);
 

	
 
	std::string error;
 
	StorageBackend *storageBackend = StorageBackend::createBackend(config_, error);
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
	}
 
	else if (!storageBackend->connect()) {
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 

	
 
	Logging::redirect_stderr();
 

	
 
	DiscoItemsResponder discoItemsResponder(&transport);
 
	discoItemsResponder.start();
 

	
 
	UserManager userManager(&transport, &userRegistry, &discoItemsResponder, storageBackend);
 
	userManager_ = &userManager;
 

	
 
	UserRegistration *userRegistration = NULL;
 
	UsersReconnecter *usersReconnecter = NULL;
 
	if (storageBackend) {
 
		userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration->start();
 

	
 
		usersReconnecter = new UsersReconnecter(&transport, storageBackend);
 
	}
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 

	
 
	NetworkPluginServer plugin(&transport, config_, &userManager, &ftManager, &discoItemsResponder);
 
	plugin.start();
 

	
 
	AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration);
 
	plugin.setAdminInterface(&adminInterface);
 

	
 
	StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
 
	statsResponder.start();
 

	
 
	GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager);
 
	gatewayResponder.start();
 

	
 
	AdHocManager adhocmanager(&transport, &discoItemsResponder, &userManager, storageBackend);
 
	adhocmanager.start();
 

	
 
	SettingsAdHocCommandFactory settings;
 
	adhocmanager.addAdHocCommand(&settings);
 

	
 
	eventLoop_ = &eventLoop;
 

	
 
	eventLoop.run();
 

	
 
#ifndef WIN32
 
	umask(old_cmask);
 
#endif
 

	
 
	if (userRegistration) {
 
		userRegistration->stop();
 
		delete userRegistration;
 
	}
 

	
 
	if (usersReconnecter) {
 
		delete usersReconnecter;
 
	}
 

	
 
	delete storageBackend;
 
	delete factories;
 
	return 0;
 
}
 

	
 

	
 
int main(int argc, char **argv)
 
{
 
	Config config(argc, argv);
 

	
 
	config_ = &config;
 
	boost::program_options::variables_map vm;
 
	bool no_daemon = false;
 
	std::string config_file;
 
	std::string jid;
 

	
 
#ifdef WIN32
 
	std::string install_service_name, uninstall_service_name, run_service_name;
 
	// determine the name of the currently executing file
 
	char szFilePath[MAX_PATH];
 
	GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath));
 
	std::string exe_file(szFilePath);					
 
#endif	
 
	setlocale(LC_ALL, "");
 
#ifndef WIN32
 
#ifndef __FreeBSD__
 
	mallopt(M_CHECK_ACTION, 2);
 
	mallopt(M_PERTURB, 0xb);
 
#endif
 
#endif
 

	
 
#ifndef WIN32
 
	if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
		std::cout << "SIGINT handler can't be set\n";
 
		return -1;
 
	}
 
@@ -152,15 +299,16 @@ int main(int argc, char **argv)
 
		("no-debug,d", "Create coredumps on crash")
 
		("jid,j", boost::program_options::value<std::string>(&jid)->default_value(""), "Specify JID of transport manually")
 
		("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
 
		("version,v", "Shows Spectrum version")
 
		;
 
#ifdef WIN32
 
// 	desc.add_options()
 
// 		("install-service,i", "Install spectrum as Windows service")
 
// 		("uninstall-service,u", "Uninstall Windows service");
 
 	desc.add_options()
 
		("install-service,i", boost::program_options::value<std::string>(&install_service_name)->default_value(""), "Install spectrum as Windows service")
 
 		("uninstall-service,u", boost::program_options::value<std::string>(&uninstall_service_name)->default_value(""), "Uninstall Windows service")
 
		("run-as-service,r", boost::program_options::value<std::string>(&run_service_name)->default_value(""), "stub for Windows Service Manager");
 
#endif
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
 
@@ -183,52 +331,47 @@ int main(int argc, char **argv)
 
			return 1;
 
		}
 

	
 
		if(vm.count("no-daemonize")) {
 
			no_daemon = true;
 
		}
 
#ifdef WIN32
 
#if 0
 
		if (vm.count("install-service")) {
 
			SpectrumService ntservice;
 
#ifdef WIN32	
 
		if (!install_service_name.empty()) {				
 
			// build command line for Service Manager
 
			std::string service_path = exe_file + std::string(" --config ") + vm["config"].as<std::string>() 
 
						+ std::string(" --run-as-service ") + install_service_name;													
 
		
 
			ServiceWrapper ntservice((char *)install_service_name.c_str());
 
			if (!ntservice.IsInstalled()) {
 
					// determine the name of the currently executing file
 
				char szFilePath[MAX_PATH];
 
				GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
 
				std::string exe_file(szFilePath);
 
				std::string config_file = exe_file.replace(exe_file.end() - 4, exe_file.end(), ".cfg");
 
				std::string service_path = std::string(szFilePath) + std::string(" --config ") + config_file;
 

	
 
				if (ntservice.Install(service_path.c_str())) {
 
					std::cout << "Successfully installed" << std::endl;
 
				if (ntservice.Install((char *)service_path.c_str())) {
 
					std::cout << "Successfully installed " << install_service_name << std::endl;
 
					return 0;
 
				} else {
 
					std::cout << "Error installing service, are you an Administrator?" << std::endl;
 
					return 1;
 
				}                				
 
			} else {
 
				std::cout << "Already installed" << std::endl;
 
				std::cout << "Already installed " << install_service_name << std::endl;
 
				return 1;
 
			}
 
		}
 
		if (vm.count("uninstall-service")) {
 
			SpectrumService ntservice;
 
		if (!uninstall_service_name.empty()) {
 
			ServiceWrapper ntservice((char *)uninstall_service_name.c_str());
 
			if (ntservice.IsInstalled()) {
 
				if (ntservice.Remove()) {
 
					std::cout << "Successfully removed" << std::endl;
 
				if (ntservice.UnInstall()) {
 
					std::cout << "Successfully removed " << uninstall_service_name << std::endl;
 
					return 0;
 
				} else {
 
					std::cout << "Error removing service, are you an Administrator?" << std::endl;
 
					return 1;
 
				}                               				
 
			} else {
 
				std::cout << "Service not installed" << std::endl;
 
				std::cout << "Service not installed: " << uninstall_service_name << std::endl;
 
				return 1;
 
			}
 
		}
 
#endif
 
		}		
 
#endif
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		return 1;
 
@@ -243,13 +386,14 @@ int main(int argc, char **argv)
 
		std::cerr << "Can't load configuration file.\n";
 
		return 1;
 
	}
 

	
 
	// create directories
 
	try {
 
		boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir"));
 
		
 
		Transport::Util::createDirectories(&config, CONFIG_STRING(&config, "service.working_dir"));
 
	}
 
	catch (...) {
 
		std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n";
 
		return 1;
 
	}
 
#ifndef WIN32
 
@@ -277,26 +421,12 @@ int main(int argc, char **argv)
 

	
 
#ifdef WIN32
 
	SetCurrentDirectory( utf8ToUtf16(CONFIG_STRING(&config, "service.working_dir")).c_str() );
 
#endif
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
 
		struct group *gr;
 
		if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
			std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
			return 1;
 
		}
 
		struct passwd *pw;
 
		if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
			std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
			return 1;
 
		}
 
		chown(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid);
 
	}
 

	
 
	char backendport[20];
 
	FILE* port_file_f;
 
	port_file_f = fopen(CONFIG_STRING(&config, "service.portfile").c_str(), "w+");
 
	if (port_file_f == NULL) {
 
		std::cerr << "Cannot create port_file file " << CONFIG_STRING(&config, "service.portfile").c_str() << ". Exiting\n";
 
		exit(1);
 
@@ -311,123 +441,22 @@ int main(int argc, char **argv)
 
	if (!no_daemon) {
 
		// daemonize
 
		daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str());
 
// 		removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons");
 
    }
 
#endif
 

	
 
	Logging::initMainLogging(&config);
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
 
		struct rlimit limit;
 
		getrlimit(RLIMIT_CORE, &limit);
 

	
 
		if (!CONFIG_STRING(&config, "service.group").empty()) {
 
			struct group *gr;
 
			if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
				std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
				return 1;
 
			}
 

	
 
			if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) {
 
				std::cerr << "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
		}
 

	
 
		if (!CONFIG_STRING(&config, "service.user").empty()) {
 
			struct passwd *pw;
 
			if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
				std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
				return 1;
 
			}
 

	
 
			if ((setuid(pw->pw_uid)) != 0) {
 
				std::cerr << "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
#ifdef WIN32
 
	if (!run_service_name.empty()) {
 
		ServiceWrapper ntservice((char *)run_service_name.c_str());
 
		if (ntservice.IsInstalled()) {
 
			ntservice.RunService();
 
		} else {
 
			std::cerr << "Service not installed: " << run_service_name << std::endl;
 
			return 1;
 
		}
 
		setrlimit(RLIMIT_CORE, &limit);
 
	} else {
 
		mainloop();
 
	}
 

	
 
	struct rlimit limit;
 
	limit.rlim_max = RLIM_INFINITY;
 
	limit.rlim_cur = RLIM_INFINITY;
 
	setrlimit(RLIMIT_CORE, &limit);
 
#else
 
	mainloop();
 
#endif
 

	
 
	Swift::SimpleEventLoop eventLoop;
 

	
 
	Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop);
 
	UserRegistry userRegistry(&config, factories);
 

	
 
	Component transport(&eventLoop, factories, &config, NULL, &userRegistry);
 
	component_ = &transport;
 
// 	Logger logger(&transport);
 

	
 
	std::string error;
 
	StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
	}
 
	else if (!storageBackend->connect()) {
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 

	
 
	Logging::redirect_stderr();
 

	
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	userManager_ = &userManager;
 

	
 
	UserRegistration *userRegistration = NULL;
 
	UsersReconnecter *usersReconnecter = NULL;
 
	if (storageBackend) {
 
		userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration->start();
 

	
 
		usersReconnecter = new UsersReconnecter(&transport, storageBackend);
 
	}
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 

	
 
	NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager);
 

	
 
	AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration);
 
	plugin.setAdminInterface(&adminInterface);
 

	
 
	StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
 
	statsResponder.start();
 

	
 
	GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager);
 
	gatewayResponder.start();
 

	
 
	DiscoItemsResponder discoItemsResponder(&transport);
 
	discoItemsResponder.start();
 

	
 
	AdHocManager adhocmanager(&transport, &discoItemsResponder, &userManager, storageBackend);
 
	adhocmanager.start();
 

	
 
	SettingsAdHocCommandFactory settings;
 
	adhocmanager.addAdHocCommand(&settings);
 

	
 
	eventLoop_ = &eventLoop;
 

	
 
	eventLoop.run();
 

	
 
	if (userRegistration) {
 
		userRegistration->stop();
 
		delete userRegistration;
 
	}
 

	
 
	if (usersReconnecter) {
 
		delete usersReconnecter;
 
	}
 

	
 
	delete storageBackend;
 
	delete factories;
 
	return 0;
 
}
spectrum/src/sample.cfg
Show inline comments
 
@@ -10,21 +10,22 @@ pidfile=./test.pid
 
#backend_port=10001
 
#admin_jid=admin@localhost
 
admin_password=test
 
#cert=server.pfx #patch to PKCS#12 certificate
 
#cert_password=test #password to that certificate if any
 
users_per_backend=10
 
backend=../..//backends/libpurple/spectrum2_libpurple_backend
 
backend=../..//backends/swiften/spectrum2_swiften_backend
 
#backend=../../backends/twitter/spectrum2_twitter_backend
 
#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_communi_backend
 
protocol=prpl-icq
 
#backend=/home/hanzz/code/libtransport/backends/libcommuni/spectrum2_libcommuni_backend
 
protocol=prpl-jabber
 
#protocol=prpl-msn
 
#protocol=any
 
#protocol=prpl-icq
 
working_dir=./
 
portfile=$jid.port
 
irc_server=irc.freenode.org
 

	
 
[backend]
 
#default_avatar=catmelonhead.jpg
 
#no_vcard_fetch=true
 

	
 
[logging]
spectrum/src/sample2.cfg
Show inline comments
 
@@ -36,13 +36,13 @@ backend_host = localhost
 

	
 
# Number of users per one legacy network backend.
 
users_per_backend=10
 

	
 
# Full path to backend binary.
 
backend=/usr/bin/spectrum2_libpurple_backend
 
#backend=/usr/bin/spectrum2_libircclient-qt_backend
 
#backend=/usr/bin/spectrum2_libcommuni_backend
 
# For skype:
 
#backend=/usr/bin/xvfb-run -n BACKEND_ID -s "-screen 0 10x10x8" -f /tmp/x-skype-gw /usr/bin/spectrum2_skype_backend
 

	
 
# Libpurple protocol-id for spectrum_libpurple_backend
 
protocol=prpl-jabber
 
#protocol=prpl-msn
spectrum/src/win32/ServiceWrapper.cpp
Show inline comments
 
new file 100644
 
#include "ServiceWrapper.h"
 

	
 

	
 
LPSTR ServiceName;
 
SERVICE_STATUS ServiceStatus;
 
SERVICE_STATUS_HANDLE ServiceStatusHandle;	
 

	
 
bool doAction (int action, int desiredAccess, LPSTR path = NULL);
 

	
 
enum actions {
 
	DO_INSTALL, DO_DELETE, DO_CHECK 
 
};
 

	
 

	
 
ServiceWrapper::ServiceWrapper(LPSTR serviceName)
 
{
 
	ServiceName = serviceName;
 
	ServiceStatusHandle = 0;	
 
}
 

	
 
ServiceWrapper::~ServiceWrapper(void)
 
{
 
}
 

	
 
bool ServiceWrapper::Install(LPSTR commandLine) {
 
	return doAction(DO_INSTALL, SC_MANAGER_ALL_ACCESS, commandLine);		
 
}
 

	
 
bool ServiceWrapper::UnInstall() {
 
	return doAction(DO_DELETE, SC_MANAGER_ALL_ACCESS);
 
}
 

	
 
bool ServiceWrapper::IsInstalled() {
 
	return doAction(DO_CHECK, SC_MANAGER_CONNECT);	
 
}
 

	
 
bool doAction(int action, int desiredAccess, LPSTR path) {
 
	SC_HANDLE scm = OpenSCManager(NULL, NULL, desiredAccess);
 
	SC_HANDLE service = NULL;
 
	if (!scm) return FALSE;
 

	
 
	switch(action) {
 
	case DO_INSTALL:
 
		service = CreateServiceA(
 
			scm, 
 
			ServiceName, 
 
			ServiceName, 
 
			SERVICE_ALL_ACCESS, 
 
			SERVICE_WIN32_OWN_PROCESS, 
 
			SERVICE_DEMAND_START, 
 
			SERVICE_ERROR_NORMAL, 
 
			path,
 
			NULL,
 
			NULL,
 
			NULL,
 
			NULL,
 
			NULL
 
			);
 
		return (service != NULL);
 
		break;
 
	case DO_DELETE:
 
		service = OpenServiceA(scm, ServiceName, DELETE);
 
		if (service == NULL)
 
			return FALSE;
 
		if (DeleteService(service))
 
			return TRUE;
 
		break;
 
	case DO_CHECK:
 
		service = OpenServiceA(scm, ServiceName, SERVICE_QUERY_STATUS);
 
		return (service != NULL);
 
	default:
 
		return FALSE;
 
	}
 
	CloseServiceHandle(service);		
 
	CloseServiceHandle(scm);
 
	return FALSE;
 
}
 

	
 
void WINAPI ServiceControlHandler(DWORD controlCode) {
 
	switch (controlCode) {
 
	case SERVICE_CONTROL_INTERROGATE:
 
		break;
 
	case SERVICE_CONTROL_STOP:
 
		ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;		
 
		break;
 
	default:
 
		break;
 
	}
 
	SetServiceStatus(ServiceStatusHandle, &ServiceStatus);	
 
	stop();
 
}
 

	
 
void WINAPI ServiceMain(DWORD argc, LPSTR *argv) {
 
	ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
 
	ServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
 

	
 
	ServiceStatusHandle = RegisterServiceCtrlHandlerA(ServiceName, ServiceControlHandler);
 
	if (ServiceStatusHandle) {
 
		ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
 
		SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
 
		ServiceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
 
		ServiceStatus.dwCurrentState = SERVICE_RUNNING;
 
		SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
 
		mainloop();
 
		ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
 
		SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
 
		ServiceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
 
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
 
		SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
 
	}	
 
}
 

	
 
void ServiceWrapper::RunService() {
 
	SERVICE_TABLE_ENTRYA serviceTable[] = {
 
		{ ServiceName, ServiceMain },
 
		{ NULL, NULL}
 
	};
 

	
 
	StartServiceCtrlDispatcherA(serviceTable);
 
}
 
\ No newline at end of file
spectrum/src/win32/ServiceWrapper.h
Show inline comments
 
new file 100644
 
#pragma once
 
#include "transport/config.h"
 
#include <windows.h>
 
#include <tchar.h>
 

	
 
class ServiceWrapper
 
{
 
public:
 
	ServiceWrapper(LPSTR serviceName);
 
	~ServiceWrapper(void);
 
	bool Install(LPSTR commandLine);
 
	bool UnInstall();
 
	bool IsInstalled();
 
	void RunService();
 
};
 

	
 
int mainloop();
 
void stop();
 

	
spectrum/src/win32/SpectrumService.cpp
Show inline comments
 
deleted file
spectrum/src/win32/SpectrumService.h
Show inline comments
 
deleted file
spectrum/src/win32/WindowsService.cpp
Show inline comments
 
deleted file
spectrum/src/win32/WindowsService.h
Show inline comments
 
deleted file
spectrum_manager/src/main.cpp
Show inline comments
 
@@ -136,13 +136,16 @@ int main(int argc, char **argv)
 
	}
 
	else if (command[0] == "list") {
 
		std::vector<std::string> list = show_list(&config);
 
	}
 
	else if (command[0] == "server") {
 
		Server server(&config);
 
		server.start();
 
		if (server.start() == false) {
 
			std::cerr << "Can't set up server handler.\n";
 
			return 1;
 
		}
 
		while (1) { sleep(10); }
 
	}
 
	else {
 
		if (command.size() < 2) {
 
			std::cout << desc << "\n";
 
			return 11;
spectrum_manager/src/mongoose.c
Show inline comments
 
@@ -15,12 +15,14 @@
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
// THE SOFTWARE.
 
 
#include <netinet/in.h>
 
 
#if defined(_WIN32)
 
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
 
#else
 
#define _XOPEN_SOURCE 600     // For flockfile() on Linux
 
#define _LARGEFILE_SOURCE     // Enable 64-bit file offsets
 
#define __STDC_FORMAT_MACROS  // <inttypes.h> wants this for C++
spectrum_manager/src/server.cpp
Show inline comments
 
@@ -146,13 +146,15 @@ Server::Server(ManagerConfig *config) {
 
	m_config = config;
 
	m_user = CONFIG_STRING(m_config, "service.admin_username");
 
	m_password = CONFIG_STRING(m_config, "service.admin_password");
 
}
 

	
 
Server::~Server() {
 
	mg_stop(ctx);
 
	if (ctx) {
 
		mg_stop(ctx);
 
	}
 
}
 

	
 

	
 
static void *_event_handler(enum mg_event event, struct mg_connection *conn) {
 
	const struct mg_request_info *request_info = mg_get_request_info(conn);
 
	return static_cast<Server *>(request_info->user_data)->event_handler(event, conn);
 
@@ -443,13 +445,18 @@ void *Server::event_handler(enum mg_event event, struct mg_connection *conn) {
 
			serve_stop(conn, request_info);
 
		} else {
 
			// No suitable handler found, mark as not processed. Mongoose will
 
			// try to serve the request.
 
			processed = NULL;
 
		}
 
	} else {
 
	}
 
	else if (event == MG_EVENT_LOG) {
 
		// Called by Mongoose's cry()
 
		std::cerr << "Mongoose error: " << request_info->log_message << "\n";
 
	}
 
	else {
 
		processed = NULL;
 
	}
 

	
 
	return processed;
 
}
 

	
src/CMakeLists.txt
Show inline comments
 
@@ -12,12 +12,13 @@ endif()
 
FILE(GLOB HEADERS ../include/transport/*.h)
 

	
 
if (CPPUNIT_FOUND)
 
	FILE(GLOB SRC_TEST tests/*.cpp)
 

	
 
	ADD_EXECUTABLE(libtransport_test ${SRC_TEST})
 
	set_target_properties(libtransport_test PROPERTIES COMPILE_DEFINITIONS LIBTRANSPORT_TEST=1)
 

	
 
	target_link_libraries(libtransport_test transport ${CPPUNIT_LIBRARY} ${Boost_LIBRARIES})
 
endif()
 

	
 
if (NOT WIN32)
 
include_directories(${POPT_INCLUDE_DIR})
src/buddy.cpp
Show inline comments
 
@@ -20,12 +20,14 @@
 

	
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/BlockPayload.h"
 
#include "transport/usermanager.h"
 
#include "transport/discoitemsresponder.h"
 

	
 
namespace Transport {
 

	
 
Buddy::Buddy(RosterManager *rosterManager, long id, BuddyFlag flags) : m_id(id), m_flags(flags), m_rosterManager(rosterManager),
 
	m_subscription(Ask) {
 
// 	m_rosterManager->setBuddy(this);
 
@@ -103,13 +105,13 @@ Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new)
 
		presence->setType(Swift::Presence::Unavailable);
 
	presence->setShow(s.getType());
 

	
 
	if (presence->getType() != Swift::Presence::Unavailable) {
 
		// caps
 
		
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(m_rosterManager->getUser()->getComponent()->getBuddyCapsInfo())));
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(m_rosterManager->getUser()->getUserManager()->getDiscoResponder()->getBuddyCapsInfo())));
 

	
 
// 		if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) {
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate (getIconHash())));
 
// 		}
 
		if (isBlocked()) {
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Transport::BlockPayload ()));
src/config.cpp
Show inline comments
 
@@ -94,12 +94,16 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
 
		("service.reuse_old_backends", value<bool>()->default_value(true), "True if Spectrum should use old backends which were full in the past.")
 
		("service.idle_reconnect_time", value<int>()->default_value(0), "Time in seconds after which idle users are reconnected to let their backend die.")
 
		("service.memory_collector_time", value<int>()->default_value(0), "Time in seconds after which backend with most memory is set to die.")
 
		("service.more_resources", value<bool>()->default_value(false), "Allow more resources to be connected in server mode at the same time.")
 
		("service.enable_privacy_lists", value<bool>()->default_value(true), "")
 
		("service.enable_xhtml", value<bool>()->default_value(true), "")
 
		("service.max_room_list_size", value<int>()->default_value(100), "")
 
		("service.jid_escaping", value<bool>()->default_value(true), "")
 
		("service.vip_only", value<bool>()->default_value(false), "")
 
		("service.vip_message", value<std::string>()->default_value(""), "")
 
		("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
 
		("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
 
		("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
 
		("identity.type", value<std::string>()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)")
 
		("registration.enable_public_registration", value<bool>()->default_value(true), "True if users should be able to register.")
 
		("registration.language", value<std::string>()->default_value("en"), "Default language for registration form")
 
@@ -120,12 +124,13 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
 
		("database.server", value<std::string>()->default_value("localhost"), "Database server.")
 
		("database.user", value<std::string>()->default_value(""), "Database user.")
 
		("database.password", value<std::string>()->default_value(""), "Database Password.")
 
		("database.port", value<int>()->default_value(0), "Database port.")
 
		("database.prefix", value<std::string>()->default_value(""), "Prefix of tables in database")
 
		("database.encryption_key", value<std::string>()->default_value(""), "Encryption key.")
 
		("database.vip_statement", value<std::string>()->default_value(""), "Encryption key.")
 
		("logging.config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance")
 
		("logging.backend_config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for backends")
 
		("backend.default_avatar", value<std::string>()->default_value(""), "Full path to default avatar")
 
		("backend.avatars_directory", value<std::string>()->default_value(""), "Path to directory with avatars")
 
		("backend.no_vcard_fetch", value<bool>()->default_value(false), "True if VCards for buddies should not be fetched. Only avatars will be forwarded.")
 
		("proxy.server", value<std::string>()->default_value("localhost"), "Proxy IP.")
src/conversation.cpp
Show inline comments
 
@@ -30,12 +30,13 @@ namespace Transport {
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
// 	m_conversationManager->addConversation(this);
 
	m_muc = isMUC;
 
	m_jid = m_conversationManager->getUser()->getJID().toBare();
 
	m_sentInitialPresence = false;
 
}
 

	
 
Conversation::~Conversation() {
 
}
 

	
 
void Conversation::destroyRoom() {
 
@@ -88,13 +89,23 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
 
		if (n.empty()) {
 
			Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
			if (buddy) {
 
				message->setFrom(buddy->getJID());
 
			}
 
			else {
 
				message->setFrom(Swift::JID(Swift::JID::getEscapedNode(m_legacyName), m_conversationManager->getComponent()->getJID().toBare()));
 
				std::string name = m_legacyName;
 
				if (CONFIG_BOOL_DEFAULTED(m_conversationManager->getComponent()->getConfig(), "service.jid_escaping", true)) {
 
					name = Swift::JID::getEscapedNode(m_legacyName);
 
				}
 
				else {
 
					if (name.find_last_of("@") != std::string::npos) {
 
						name.replace(name.find_last_of("@"), 1, "%");
 
					}
 
				}
 

	
 
				message->setFrom(Swift::JID(name, m_conversationManager->getComponent()->getJID().toBare(), "bot"));
 
			}
 
		}
 
		// PM message
 
		else {
 
			if (m_room.empty()) {
 
				message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
@@ -115,12 +126,17 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
 
		if (n.empty()) {
 
			n = " ";
 
		}
 
		BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
			message->setTo(jid);
 
			message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
			// Subject has to be sent after our own presence (the one with code 110)
 
			if (!message->getSubject().empty() && m_sentInitialPresence == false) {
 
				m_subject = message;
 
				return;
 
			}
 
			m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
		}
 
	}
 
}
 

	
 
void Conversation::sendParticipants(const Swift::JID &to) {
 
@@ -156,12 +172,13 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int
 

	
 
	Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
	if (m_nickname == nickname) {
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 110;
 
		p->addStatusCode(c);
 
		m_sentInitialPresence = true;
 
	}
 

	
 
	
 
	Swift::MUCItem item;
 
	
 
	item.affiliation = Swift::MUCOccupant::Member;
 
@@ -204,9 +221,14 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
 
		presence->setTo(jid);
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
	}
 
	if (!newname.empty()) {
 
		handleParticipantChanged(newname, flag, status, statusMessage);
 
	}
 

	
 
	if (m_sentInitialPresence && m_subject) {
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject);
 
		m_subject.reset();
 
	}
 
}
 

	
 
}
src/conversationmanager.cpp
Show inline comments
 
@@ -44,12 +44,21 @@ ConversationManager::~ConversationManager() {
 
		(*m_convs.begin()).second->destroyRoom();
 
		delete (*m_convs.begin()).second;
 
		m_convs.erase(m_convs.begin());
 
	}
 
}
 

	
 
void ConversationManager::deleteAllConversations() {
 
	while(!m_convs.empty()) {
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Removing conversation " << (*m_convs.begin()).first);
 
		(*m_convs.begin()).second->destroyRoom();
 
		delete (*m_convs.begin()).second;
 
		m_convs.erase(m_convs.begin());
 
	}
 
}
 

	
 
Conversation *ConversationManager::getConversation(const std::string &name) {
 
	if (m_convs.find(name) != m_convs.end())
 
		return m_convs[name];
 

	
 
	if (name.find("/") == std::string::npos) {
 
		return NULL;
src/discoinforesponder.cpp
Show inline comments
 
@@ -19,21 +19,25 @@
 
 */
 

	
 
#include "discoinforesponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include <boost/algorithm/string.hpp>
 
#include "Swiften/Disco/DiscoInfoResponder.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Swiften.h"
 
#include "transport/config.h"
 
#include "transport/logging.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
DEFINE_LOGGER(logger, "DiscoInfoResponder");
 

	
 
namespace Transport {
 

	
 
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
 
	m_config = config;
 
	m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"),
 
													CONFIG_STRING(m_config, "identity.category"),
 
@@ -77,25 +81,57 @@ void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
 

	
 
	CapsInfoGenerator caps("spectrum");
 
	m_capsInfo = caps.generateCapsInfo(m_buddyInfo);
 
	onBuddyCapsInfoChanged(m_capsInfo);
 
}
 

	
 
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> info) {
 
	if (!info->getNode().empty()) {
 
		sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
 
		return true;
 
	}
 
void DiscoInfoResponder::addRoom(const std::string &jid, const std::string &name) {
 
	std::string j = jid;
 
	boost::algorithm::to_lower(j);
 
	m_rooms[j] = name;
 
}
 

	
 
void DiscoInfoResponder::clearRooms() {
 
	m_rooms.clear();
 
}
 

	
 
void DiscoInfoResponder::addAdHocCommand(const std::string &node, const std::string &name) {
 
	m_commands[node] = node;
 
}
 

	
 
	// presence for transport
 
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> info) {
 
	// disco#info for transport
 
	if (to.getNode().empty()) {
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
 
		// Adhoc command
 
		if (m_commands.find(info->getNode()) != m_commands.end()) {
 
			boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
 
			res->addFeature("http://jabber.org/protocol/commands");
 
			res->addFeature("jabber:x:data");
 
			res->addIdentity(DiscoInfo::Identity(m_commands[info->getNode()], "automation", "command-node"));
 
			res->setNode(info->getNode());
 
			sendResponse(from, to, id, res);
 
		}
 
		else {
 
			if (!info->getNode().empty()) {
 
				sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
 
				return true;
 
			}
 

	
 
			boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
 
			res->setNode(info->getNode());
 
			sendResponse(from, id, res);
 
		}
 
	}
 
	// disco#info for room
 
	else if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
 
		res->addIdentity(DiscoInfo::Identity(m_rooms[to.toBare().toString()], "conference", "text"));
 
		res->setNode(info->getNode());
 
		sendResponse(from, id, res);
 
		sendResponse(from, to, id, res);
 
	}
 
	// presence for buddy
 
	// disco#info for buddy
 
	else {
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_buddyInfo));
 
		res->setNode(info->getNode());
 
		sendResponse(from, to, id, res);
 
	}
 
	return true;
src/discoinforesponder.h
Show inline comments
 
@@ -35,12 +35,17 @@ class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
 
		DiscoInfoResponder(Swift::IQRouter *router, Config *config);
 
		~DiscoInfoResponder();
 

	
 
		void setTransportFeatures(std::list<std::string> &features);
 
		void setBuddyFeatures(std::list<std::string> &features);
 

	
 
		void addRoom(const std::string &jid, const std::string &name);
 
		void clearRooms();
 

	
 
		void addAdHocCommand(const std::string &node, const std::string &name);
 

	
 
		boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
 

	
 
		Swift::CapsInfo &getBuddyCapsInfo() {
 
				return m_capsInfo;
 
		}
 

	
 
@@ -48,9 +53,11 @@ class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> payload);
 

	
 
		Swift::DiscoInfo m_transportInfo;
 
		Swift::DiscoInfo m_buddyInfo;
 
		Config *m_config;
 
		Swift::CapsInfo m_capsInfo;
 
		std::map<std::string, std::string> m_rooms;
 
		std::map<std::string, std::string> m_commands;
 
};
 

	
 
}
 
\ No newline at end of file
src/discoitemsresponder.cpp
Show inline comments
 
@@ -23,42 +23,65 @@
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Swiften.h"
 
#include "transport/transport.h"
 
#include "transport/logging.h"
 
#include "discoinforesponder.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "DiscoItemsResponder");
 

	
 
DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder<DiscoItems>(component->getIQRouter()) {
 
	m_component = component;
 
	m_commands = boost::shared_ptr<DiscoItems>(new DiscoItems());
 
	m_commands->setNode("http://jabber.org/protocol/commands");
 

	
 
	m_rooms = boost::shared_ptr<DiscoItems>(new DiscoItems());
 
	m_discoInfoResponder = new DiscoInfoResponder(component->getIQRouter(), component->getConfig());
 
	m_discoInfoResponder->start();
 
}
 

	
 
DiscoItemsResponder::~DiscoItemsResponder() {
 
	>
 
	delete m_discoInfoResponder;
 
}
 

	
 
void DiscoItemsResponder::addAdHocCommand(const std::string &node, const std::string &name) {
 
	m_commands->addItem(DiscoItems::Item(name, m_component->getJID(), node));
 
	m_discoInfoResponder->addAdHocCommand(node, name);
 
}
 

	
 
void DiscoItemsResponder::addRoom(const std::string &node, const std::string &name) {
 
	if (m_rooms->getItems().size() > CONFIG_INT(m_component->getConfig(), "service.max_room_list_size")) {
 
		return;
 
	}
 
	m_rooms->addItem(DiscoItems::Item(name, node));
 
	m_discoInfoResponder->addRoom(node, name);
 
}
 

	
 
void DiscoItemsResponder::clearRooms() {
 
	m_rooms = boost::shared_ptr<DiscoItems>(new DiscoItems());
 
	m_discoInfoResponder->clearRooms();
 
}
 

	
 
Swift::CapsInfo &DiscoItemsResponder::getBuddyCapsInfo() {
 
	return m_discoInfoResponder->getBuddyCapsInfo();
 
}
 

	
 

	
 
bool DiscoItemsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoItems> info) {
 
	LOG4CXX_INFO(logger, "get request received with node " << info->getNode());
 
	if (info->getNode() == "http://jabber.org/protocol/commands") {
 
		sendResponse(from, id, m_commands);
 
	}
 
	else if (to.getNode().empty()) {
 
		sendResponse(from, id, boost::shared_ptr<DiscoItems>(new DiscoItems()));
 
		sendResponse(from, id, m_rooms);
 
	}
 
	else {
 
		sendResponse(from, id, boost::shared_ptr<DiscoItems>(new DiscoItems()));
 
	}
 
	return true;
 
}
src/logging.cpp
Show inline comments
 
@@ -17,23 +17,25 @@
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/logging.h"
 
#include "transport/config.h"
 
#include "transport/util.h"
 
#include <boost/foreach.hpp>
 
#include <iostream>
 
#include <iterator>
 
#include <algorithm>
 

	
 

	
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 

	
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include <sys/stat.h>
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#else
 
#include <windows.h>
 
@@ -133,41 +135,48 @@ static void initLogging(Config *config, std::string key) {
 
			if (boost::ends_with(prop, ".File")) {
 
				log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
 
				boost::replace_all(dir, "${jid}", jid);
 
				break;
 
			}
 
		}
 

	
 
		mode_t old_cmask;
 
		if (!dir.empty()) {
 
			// create directories
 
#ifndef WIN32
 
			old_cmask = umask(0007);
 
#endif
 
			try {
 
				boost::filesystem::create_directories(
 
					boost::filesystem::path(dir).parent_path().string()
 
				);
 
				Transport::Util::createDirectories(config, boost::filesystem::path(dir).parent_path());
 
			}
 
			catch (...) {
 
				std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
 
			catch (const boost::filesystem::filesystem_error &e) {
 
				std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ": " << e.what() << ".\n";
 
			}
 
		}
 

	
 
#ifndef WIN32
 
			if (!CONFIG_STRING(config, "service.group").empty() && !CONFIG_STRING(config, "service.user").empty()) {
 
				struct group *gr;
 
				if ((gr = getgrnam(CONFIG_STRING(config, "service.group").c_str())) == NULL) {
 
					std::cerr << "Invalid service.group name " << CONFIG_STRING(config, "service.group") << "\n";
 
				}
 
				struct passwd *pw;
 
				if ((pw = getpwnam(CONFIG_STRING(config, "service.user").c_str())) == NULL) {
 
					std::cerr << "Invalid service.user name " << CONFIG_STRING(config, "service.user") << "\n";
 
				}
 
				chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
 
			}
 
		log4cxx::PropertyConfigurator::configure(p);
 

	
 
#endif
 
		// Change owner of main log file
 
#ifndef WIN32
 
	if (!CONFIG_STRING(config, "service.group").empty() && !CONFIG_STRING(config, "service.user").empty()) {
 
		struct group *gr;
 
		if ((gr = getgrnam(CONFIG_STRING(config, "service.group").c_str())) == NULL) {
 
			std::cerr << "Invalid service.group name " << CONFIG_STRING(config, "service.group") << "\n";
 
		}
 
		struct passwd *pw;
 
		if ((pw = getpwnam(CONFIG_STRING(config, "service.user").c_str())) == NULL) {
 
			std::cerr << "Invalid service.user name " << CONFIG_STRING(config, "service.user") << "\n";
 
		}
 
		chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
 
	}
 
#endif
 

	
 
		log4cxx::PropertyConfigurator::configure(p);
 
#ifndef WIN32
 
		if (!dir.empty()) {
 
			umask(old_cmask);
 
		}
 
#endif
 
	}
 
}
 

	
 
void initBackendLogging(Config *config) {
 
	initLogging(config, "logging.backend_config");
 

	
src/mysqlbackend.cpp
Show inline comments
 
@@ -418,13 +418,13 @@ bool MySQLBackend::exec(const std::string &query) {
 
	return true;
 
}
 

	
 
void MySQLBackend::setUser(const UserInfo &user) {
 
	std::string encrypted = user.password;
 
	if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
		encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
		encrypted = StorageBackend::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
	}
 
	*m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.uin << encrypted;
 
	EXEC(m_setUser, setUser(user));
 
}
 

	
 
bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
 
@@ -436,13 +436,30 @@ bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
 
	int ret = false;
 
	while (m_getUser->fetch() == 0) {
 
		ret = true;
 
		*m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip;
 

	
 
		if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
			user.password = Util::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key"));
 
			user.password = StorageBackend::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key"));
 
		}
 
	}
 

	
 
	if (!CONFIG_STRING(m_config, "database.vip_statement").empty()) {
 
		std::string query = CONFIG_STRING(m_config, "database.vip_statement");
 
		boost::replace_all(query, "$barejid", barejid);
 
		LOG4CXX_INFO(logger, "Executing '" << query << "' to find out if user " << barejid << " is VIP");
 
		if (exec(query)) {
 
			MYSQL_RES *result = mysql_store_result(&m_conn);
 
			if (result && mysql_num_rows(result) > 0) {
 
				LOG4CXX_INFO(logger, "User " << barejid << " is VIP");
 
				user.vip = 1;
 
			}
 
			else {
 
				LOG4CXX_INFO(logger, "User " << barejid << " is not VIP");
 
				user.vip = 0;
 
			}
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
@@ -464,13 +481,13 @@ bool MySQLBackend::getOnlineUsers(std::vector<std::string> &users) {
 

	
 
	return true;
 
}
 

	
 
long MySQLBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
	std::string groups = Util::serializeGroups(buddyInfo.groups);
 
	std::string groups = StorageBackend::serializeGroups(buddyInfo.groups);
 
	*m_addBuddy << userId << buddyInfo.legacyName << buddyInfo.subscription;
 
	*m_addBuddy << groups;
 
	*m_addBuddy << buddyInfo.alias << buddyInfo.flags;
 

	
 
	EXEC(m_addBuddy, addBuddy(userId, buddyInfo));
 

	
 
@@ -514,13 +531,13 @@ void MySQLBackend::removeBuddy(long id) {
 
	if (!exec_ok)
 
		return;
 
}
 

	
 
void MySQLBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?"
 
	std::string groups = Util::serializeGroups(buddyInfo.groups);
 
	std::string groups = StorageBackend::serializeGroups(buddyInfo.groups);
 
	*m_updateBuddy << groups;
 
	*m_updateBuddy << buddyInfo.alias << buddyInfo.flags << buddyInfo.subscription;
 
	*m_updateBuddy << userId << buddyInfo.legacyName;
 

	
 
	EXEC(m_updateBuddy, updateBuddy(userId, buddyInfo));
 
}
 
@@ -544,13 +561,13 @@ bool MySQLBackend::getBuddies(long id, std::list<BuddyInfo> &roster) {
 
		BuddyInfo b;
 

	
 
		std::string group;
 
		*m_getBuddies >> b.id >> b.legacyName >> b.subscription >> b.alias >> group >> b.flags;
 

	
 
		if (!group.empty()) {
 
			b.groups = Util::deserializeGroups(group);
 
			b.groups = StorageBackend::deserializeGroups(group);
 
		}
 

	
 
		roster.push_back(b);
 
	}
 

	
 
	EXEC(m_getBuddiesSettings, getBuddies(id, roster));
src/networkpluginserver.cpp
Show inline comments
 
@@ -41,12 +41,13 @@
 
#include "Swiften/Elements/AttentionPayload.h"
 
#include "Swiften/Elements/XHTMLIMPayload.h"
 
#include "Swiften/Elements/InvisiblePayload.h"
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 
#include "transport/protocol.pb.h"
 
#include "transport/util.h"
 
#include "transport/discoitemsresponder.h"
 

	
 
#include "utf8.h"
 

	
 
#include <Swiften/FileTransfer/ReadBytestream.h>
 
#include <Swiften/Elements/StreamInitiationFileInfo.h>
 

	
 
@@ -89,14 +90,14 @@ class NetworkFactory : public Factory {
 
			m_nps = nps;
 
		}
 

	
 
		virtual ~NetworkFactory() {}
 

	
 
		// Creates new conversation (NetworkConversation in this case)
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			NetworkConversation *nc = new NetworkConversation(conversationManager, legacyName);
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMuc) {
 
			NetworkConversation *nc = new NetworkConversation(conversationManager, legacyName, isMuc);
 
			nc->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, m_nps, _1, _2));
 
			return nc;
 
		}
 

	
 
		// Creates new LocalBuddy
 
		Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) {
 
@@ -181,12 +182,17 @@ static unsigned long exec_(const std::string& exePath, const char *host, const c
 
	poptParseArgvString(p, &argc, (const char ***) &argv);
 

	
 
	// fork and exec
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		setsid();
 
		// close all files
 
		int maxfd=sysconf(_SC_OPEN_MAX);
 
		for(int fd=3; fd<maxfd; fd++) {
 
			close(fd);
 
		}
 
		// child process
 
		errno = 0;
 
		int ret = execv(argv[0], argv);
 
		if (ret == -1) {
 
			exit(errno);
 
		}
 
@@ -228,31 +234,34 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa
 
		buddy->setAlias(payload.alias());
 
	}
 

	
 
	// Change groups if it's not empty. The same as above...
 
	std::vector<std::string> groups;
 
	for (int i = 0; i < payload.group_size(); i++) {
 
		groups.push_back(payload.group(i));
 
		std::string group = payload.group(i);
 
		utf8::replace_invalid(payload.group(i).begin(), payload.group(i).end(), group.begin(), '_');
 
		groups.push_back(group);
 
	}
 
	if (!groups.empty()) {
 
		buddy->setGroups(groups);
 
	}
 

	
 
	buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
	buddy->setIconHash(payload.iconhash());
 
	buddy->setBlocked(payload.blocked());
 
}
 

	
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager) {
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder) {
 
	m_ftManager = ftManager;
 
	m_userManager = userManager;
 
	m_config = config;
 
	m_component = component;
 
	m_isNextLongRun = false;
 
	m_adminInterface = NULL;
 
	m_startingBackend = false;
 
	m_discoItemsResponder = discoItemsResponder;
 
	m_component->m_factory = new NetworkFactory(this);
 
	m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
 
	m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
 

	
 
	m_pingTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(20000);
 
	m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this));
 
@@ -278,12 +287,36 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
	m_blockResponder = new BlockResponder(component->getIQRouter(), userManager);
 
	m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1));
 
	m_blockResponder->start();
 

	
 
	m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")));
 
	m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
	for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
 
		LOG4CXX_INFO(logger, "Stopping backend " << *it);
 
		std::string message;
 
		pbnetwork::WrapperMessage wrap;
 
		wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT);
 
		wrap.SerializeToString(&message);
 

	
 
		Backend *c = (Backend *) *it;
 
		send(c->connection, message);
 
	}
 

	
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
	delete m_blockResponder;
 
}
 

	
 
void NetworkPluginServer::start() {
 
	m_server->start();
 

	
 
	LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port"));
 

	
 
	while (true) {
 
		unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getCommandLineArgs().c_str());
 
@@ -296,13 +329,19 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
		pid_t result;
 
		int status;
 
		result = waitpid(-1, &status, WNOHANG);
 
		if (result != 0) {
 
			if (WIFEXITED(status)) {
 
				if (WEXITSTATUS(status) != 0) {
 
					LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status) << ", possible error: " << strerror(WEXITSTATUS(status)));
 
					if (status == 254) {
 
						LOG4CXX_ERROR(logger, "Backend can not be started, because it needs database to store data, but the database backend is not configured.");
 
					}
 
					else {
 
						LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status) << ", possible error: " << strerror(WEXITSTATUS(status)));
 
					}
 
					LOG4CXX_ERROR(logger, "Check backend log for more details");
 
					continue;
 
				}
 
			}
 
			else {
 
				LOG4CXX_ERROR(logger, "Backend can not be started");
 
				continue;
 
@@ -311,34 +350,12 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 

	
 
		signal(SIGCHLD, SigCatcher);
 
#endif
 
		// quit the while loop
 
		break;
 
	}
 

	
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
	for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
 
		LOG4CXX_INFO(logger, "Stopping backend " << *it);
 
		std::string message;
 
		pbnetwork::WrapperMessage wrap;
 
		wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT);
 
		wrap.SerializeToString(&message);
 

	
 
		Backend *c = (Backend *) *it;
 
		send(c->connection, message);
 
	}
 

	
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
	delete m_blockResponder;
 
}
 

	
 
void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Connection> c) {
 
	// Create new Backend instance
 
	Backend *client = new Backend;
 
	client->pongReceived = -1;
 
@@ -472,17 +489,20 @@ void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) {
 

	
 
	// Create subscribe presence and forward it to XMPP side
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo(user->getJID());
 
	std::string name = payload.buddyname();
 

	
 
	name = Swift::JID::getEscapedNode(name);
 

	
 
// 	if (name.find_last_of("@") != std::string::npos) { // OK when commented
 
// 		name.replace(name.find_last_of("@"), 1, "%"); // OK when commented
 
// 	}
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) {
 
		name = Swift::JID::getEscapedNode(name);
 
	}
 
	else {
 
		if (name.find_last_of("@") != std::string::npos) {
 
			name.replace(name.find_last_of("@"), 1, "%");
 
		}
 
	}
 

	
 
	response->setFrom(Swift::JID(name, m_component->getJID().toString()));
 
	response->setType(Swift::Presence::Subscribe);
 
	m_component->getStanzaChannel()->sendPresence(response);
 
}
 

	
 
@@ -525,21 +545,31 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
 
	LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
 
	if (buddy) {
 
		handleBuddyPayload(buddy, payload);
 
		buddy->handleBuddyChanged();
 
	}
 
	else {
 
		if (payload.buddyname() == user->getUserInfo().uin) {
 
			return;
 
		}
 

	
 
		std::vector<std::string> groups;
 
		for (int i = 0; i < payload.group_size(); i++) {
 
			groups.push_back(payload.group(i));
 
		}
 
		buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_JID_ESCAPING);
 
		if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) {
 
			buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_JID_ESCAPING);
 
		}
 
		else {
 
			buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_NO_FLAG);
 
		}
 
		if (!buddy->isValid()) {
 
			delete buddy;
 
			return;
 
		}
 

	
 
		buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
		buddy->setIconHash(payload.iconhash());
 
		buddy->setBlocked(payload.blocked());
 
		user->getRosterManager()->setBuddy(buddy);
 
	}
 
}
 
@@ -621,14 +651,27 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 

	
 
	// Add xhtml-im payload.
 
	if (CONFIG_BOOL(m_config, "service.enable_xhtml") && !payload.xhtml().empty()) {
 
		msg->addPayload(boost::make_shared<Swift::XHTMLIMPayload>(payload.xhtml()));
 
	}
 

	
 
	// Create new Conversation if it does not exist
 
	if (!payload.timestamp().empty()) {
 
		boost::posix_time::ptime timestamp = boost::posix_time::from_iso_string(payload.timestamp());
 
		msg->addPayload(boost::make_shared<Swift::Delay>(timestamp));
 
	}
 

	
 
	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 

	
 
	// We can't create Conversation for payload with nickname, because this means the message is from room,
 
	// but this user is not in any room, so it's OK to just reject this message
 
	if (!conv && !payload.nickname().empty()) {
 
		return;
 
	}
 

	
 
	// Create new Conversation if it does not exist
 
	if (!conv) {
 
		conv = new NetworkConversation(user->getConversationManager(), payload.buddyname());
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	}
 

	
 
@@ -743,12 +786,17 @@ void NetworkPluginServer::handleFTDataPayload(Backend *b, const std::string &dat
 
	}
 

	
 
// 	User *user = m_userManager->getUser(payload.username());
 
// 	if (!user)
 
// 		return;
 

	
 
	if (m_filetransfers.find(payload.ftid()) == m_filetransfers.end()) {
 
		LOG4CXX_ERROR(logger, "Uknown filetransfer with id " << payload.ftid());
 
		return;
 
	}
 

	
 
	FileTransferManager::Transfer &transfer = m_filetransfers[payload.ftid()];
 
	MemoryReadBytestream *bytestream = (MemoryReadBytestream *) transfer.readByteStream.get();
 

	
 
	if (bytestream->appendData(payload.data()) > 5000000) {
 
		pbnetwork::FileTransferData f;
 
		f.set_ftid(payload.ftid());
 
@@ -845,12 +893,25 @@ void NetworkPluginServer::handleBackendConfigPayload(const std::string &data) {
 
		return;
 
	}
 

	
 
	m_config->updateBackendConfig(payload.config());
 
}
 

	
 
void NetworkPluginServer::handleRoomListPayload(const std::string &data) {
 
	pbnetwork::RoomList payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	m_discoItemsResponder->clearRooms();
 
	for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) {
 
		m_discoItemsResponder->addRoom(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
 
	}
 
}
 

	
 
void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr<Swift::SafeByteArray> data) {
 
	// Append data to buffer
 
	c->data.insert(c->data.end(), data->begin(), data->end());
 

	
 
	// Parse data while there are some
 
	while (c->data.size() != 0) {
 
@@ -942,12 +1003,15 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr<Swift::Sa
 
			case pbnetwork::WrapperMessage_Type_TYPE_QUERY:
 
				handleQueryPayload(c, wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BACKEND_CONFIG:
 
				handleBackendConfigPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_ROOM_LIST:
 
				handleRoomListPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
@@ -1186,18 +1250,12 @@ void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, co
 
 
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 

	
 
	NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
 
	user->getConversationManager()->addConversation(conv);
 
	conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	conv->setNickname(nickname);
 
	conv->addJID(who);
 
}
 

	
 
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
src/pqxxbackend.cpp
Show inline comments
 
@@ -154,13 +154,13 @@ bool PQXXBackend::exec(pqxx::nontransaction &txn, const std::string &query, bool
 
	return true;
 
}
 

	
 
void PQXXBackend::setUser(const UserInfo &user) {
 
	std::string encrypted = user.password;
 
	if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
		encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
		encrypted = StorageBackend::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
	}
 
	try {
 
		pqxx::nontransaction txn(*m_conn);
 
		txn.exec("INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES "
 
			+ "(" + quote(txn, user.jid) + ","
 
			+ quote(txn, user.uin) + ","
 
@@ -233,13 +233,13 @@ long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
	try {
 
		pqxx::nontransaction txn(*m_conn);
 
		pqxx::result r = txn.exec("INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES "
 
			+ "(" + pqxx::to_string(userId) + ","
 
			+ quote(txn, buddyInfo.legacyName) + ","
 
			+ quote(txn, buddyInfo.subscription) + ","
 
			+ quote(txn, Util::serializeGroups(buddyInfo.groups)) + ","
 
			+ quote(txn, StorageBackend::serializeGroups(buddyInfo.groups)) + ","
 
			+ quote(txn, buddyInfo.alias) + ","
 
			+ pqxx::to_string(buddyInfo.flags) + ") RETURNING id");
 

	
 
		long id = r[0][0].as<long>();
 

	
 
		r = txn.exec("UPDATE " + m_prefix + "buddies_settings SET var = " + quote(txn, buddyInfo.settings.find("icon_hash")->first) + ", type = " + pqxx::to_string((int)TYPE_STRING) + ", value = " + quote(txn, buddyInfo.settings.find("icon_hash")->second.s) + " WHERE user_id = " + pqxx::to_string(userId) + " AND buddy_id = " + pqxx::to_string(id));
 
@@ -260,13 +260,13 @@ long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
	}
 
}
 

	
 
void PQXXBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
	try {
 
		pqxx::nontransaction txn(*m_conn);
 
		txn.exec("UPDATE " + m_prefix + "buddies SET groups=" + quote(txn, Util::serializeGroups(buddyInfo.groups)) + ", nickname=" + quote(txn, buddyInfo.alias) + ", flags=" + pqxx::to_string(buddyInfo.flags) + ", subscription=" + quote(txn, buddyInfo.subscription) + " WHERE user_id=" + pqxx::to_string(userId) + " AND uin=" + quote(txn, buddyInfo.legacyName));
 
		txn.exec("UPDATE " + m_prefix + "buddies SET groups=" + quote(txn, StorageBackend::serializeGroups(buddyInfo.groups)) + ", nickname=" + quote(txn, buddyInfo.alias) + ", flags=" + pqxx::to_string(buddyInfo.flags) + ", subscription=" + quote(txn, buddyInfo.subscription) + " WHERE user_id=" + pqxx::to_string(userId) + " AND uin=" + quote(txn, buddyInfo.legacyName));
 
	}
 
	catch (std::exception& e) {
 
		LOG4CXX_ERROR(logger, e.what());
 
	}
 
}
 

	
 
@@ -284,13 +284,13 @@ bool PQXXBackend::getBuddies(long id, std::list<BuddyInfo> &roster) {
 
			b.subscription = r[0][2].as<std::string>();
 
			b.alias = r[0][3].as<std::string>();
 
			group = r[0][4].as<std::string>();
 
			b.flags = r[0][5].as<long>();
 

	
 
			if (!group.empty()) {
 
				b.groups = Util::deserializeGroups(group);
 
				b.groups = StorageBackend::deserializeGroups(group);
 
			}
 

	
 
			roster.push_back(b);
 
		}
 

	
 

	
src/rostermanager.cpp
Show inline comments
 
@@ -178,13 +178,13 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
		request->send();
 
		m_requests.push_back(request);
 
	}
 

	
 
	if (buddy->getSubscription() != Buddy::Both) {
 
		buddy->setSubscription(Buddy::Both);
 
		handleBuddyChanged(buddy);
 
		storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::sendBuddyUnsubscribePresence(Buddy *buddy) {
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo(m_user->getJID());
 
@@ -443,35 +443,37 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
					if (currentPresence) {
 
						currentPresence->setTo(presence->getFrom());
 
						m_component->getStanzaChannel()->sendPresence(currentPresence);
 
					}
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
						storeBuddy(buddy);
 
					}
 
					break;
 
				// remove buddy
 
				case Swift::Presence::Unsubscribe:
 
					response->setType(Swift::Presence::Unsubscribed);
 
					onBuddyRemoved(buddy);
 
					removeBuddy(buddy->getName());
 
					buddy = NULL;
 
					break;
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
 
					response->setType(Swift::Presence::Unsubscribe);
 
					// We set both here, because this Unsubscribed can be response to
 
					// subscribe presence and we don't want that unsubscribe presence
 
					// to be send later again
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
						storeBuddy(buddy);
 
					}
 
					break;
 
				case Swift::Presence::Subscribed:
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
						storeBuddy(buddy);
 
					}
 
					return;
 
				default:
 
					return;
 
			}
 
		}
 
@@ -488,16 +490,25 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 

	
 
					buddy = m_component->getFactory()->createBuddy(this, buddyInfo);
 
					setBuddy(buddy);
 
					onBuddyAdded(buddy);
 
					response->setType(Swift::Presence::Subscribed);
 
					break;
 
				// buddy is already there, so nothing to do, just answer
 
				case Swift::Presence::Unsubscribe:
 
					buddyInfo.id = -1;
 
					buddyInfo.alias = "";
 
					buddyInfo.legacyName = Buddy::JIDToLegacyName(presence->getTo());
 
					buddyInfo.subscription = "both";
 
					buddyInfo.flags = Buddy::buddyFlagsFromJID(presence->getTo());
 

	
 
					response->setType(Swift::Presence::Unsubscribed);
 
// 					onBuddyRemoved(buddy);
 
					
 
					buddy = m_component->getFactory()->createBuddy(this, buddyInfo);
 
					onBuddyRemoved(buddy);
 
					delete buddy;
 
					buddy = NULL;
 
					break;
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
 
					response->setType(Swift::Presence::Unsubscribe);
 
					break;
 
				// just send response
src/rosterresponder.cpp
Show inline comments
 
@@ -71,12 +71,16 @@ bool RosterResponder::handleSetRequest(const Swift::JID& from, const Swift::JID&
 
		LOG4CXX_WARN(logger, from.toBare().toString() << ": Roster push with no item");
 
		return true;
 
	}
 

	
 
	Swift::RosterItemPayload item = payload->getItems()[0];
 

	
 
	if (item.getJID().getNode().empty()) {
 
		return true;
 
	}
 

	
 
	Buddy *buddy = user->getRosterManager()->getBuddy(Buddy::JIDToLegacyName(item.getJID()));
 
	if (buddy) {
 
		if (item.getSubscription() == Swift::RosterItemPayload::Remove) {
 
			LOG4CXX_INFO(logger, from.toBare().toString() << ": Removing buddy " << buddy->getName());
 
			onBuddyRemoved(buddy);
 

	
src/sqlite3backend.cpp
Show inline comments
 
@@ -284,13 +284,13 @@ bool SQLite3Backend::getOnlineUsers(std::vector<std::string> &users) {
 
long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
	BEGIN(m_addBuddy);
 
	BIND_INT(m_addBuddy, userId);
 
	BIND_STR(m_addBuddy, buddyInfo.legacyName);
 
	BIND_STR(m_addBuddy, buddyInfo.subscription);
 
	BIND_STR(m_addBuddy, Util::serializeGroups(buddyInfo.groups));
 
	BIND_STR(m_addBuddy, StorageBackend::serializeGroups(buddyInfo.groups));
 
	BIND_STR(m_addBuddy, buddyInfo.alias);
 
	BIND_INT(m_addBuddy, buddyInfo.flags);
 

	
 
	if(sqlite3_step(m_addBuddy) != SQLITE_DONE) {
 
		LOG4CXX_ERROR(logger, "addBuddy query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
 
		return -1;
 
@@ -310,13 +310,13 @@ long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
	return id;
 
}
 

	
 
void SQLite3Backend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?
 
	BEGIN(m_updateBuddy);
 
	BIND_STR(m_updateBuddy, Util::serializeGroups(buddyInfo.groups));
 
	BIND_STR(m_updateBuddy, StorageBackend::serializeGroups(buddyInfo.groups));
 
	BIND_STR(m_updateBuddy, buddyInfo.alias);
 
	BIND_INT(m_updateBuddy, buddyInfo.flags);
 
	BIND_STR(m_updateBuddy, buddyInfo.subscription);
 
	BIND_INT(m_updateBuddy, userId);
 
	BIND_STR(m_updateBuddy, buddyInfo.legacyName);
 

	
 
@@ -352,13 +352,13 @@ bool SQLite3Backend::getBuddies(long id, std::list<BuddyInfo> &roster) {
 
		RESET_GET_COUNTER(m_getBuddies);
 
		b.id = GET_INT(m_getBuddies);
 
		b.legacyName = GET_STR(m_getBuddies);
 
		b.subscription = GET_STR(m_getBuddies);
 
		b.alias = GET_STR(m_getBuddies);
 
		std::string groups = GET_STR(m_getBuddies);
 
		b.groups = Util::deserializeGroups(groups);
 
		b.groups = StorageBackend::deserializeGroups(groups);
 
		b.flags = GET_INT(m_getBuddies);
 

	
 
		if (buddy_id == b.id) {
 
			std::cout << "Adding buddy info " << key << "\n";
 
			b.settings[key] = var;
 
			buddy_id = -1;
src/storagebackend.cpp
Show inline comments
 
@@ -2,19 +2,20 @@
 
#include "transport/config.h"
 

	
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/pqxxbackend.h"
 

	
 
#include "Swiften/Swiften.h"
 

	
 
namespace Transport {
 

	
 
StorageBackend *StorageBackend::createBackend(Config *config, std::string &error) {
 
	StorageBackend *storageBackend = NULL;
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(config, "database.type") == "sqlite3" ||
 
		(CONFIG_STRING(config, "database.type") == "none" && !CONFIG_BOOL(config, "service.server_mode"))) {
 
	if (CONFIG_STRING(config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(config);
 
	}
 
#else
 
	if (CONFIG_STRING(config, "database.type") == "sqlite3") {
 
		error = "Libtransport is not compiled with sqlite3 backend support.";
 
	}
 
@@ -45,7 +46,59 @@ StorageBackend *StorageBackend::createBackend(Config *config, std::string &error
 
		error = "Unknown storage backend " + CONFIG_STRING(config, "database.type");
 
	}
 

	
 
	return storageBackend;
 
}
 

	
 
std::string StorageBackend::encryptPassword(const std::string &password, const std::string &key) {
 
	std::string encrypted;
 
	encrypted.resize(password.size());
 
	for (int i = 0; i < password.size(); i++) {
 
		char c = password[i];
 
		char keychar = key[i % key.size()];
 
		c += keychar;
 
		encrypted[i] = c;
 
	}
 

	
 
	encrypted = Swift::Base64::encode(Swift::createByteArray(encrypted));
 
	return encrypted;
 
}
 

	
 
std::string StorageBackend::decryptPassword(std::string &encrypted, const std::string &key) {
 
	encrypted = Swift::byteArrayToString(Swift::Base64::decode(encrypted));
 
	std::string password;
 
	password.resize(encrypted.size());
 
	for (int i = 0; i < encrypted.size(); i++) {
 
		char c = encrypted[i];
 
		char keychar = key[i % key.size()];
 
		c -= keychar;
 
		password[i] = c;
 
	}
 

	
 
	return password;
 
}
 

	
 
std::string StorageBackend::serializeGroups(const std::vector<std::string> &groups) {
 
	std::string ret;
 
	BOOST_FOREACH(const std::string &group, groups) {
 
		ret += group + "\n";
 
	}
 
	if (!ret.empty()) {
 
		ret.erase(ret.end() - 1);
 
	}
 
	return ret;
 
}
 

	
 
std::vector<std::string> StorageBackend::deserializeGroups(std::string &groups) {
 
	std::vector<std::string> ret;
 
	if (groups.empty()) {
 
		return ret;
 
	}
 

	
 
	boost::split(ret, groups, boost::is_any_of("\n"));
 
	if (ret.back().empty()) {
 
		ret.erase(ret.end() - 1);
 
	}
 
	return ret;
 
}
 

	
 
}
src/tests/basictest.cpp
Show inline comments
 
@@ -54,20 +54,20 @@ void BasicTest::setMeUp (void) {
 

	
 
	userRegistry = new UserRegistry(cfg, factories);
 

	
 
	component = new Component(loop, factories, cfg, factory, userRegistry);
 
	component->start();
 

	
 
	userManager = new UserManager(component, userRegistry, storage);
 
	itemsResponder = new DiscoItemsResponder(component);
 
	itemsResponder->start();
 

	
 
	userManager = new UserManager(component, userRegistry, itemsResponder, storage);
 

	
 
	userRegistration = new UserRegistration(component, userManager, storage);
 
	userRegistration->start();
 

	
 
	itemsResponder = new DiscoItemsResponder(component);
 
	itemsResponder->start();
 

	
 
	payloadSerializers = new Swift::FullPayloadSerializerCollection();
 
	payloadParserFactories = new Swift::FullPayloadParserFactoryCollection();
 

	
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
@@ -199,12 +199,13 @@ void BasicTest::connectUser() {
 

	
 
	user->setConnected(true);
 
	CPPUNIT_ASSERT(user->isConnected() == true);
 

	
 
	CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
	CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 

	
 
	received.clear();
 
	receivedData.clear();
 
}
 

	
 
void BasicTest::connectSecondResource() {
 
	serverFromClientSession2 = boost::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
@@ -233,12 +234,13 @@ void BasicTest::connectSecondResource() {
 
	CPPUNIT_ASSERT_EQUAL(2, user->getResourceCount());
 

	
 
	CPPUNIT_ASSERT(getStanza(received2[1])->getPayload<Swift::DiscoInfo>());
 
}
 

	
 
void BasicTest::disconnectUser() {
 
	received.clear();
 
	userManager->disconnectUser("user@localhost");
 
	dynamic_cast<Swift::DummyTimerFactory *>(factories->getTimerFactory())->setTime(10);
 
	loop->processEvents();
 

	
 
	CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
	CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
src/tests/basictest.h
Show inline comments
 
@@ -64,14 +64,14 @@ class TestingConversation : public Conversation {
 
class TestingFactory : public Factory {
 
	public:
 
		TestingFactory() {
 
		}
 

	
 
		// Creates new conversation (NetworkConversation in this case)
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			TestingConversation *nc = new TestingConversation(conversationManager, legacyName);
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMuc = false) {
 
			TestingConversation *nc = new TestingConversation(conversationManager, legacyName, isMuc);
 
			nc->onMessageToSend.connect(boost::bind(&TestingFactory::handleMessageToSend, this, _1, _2));
 
			return nc;
 
		}
 

	
 
		void handleMessageToSend(TestingConversation *_conv, boost::shared_ptr<Swift::Message> &_msg) {
 
			onMessageToSend(_conv, _msg);
 
@@ -222,12 +222,13 @@ class BasicTest : public Swift::XMPPParserClient {
 
	void addUser() {
 
		UserInfo user;
 
		user.id = 1;
 
		user.jid = "user@localhost";
 
		user.uin = "legacyname";
 
		user.password = "password";
 
		user.vip = 0;
 
		storage->setUser(user);
 
	}
 

	
 
	void connectUser();
 
	void connectSecondResource();
 
	void disconnectUser();
src/tests/conversationmanager.cpp
Show inline comments
 
@@ -91,32 +91,41 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 

	
 
		received.clear();
 
	}
 

	
 
	void handleSubjectMessages() {
 
		User *user = userManager->getUser("user@localhost");
 

	
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1");
 
		user->getConversationManager()->addConversation(conv);
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
 
		
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 
		conv->setNickname("nickname");
 
		conv->addJID("user@localhost/resource");
 

	
 
		boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
		msg->setSubject("subject");
 
		msg->setType(Swift::Message::Groupchat);
 

	
 
		// Forward it
 
		conv->handleMessage(msg);
 
		loop->processEvents();
 

	
 
		// No response, because presence with code 110 has not been sent yet and we must not send
 
		// subject before this one.
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 

	
 
		// this user presence - status code 110
 
		conv->handleParticipantChanged("nickname", 1, Swift::StatusShow::Away, "my status message");
 
		loop->processEvents();
 
		
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getSubject());
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[1])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getSubject());
 
		received.clear();
 

	
 
		// send response
 
		msg->setFrom("user@localhost/resource");
 
		msg->setTo("buddy1@localhost/bot");
 
		msg->setTo("#room@localhost");
 
		injectMessage(msg);
 
		loop->processEvents();
 
		
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
		CPPUNIT_ASSERT(m_msg);
 
		CPPUNIT_ASSERT_EQUAL(std::string("subject"), m_msg->getSubject());
 
@@ -124,41 +133,41 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 
		received.clear();
 
	}
 

	
 
	void handleNormalMessages() {
 
		User *user = userManager->getUser("user@localhost");
 

	
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1");
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1@test");
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 

	
 
		boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
		msg->setBody("hi there!");
 
		msg->setBody("hi there<>!");
 

	
 
		// Forward it
 
		conv->handleMessage(msg);
 
		loop->processEvents();
 
		
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("hi there<>!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		
 
		received.clear();
 

	
 
		// send response
 
		msg->setFrom("user@localhost/resource");
 
		msg->setTo("buddy1@localhost/bot");
 
		msg->setBody("response!");
 
		msg->setTo("buddy1\\40test@localhost/bot");
 
		msg->setBody("response<>!");
 
		injectMessage(msg);
 
		loop->processEvents();
 
		
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
		CPPUNIT_ASSERT(m_msg);
 
		CPPUNIT_ASSERT_EQUAL(std::string("response!"), m_msg->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("response<>!"), m_msg->getBody());
 

	
 
		// send another message from legacy network, should be sent to user@localhost/resource now
 
		boost::shared_ptr<Swift::Message> msg2(new Swift::Message());
 
		msg2->setBody("hi there!");
 

	
 
		// Forward it
 
@@ -166,26 +175,34 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		
 
		received.clear();
 

	
 
		// disable jid_escaping
 
		std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nservice.more_resources=1\n");
 
		cfg->load(ifs);
 

	
 
		// and now to bare JID again...
 
		user->getConversationManager()->resetResources();
 
		conv->handleMessage(msg2);
 
		loop->processEvents();
 

	
 
		// enable jid_escaping again
 
		std::istringstream ifs2("service.server_mode = 1\nservice.jid_escaping=1\nservice.jid=localhost\nservice.more_resources=1\n");
 
		cfg->load(ifs2);
 
		
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getTo().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test@localhost/bot"), dynamic_cast<Swift::Message *>(getStanza(received[0]))->getFrom().toString());
 
		
 
		received.clear();
 
	}
 

	
 
	void handleGroupchatMessages() {
 
		User *user = userManager->getUser("user@localhost");
src/tests/discoitemsresponder.cpp
Show inline comments
 
new file 100644
 
#include "transport/userregistry.h"
 
#include "transport/userregistration.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "transport/adhocmanager.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class DiscoItemsResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(DiscoItemsResponderTest);
 
	CPPUNIT_TEST(roomList);
 
	CPPUNIT_TEST(roomInfo);
 
	CPPUNIT_TEST(clearRooms);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 

	
 
		void setUp (void) {
 
			setMeUp();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			tearMeDown();
 
		}
 

	
 
	void roomList() {
 
		itemsResponder->addRoom("#room@localhost", "#room");
 

	
 
		boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
 
		boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
		iq->setFrom("user@localhost");
 
		injectIQ(iq);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>());
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getJID().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getName());
 
	}
 

	
 
	void roomInfo() {
 
		itemsResponder->addRoom("#room@localhost", "#room");
 

	
 
		boost::shared_ptr<Swift::DiscoInfo> payload(new Swift::DiscoInfo());
 
		boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
		iq->setFrom("user@localhost");
 
		iq->setTo("#room@localhost");
 
		injectIQ(iq);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getName());
 
		CPPUNIT_ASSERT_EQUAL(std::string("conference"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getCategory());
 
		CPPUNIT_ASSERT_EQUAL(std::string("text"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getType());
 
	}
 

	
 
	void clearRooms() {
 
		itemsResponder->addRoom("#room@localhost", "#room");
 
		itemsResponder->clearRooms();
 

	
 
		boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
 
		boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
		iq->setFrom("user@localhost");
 
		injectIQ(iq);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems().empty());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (DiscoItemsResponderTest);
src/tests/localbuddy.cpp
Show inline comments
 
@@ -22,12 +22,13 @@ using namespace Transport;
 

	
 
class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(LocalBuddyTest);
 
	CPPUNIT_TEST(createWithInvalidName);
 
	CPPUNIT_TEST(buddyFlagsFromJID);
 
	CPPUNIT_TEST(JIDToLegacyName);
 
	CPPUNIT_TEST(getSafeName);
 
	CPPUNIT_TEST(handleBuddyChanged);
 
	CPPUNIT_TEST(setAlias);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
@@ -67,12 +68,26 @@ class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 

	
 
	void JIDToLegacyName() {
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz@test"), Buddy::JIDToLegacyName("hanzz\\40test@localhost/bot"));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz@test"), Buddy::JIDToLegacyName("hanzz%test@localhost/bot"));
 
	}
 

	
 
	void getSafeName() {
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 

	
 
		std::vector<std::string> grp;
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1@test", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test"), buddy->getSafeName());
 

	
 
		buddy->setFlags(BUDDY_NO_FLAG);
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test"), buddy->getSafeName());
 
	}
 

	
 
	void buddyFlagsFromJID() {
 
		CPPUNIT_ASSERT_EQUAL(BUDDY_JID_ESCAPING, Buddy::buddyFlagsFromJID("hanzz\\40test@localhost/bot"));
 
		CPPUNIT_ASSERT_EQUAL(BUDDY_NO_FLAG, Buddy::buddyFlagsFromJID("hanzz%test@localhost/bot"));
 
	}
 

	
 
	void handleBuddyChanged() {
src/tests/main.cpp
Show inline comments
 
@@ -19,12 +19,22 @@ int main (int argc, char* argv[])
 
{
 
#ifdef WITH_LOG4CXX
 
	LoggerPtr root = Logger::getRootLogger();
 
	root->addAppender(new FileAppender(new PatternLayout("%d %-5p %c: %m%n"), "libtransport_test.log", false));
 
#endif
 

	
 
	std::vector<std::string> testsToRun;
 
	for (int i = 1; i < argc; ++i) {
 
		std::string param(argv[i]);
 
		testsToRun.push_back(param);
 
	}
 

	
 
	if (testsToRun.empty()) {
 
		testsToRun.push_back("");
 
	}
 

	
 
	// informs test-listener about testresults
 
	CPPUNIT_NS :: TestResult testresult;
 

	
 
	// register listener for collecting the test-results
 
	CPPUNIT_NS :: TestResultCollector collectedresults;
 
	testresult.addListener (&collectedresults);
 
@@ -33,13 +43,21 @@ int main (int argc, char* argv[])
 
	CPPUNIT_NS :: BriefTestProgressListener progress;
 
	testresult.addListener (&progress);
 

	
 
	// insert test-suite at test-runner by registry
 
	CPPUNIT_NS :: TestRunner testrunner;
 
	testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ());
 
	testrunner.run (testresult);
 
	for (std::vector<std::string>::const_iterator i = testsToRun.begin(); i != testsToRun.end(); ++i) {
 
		try {
 
			testrunner.run(testresult, *i);
 
		}
 
		catch (const std::exception& e) {
 
			std::cerr << "Error: " << e.what() << std::endl;
 
			return -1;
 
		}
 
	}
 

	
 
	// output results in compiler-format
 
	CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr);
 
	compileroutputter.write ();
 

	
 
	// return 0 if tests were successful
src/tests/networkpluginserver.cpp
Show inline comments
 
new file 100644
 
#include "transport/userregistry.h"
 
#include "transport/userregistration.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "transport/adhocmanager.h"
 
#include "transport/protocol.pb.h"
 
#include "transport/networkpluginserver.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(NetworkPluginServerTest);
 
	CPPUNIT_TEST(handleBuddyChangedPayload);
 
	CPPUNIT_TEST(handleBuddyChangedPayloadNoEscaping);
 
	CPPUNIT_TEST(handleBuddyChangedPayloadUserContactInRoster);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		NetworkPluginServer *serv;
 

	
 
		void setUp (void) {
 
			setMeUp();
 

	
 
			serv = new NetworkPluginServer(component, cfg, userManager, NULL, NULL);
 
			connectUser();
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			delete serv;
 
			tearMeDown();
 
		}
 

	
 
		void handleBuddyChangedPayload() {
 
			User *user = userManager->getUser("user@localhost");
 

	
 
			pbnetwork::Buddy buddy;
 
			buddy.set_username("user@localhost");
 
			buddy.set_buddyname("buddy1@test");
 

	
 
			std::string message;
 
			buddy.SerializeToString(&message);
 

	
 
			serv->handleBuddyChangedPayload(message);
 
			CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
			Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>();
 
			CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size());
 
			Swift::RosterItemPayload item = payload1->getItems()[0];
 
			CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost"), item.getJID().toString());
 
		}
 

	
 
		void handleBuddyChangedPayloadNoEscaping() {
 
			std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nservice.more_resources=1\n");
 
			cfg->load(ifs);
 
			User *user = userManager->getUser("user@localhost");
 

	
 
			pbnetwork::Buddy buddy;
 
			buddy.set_username("user@localhost");
 
			buddy.set_buddyname("buddy1@test");
 

	
 
			std::string message;
 
			buddy.SerializeToString(&message);
 

	
 
			serv->handleBuddyChangedPayload(message);
 
			CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
			Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>();
 
			CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size());
 
			Swift::RosterItemPayload item = payload1->getItems()[0];
 
			CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test@localhost"), item.getJID().toString());
 

	
 
			std::istringstream ifs2("service.server_mode = 1\nservice.jid_escaping=1\nservice.jid=localhost\nservice.more_resources=1\n");
 
			cfg->load(ifs2);
 
		}
 

	
 
		void handleBuddyChangedPayloadUserContactInRoster() {
 
			User *user = userManager->getUser("user@localhost");
 

	
 
			pbnetwork::Buddy buddy;
 
			buddy.set_username("user@localhost");
 
			buddy.set_buddyname("user");
 

	
 
			std::string message;
 
			buddy.SerializeToString(&message);
 

	
 
			serv->handleBuddyChangedPayload(message);
 
			CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
		}
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (NetworkPluginServerTest);
src/tests/rosterresponder.cpp
Show inline comments
 
new file 100644
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/rosterresponder.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class RosterResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(RosterResponderTest);
 
	CPPUNIT_TEST(addEmptyBuddy);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		RosterResponder *m_rosterResponder;
 
		std::string m_buddy;
 

	
 
		void setUp (void) {
 
			m_buddy = "none";
 
			setMeUp();
 
			connectUser();
 

	
 
			m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager);
 
			m_rosterResponder->onBuddyAdded.connect(boost::bind(&RosterResponderTest::handleBuddyAdded, this, _1, _2));
 
			m_rosterResponder->onBuddyRemoved.connect(boost::bind(&RosterResponderTest::handleBuddyRemoved, this, _1));
 
			m_rosterResponder->onBuddyUpdated.connect(boost::bind(&RosterResponderTest::handleBuddyUpdated, this, _1, _2));
 
			m_rosterResponder->start();
 

	
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			tearMeDown();
 
		}
 

	
 
	void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item) {
 
		m_buddy = buddy->getName();
 
	}
 

	
 
	void handleBuddyRemoved(Buddy *buddy) {
 
		m_buddy = buddy->getName();
 
	}
 

	
 
	void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item) {
 
		m_buddy = buddy->getName();
 
	}
 

	
 
	void addEmptyBuddy() {
 
		Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
		Swift::RosterItemPayload item;
 
		item.setJID("icq.localhost");
 
		item.setSubscription(Swift::RosterItemPayload::Both);
 

	
 
		p->addItem(item);
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, "user@localhost", component->getIQRouter());
 

	
 
		boost::shared_ptr<Swift::IQ> iq(new Swift::IQ(Swift::IQ::Set));
 
		iq->setTo("icq.localhost");
 
		iq->setFrom("user@localhost");
 
		iq->addPayload(p);
 
		iq->setID("123");
 
		injectIQ(iq);
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string("none"), m_buddy);
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (RosterResponderTest);
src/tests/settingsadhoccommand.cpp
Show inline comments
 
@@ -23,12 +23,13 @@
 

	
 
using namespace Transport;
 

	
 
class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(SettingsAdHocCommandTest);
 
	CPPUNIT_TEST(getItems);
 
	CPPUNIT_TEST(getInfo);
 
	CPPUNIT_TEST(execute);
 
	CPPUNIT_TEST(executeBadSessionID);
 
	CPPUNIT_TEST(executeNotRegistered);
 
	CPPUNIT_TEST(cancel);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
@@ -67,12 +68,28 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT
 
			CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
			CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
			CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>());
 
			CPPUNIT_ASSERT_EQUAL(std::string("settings"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getNode());
 
		}
 

	
 
		void getInfo() {
 
			boost::shared_ptr<Swift::DiscoInfo> payload(new Swift::DiscoInfo());
 
			payload->setNode("settings");
 
			boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
			iq->setFrom("user@localhost");
 
			injectIQ(iq);
 
			loop->processEvents();
 

	
 
			CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
			CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
			CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
			CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
			CPPUNIT_ASSERT_EQUAL(std::string("automation"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getCategory());
 
			CPPUNIT_ASSERT_EQUAL(std::string("command-node"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getType());
 
		}
 

	
 
		void executeNotRegistered() {
 
			boost::shared_ptr<Swift::Command> payload(new Swift::Command("settings"));
 
			boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Set, Swift::JID("localhost"), "id", payload);
 
			iq->setFrom("user@localhost");
 
			injectIQ(iq);
 
			loop->processEvents();
src/tests/stringtreeparser.cpp
Show inline comments
 
new file 100644
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Parser/StringTreeParser.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
#include "transport/util.h"
 

	
 
using namespace Transport;
 

	
 
class StringTreeParserTest : public CPPUNIT_NS :: TestFixture{
 
	CPPUNIT_TEST_SUITE(StringTreeParserTest);
 
	CPPUNIT_TEST(parseEscapedCharacters);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
		}
 

	
 
		void tearDown (void) {
 

	
 
		}
 

	
 
	void parseEscapedCharacters() {
 
		Swift::ParserElement::ref root = Swift::StringTreeParser::parse("<body>&lt;test&gt;</body>");
 
		CPPUNIT_ASSERT_EQUAL(std::string("<test>"), root->getText());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (StringTreeParserTest);
src/tests/user.cpp
Show inline comments
 
@@ -27,14 +27,16 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST(handlePresenceJoinRoom);
 
	CPPUNIT_TEST(handlePresenceJoinRoomTwoResources);
 
	CPPUNIT_TEST(handlePresenceLeaveRoom);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResources);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResourcesOneDisconnects);
 
	CPPUNIT_TEST(leaveJoinedRoom);
 
	CPPUNIT_TEST(joinRoomBeforeConnected);
 
	CPPUNIT_TEST(handleDisconnected);
 
	CPPUNIT_TEST(handleDisconnectedReconnect);
 
	CPPUNIT_TEST(joinRoomHandleDisconnectedRejoin);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		std::string room;
 
		std::string roomNickname;
 
		std::string roomPassword;
 
@@ -315,11 +317,61 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT(!streamEnded);
 
		user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(user);
 
		CPPUNIT_ASSERT(readyToConnect);
 

	
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		injectPresence(response);
 
		loop->processEvents();
 
	}
 

	
 
	void joinRoomBeforeConnected() {
 
		User *user = userManager->getUser("user@localhost");
 
		user->setConnected(false);
 

	
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("#room@localhost/hanzz");
 
		response->setFrom("user@localhost/resource");
 

	
 
		Swift::MUCPayload *payload = new Swift::MUCPayload();
 
		payload->setPassword("password");
 
		response->addPayload(boost::shared_ptr<Swift::Payload>(payload));
 
		injectPresence(response);
 
		loop->processEvents();
 

	
 
		// no presence received in server mode, just disco#info
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), room);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
 

	
 
		user->setConnected(true);
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
 
	}
 

	
 
	void joinRoomHandleDisconnectedRejoin() {
 
		User *user = userManager->getUser("user@localhost");
 
		handlePresenceJoinRoom();
 
		handleDisconnectedReconnect();
 
		room = "";
 
		roomNickname = "";
 
		roomPassword = "";
 
		received.clear();
 
		user->setConnected(true);
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (UserTest);
src/tests/usermanager.cpp
Show inline comments
 
@@ -24,12 +24,13 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(UserManagerTest);
 
	CPPUNIT_TEST(connectUser);
 
	CPPUNIT_TEST(connectTwoResources);
 
	CPPUNIT_TEST(connectUserTransportDisabled);
 
	CPPUNIT_TEST(connectUserRegistrationNeeded);
 
	CPPUNIT_TEST(connectUserRegistrationNeededRegistered);
 
	CPPUNIT_TEST(connectUserVipOnlyNonVip);
 
	CPPUNIT_TEST(handleProbePresence);
 
	CPPUNIT_TEST(disconnectUser);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
@@ -68,26 +69,102 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount());
 
		CPPUNIT_ASSERT(!streamEnded);
 
	}
 

	
 
	void connectUserVipOnlyNonVip() {
 
		addUser();
 
		std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nservice.vip_only=1\nservice.vip_message=Ahoj\n");
 
		cfg->load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(3, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[1])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("Ahoj"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getTo().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("localhost"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getFrom().toString());
 

	
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		CPPUNIT_ASSERT(streamEnded);
 
		std::istringstream ifs2("service.server_mode = 1\nservice.jid_escaping=1\nservice.jid=localhost\nservice.more_resources=1\n");
 
		cfg->load(ifs2);
 
	}
 

	
 
	void handleProbePresence() {
 
		UserInfo info;
 
		info.id = 1;
 
		info.jid = "user@localhost";
 
		storage->setUser(info);
 

	
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		response->setType(Swift::Presence::Probe);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		CPPUNIT_ASSERT_EQUAL(3, (int) received.size());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 

	
 
		Swift::Presence *presence = dynamic_cast<Swift::Presence *>(getStanza(received[1]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, presence->getType());
 

	
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[2]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Probe, presence->getType());
 

	
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Unsubscribed);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[1]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType());
 

	
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Error);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 

	
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Error);
 
		response->addPayload(boost::shared_ptr<Swift::ErrorPayload>(new Swift::ErrorPayload(Swift::ErrorPayload::SubscriptionRequired)));
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[0]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType());
 

	
 
		storage->removeUser(1);
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Unsubscribed);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
	}
 

	
 
	void connectTwoResources() {
 
		connectUser();
 
		add2Buddies();
 
		connectSecondResource();
src/tests/util.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
@@ -33,13 +34,13 @@ class UtilTest : public CPPUNIT_NS :: TestFixture{
 

	
 
		void tearDown (void) {
 

	
 
		}
 

	
 
	void encryptDecryptPassword() {
 
		std::string encrypted = Util::encryptPassword("password", "key");
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), Util::decryptPassword(encrypted, "key"));
 
		std::string encrypted = StorageBackend::encryptPassword("password", "key");
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), StorageBackend::decryptPassword(encrypted, "key"));
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (UtilTest);
src/transport.cpp
Show inline comments
 
@@ -23,13 +23,12 @@
 
#include <boost/smart_ptr/make_shared.hpp>
 
#include <boost/algorithm/string/predicate.hpp>
 
#include "transport/storagebackend.h"
 
#include "transport/factory.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "discoinforesponder.h"
 
#include "storageparser.h"
 
#ifdef _WIN32
 
#include <Swiften/TLS/CAPICertificate.h>
 
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
 
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
 
#else
 
@@ -155,26 +154,24 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
 
 	m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
 
	
 
	m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
 
	m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
 

	
 
	m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config);
 
	m_discoInfoResponder->start();
 

	
 

	
 
// 
 
// 	m_registerHandler = new SpectrumRegisterHandler(m_component);
 
// 	m_registerHandler->start();
 
}
 

	
 
Component::~Component() {
 
	delete m_presenceOracle;
 
	delete m_entityCapsManager;
 
	delete m_capsManager;
 
	delete m_capsMemoryStorage;
 
	delete m_discoInfoResponder;
 
	if (m_component)
 
		delete m_component;
 
	if (m_server) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 
@@ -185,25 +182,12 @@ Swift::StanzaChannel *Component::getStanzaChannel() {
 
}
 

	
 
Transport::PresenceOracle *Component::getPresenceOracle() {
 
	return m_presenceOracle;
 
}
 

	
 
void Component::setTransportFeatures(std::list<std::string> &features) {
 
	m_discoInfoResponder->setTransportFeatures(features);
 
}
 

	
 
Swift::CapsInfo &Component::getBuddyCapsInfo() {
 
		return m_discoInfoResponder->getBuddyCapsInfo();
 
}
 

	
 
void Component::setBuddyFeatures(std::list<std::string> &features) {
 
	// TODO: handle caps change
 
	m_discoInfoResponder->setBuddyFeatures(features);
 
}
 

	
 
void Component::start() {
 
	if (m_component && !m_component->isAvailable()) {
 
		LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
 
		if (CONFIG_INT(m_config, "service.port") == 5222) {
 
			LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?");
 
		}
 
@@ -294,15 +278,22 @@ void Component::handlePresence(Swift::Presence::ref presence) {
 

	
 
	// filter out bad presences
 
	if (!presence->getFrom().isValid()) {
 
		return;
 
	}
 

	
 
	if (presence->getType() == Presence::Error) {
 
		return;
 
	}
 
	switch (presence->getType()) {
 
		case Presence::Error:
 
		case Presence::Subscribe:
 
		case Presence::Subscribed:
 
		case Presence::Unsubscribe:
 
		case Presence::Unsubscribed:
 
			return;
 
		default:
 
			break;
 
	};
 

	
 
	// check if we have this client's capabilities and ask for them
 
	if (presence->getType() != Swift::Presence::Unavailable) {
 
		boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
 
		if (capsInfo && capsInfo->getHash() == "sha-1") {
 
			/*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
src/user.cpp
Show inline comments
 
@@ -173,20 +173,27 @@ void User::setConnected(bool connected) {
 
	m_connected = connected;
 
	m_reconnectCounter = 0;
 
	setIgnoreDisconnect(false);
 
	updateLastActivity();
 

	
 
	sendCurrentPresence();
 

	
 
	if (m_connected) {
 
		BOOST_FOREACH(Swift::Presence::ref &presence, m_joinedRooms) {
 
			handlePresence(presence, true);
 
		}
 
	}
 
}
 

	
 
void User::handlePresence(Swift::Presence::ref presence) {
 
void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
 

	
 
	int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
 

	
 
	m_conversationManager->resetResources();
 

	
 
	LOG4CXX_INFO(logger, "PRESENCE " << presence->getFrom().toString() << " " << presence->getTo().toString());
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			
 
			// Forward status message to legacy network, but only if it's sent from active resource
 
// 					if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
 
@@ -226,42 +233,76 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
				}
 
			}
 

	
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room);
 
			onRoomLeft(room);
 

	
 
			BOOST_FOREACH(Swift::Presence::ref &p, m_joinedRooms) {
 
				if (p->getTo() == presence->getTo()) {
 
					m_joinedRooms.remove(p);
 
					break;
 
				}
 
			}
 

	
 
			if (conv) {
 
				m_conversationManager->removeConversation(conv);
 
				delete conv;
 
			}
 
		}
 
		else {
 
			// force connection to legacy network to let backend to handle auto-join on connect.
 
			if (!m_readyForConnect) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 

	
 
			std::string room = Buddy::JIDToLegacyName(presence->getTo());
 
			std::string password = "";
 
			if (presence->getPayload<Swift::MUCPayload>() != NULL) {
 
				password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
 
			}
 

	
 
			Conversation *conv = m_conversationManager->getConversation(room);
 
			if (conv != NULL) {
 
				if (std::find(conv->getJIDs().begin(), conv->getJIDs().end(), presence->getFrom()) != conv->getJIDs().end()) {
 
					LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource());
 
				}
 
				else {
 
					conv->addJID(presence->getFrom());
 
					conv->sendParticipants(presence->getFrom());
 
				}
 

	
 
				if (forceJoin) {
 
					onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
 
				}
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource());
 
			std::string password = "";
 
			if (presence->getPayload<Swift::MUCPayload>() != NULL) {
 
				password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
 
			bool isInJoined = false;
 
			BOOST_FOREACH(Swift::Presence::ref &p, m_joinedRooms) {
 
				if (p->getTo() == presence->getTo()) {
 
					isInJoined = true;
 
				}
 
			}
 
			if (!isInJoined) {
 
				m_joinedRooms.push_back(presence);
 
			}
 

	
 
			if (!m_connected) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Joining room " << room << " postponed, because use is not connected to legacy network yet.");
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource());
 

	
 
			conv = m_component->getFactory()->createConversation(m_conversationManager, room, true);
 
			m_conversationManager->addConversation(conv);
 
			conv->setNickname(presence->getTo().getResource());
 
			conv->addJID(presence->getFrom());
 

	
 
			onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
 
		}
 
		return;
 
	}
 
	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
src/usermanager.cpp
Show inline comments
 
@@ -23,12 +23,13 @@
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "transport/discoitemsresponder.h"
 
#include "storageresponder.h"
 

	
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#ifndef __FreeBSD__
 
@@ -37,21 +38,22 @@
 
// #include "valgrind/memcheck.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "UserManager");
 

	
 
UserManager::UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
 
UserManager::UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend) {
 
	m_cachedUser = NULL;
 
	m_onlineBuddies = 0;
 
	m_sentToXMPP = 0;
 
	m_sentToBackend = 0;
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 
	m_storageResponder = NULL;
 
	m_userRegistry = userRegistry;
 
	m_discoItemsResponder = discoItemsResponder;
 

	
 
	if (m_storageBackend) {
 
		m_storageResponder = new StorageResponder(component->getIQRouter(), m_storageBackend, this);
 
		m_storageResponder->start();
 
	}
 

	
 
@@ -179,34 +181,44 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
				response->setFrom(m_component->getJID());
 
				m_component->getStanzaChannel()->sendPresence(response);
 
				return;
 
		    }
 
		}
 

	
 
		UserInfo res;
 
		bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;
 

	
 
		// No user and unavailable presence -> answer with unavailable
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
		if (presence->getType() == Swift::Presence::Unavailable || presence->getType() == Swift::Presence::Probe) {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(presence->getFrom());
 
			response->setFrom(presence->getTo());
 
			response->setType(Swift::Presence::Unavailable);
 
			m_component->getStanzaChannel()->sendPresence(response);
 

	
 
			// bother him with probe presence, just to be
 
			// sure he is subscribed to us.
 
			if (/*registered && */presence->getType() == Swift::Presence::Probe) {
 
				Swift::Presence::ref response = Swift::Presence::create();
 
				response->setTo(presence->getFrom());
 
				response->setFrom(presence->getTo());
 
				response->setType(Swift::Presence::Probe);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
			}
 

	
 
			// Set user offline in database
 
			if (m_storageBackend) {
 
				UserInfo res;
 
				bool registered = m_storageBackend->getUser(userkey, res);
 
				if (registered) {
 
					m_storageBackend->setUserOnline(res.id, false);
 
				}
 
			}
 
			return;
 
		}
 

	
 
		UserInfo res;
 
		bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;
 

	
 
		// In server mode, we don't need registration normally, but for networks like IRC
 
		// or Twitter where there's no real authorization using password, we have to force
 
		// registration otherwise some data (like bookmarked rooms) could leak.
 
		if (m_component->inServerMode()) {
 
			if (!registered) {
 
				// If we need registration, stop login process because user is not registered
 
@@ -232,13 +244,14 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
			res.password = m_userRegistry->getUserPassword(userkey);
 
		}
 

	
 
		// We allow auto_register feature in gateway-mode. This allows IRC user to register
 
		// the transport just by joining the room.
 
		if (!m_component->inServerMode()) {
 
			if (!registered && CONFIG_BOOL(m_component->getConfig(), "registration.auto_register")) {
 
			if (!registered && (CONFIG_BOOL(m_component->getConfig(), "registration.auto_register") ||
 
				!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true))) {
 
				res.password = "";
 
				res.jid = userkey;
 

	
 
				bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
				if (isMUC) {
 
					res.uin = presence->getTo().getResource();
 
@@ -251,23 +264,39 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
				if (m_storageBackend) {
 
					// store user and getUser again to get user ID.
 
					m_storageBackend->setUser(res);
 
					registered = m_storageBackend->getUser(userkey, res);
 
				}
 
				else {
 
					registered = false;
 
					registered = true;
 
				}
 
			}
 
		}
 

	
 
		// Unregistered users are not able to login
 
		if (!registered) {
 
			LOG4CXX_WARN(logger, "Unregistered user " << userkey << " tried to login");
 
			return;
 
		}
 

	
 
		if (CONFIG_BOOL(m_component->getConfig(), "service.vip_only") && res.vip == false) {
 
			if (!CONFIG_STRING(m_component->getConfig(), "service.vip_message").empty()) {
 
				boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
				msg->setBody(CONFIG_STRING(m_component->getConfig(), "service.vip_message"));
 
				msg->setTo(presence->getFrom());
 
				msg->setFrom(m_component->getJID());
 
				m_component->getStanzaChannel()->sendMessage(msg);
 
			}
 

	
 
			LOG4CXX_WARN(logger, "Non VIP user " << userkey << " tried to login");
 
			if (m_component->inServerMode()) {
 
				m_userRegistry->onPasswordInvalid(presence->getFrom());
 
			}
 
			return;
 
		}
 

	
 
		bool transport_enabled = true;
 
		if (m_storageBackend) {
 
			std::string value = "1";
 
			int type = (int) TYPE_BOOLEAN;
 
			m_storageBackend->getUserSetting(res.id, "enable_transport", type, value);
 
			transport_enabled = value == "1";
 
@@ -367,18 +396,26 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
 
		case Swift::Presence::Available:
 
		case Swift::Presence::Unavailable:
 
			break;
 
		case Swift::Presence::Probe:
 
			handleProbePresence(presence);
 
			break;
 
		case Swift::Presence::Error:
 
			handleErrorPresence(presence);
 
			break;
 
		default:
 
			break;
 
	};
 
}
 

	
 
void UserManager::handleProbePresence(Swift::Presence::ref presence) {
 
	// Don't let RosterManager to handle presences for us
 
	if (presence->getTo().getNode().empty()) {
 
		return;
 
	}
 

	
 
	User *user = getUser(presence->getFrom().toBare().toString());
 

	
 
 	if (user) {
 
 		user->getRosterManager()->sendCurrentPresence(presence->getTo(), presence->getFrom());
 
 	}
 
 	else {
 
@@ -387,13 +424,40 @@ void UserManager::handleProbePresence(Swift::Presence::ref presence) {
 
		response->setTo(presence->getFrom());
 
		response->setType(Swift::Presence::Unavailable);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
	}
 
}
 

	
 
void UserManager::handleErrorPresence(Swift::Presence::ref presence) {
 
	// Don't let RosterManager to handle presences for us
 
	if (!presence->getTo().getNode().empty()) {
 
		return;
 
	}
 

	
 
	if (!presence->getPayload<Swift::ErrorPayload>()) {
 
		return;
 
	}
 

	
 
	if (presence->getPayload<Swift::ErrorPayload>()->getCondition() != Swift::ErrorPayload::SubscriptionRequired) {
 
		return;
 
	}
 

	
 
	std::string userkey = presence->getFrom().toBare().toString();
 
	UserInfo res;
 
	bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;
 
	if (registered) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setFrom(presence->getTo().toBare());
 
		response->setTo(presence->getFrom().toBare());
 
		response->setType(Swift::Presence::Subscribe);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
	}
 
}
 

	
 
void UserManager::handleSubscription(Swift::Presence::ref presence) {
 
	
 
	// answer to subscibe for transport itself
 
	if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().empty()) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setFrom(presence->getTo().toBare());
 
		response->setTo(presence->getFrom().toBare());
 
		response->setType(Swift::Presence::Subscribed);
 
@@ -403,12 +467,25 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) {
 
// 		response->setFrom(presence->getTo());
 
// 		response->setTo(presence->getFrom());
 
// 		response->setType(Swift::Presence::Subscribe);
 
// 		m_component->getStanzaChannel()->sendPresence(response);
 
		return;
 
	}
 
	else if (presence->getType() == Swift::Presence::Unsubscribed && presence->getTo().getNode().empty()) {
 
		std::string userkey = presence->getFrom().toBare().toString();
 
		UserInfo res;
 
		bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false;
 
		if (registered) {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setFrom(presence->getTo().toBare());
 
			response->setTo(presence->getFrom().toBare());
 
			response->setType(Swift::Presence::Subscribe);
 
			m_component->getStanzaChannel()->sendPresence(response);
 
		}
 
		return;
 
	}
 

	
 
	// Don't let RosterManager to handle presences for us
 
	if (presence->getTo().getNode().empty()) {
 
		return;
 
	}
 

	
src/userregistration.cpp
Show inline comments
 
@@ -91,13 +91,21 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr<Sw
 
		return;
 

	
 
	if (remoteRosterNotSupported || !payload) {
 
		std::list <BuddyInfo> roster;
 
		m_storageBackend->getBuddies(userInfo.id, roster);
 
		for(std::list<BuddyInfo>::iterator u = roster.begin(); u != roster.end() ; u++){
 
			std::string name = Swift::JID::getEscapedNode((*u).legacyName);
 
			std::string name = (*u).legacyName;
 
			if ((*u).flags & BUDDY_JID_ESCAPING) {
 
				name = Swift::JID::getEscapedNode((*u).legacyName);
 
			}
 
			else {
 
				if (name.find_last_of("@") != std::string::npos) {
 
					name.replace(name.find_last_of("@"), 1, "%");
 
				}
 
			}
 

	
 
			Swift::Presence::ref response;
 
			response = Swift::Presence::create();
 
			response->setTo(Swift::JID(barejid));
 
			response->setFrom(Swift::JID(name, m_component->getJID().toString()));
 
			response->setType(Swift::Presence::Unsubscribe);
src/util.cpp
Show inline comments
 
@@ -16,28 +16,68 @@
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/util.h"
 
#include "transport/config.h"
 
#include <boost/foreach.hpp>
 
#include <iostream>
 
#include <iterator>
 
#include <algorithm>
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
#include <boost/numeric/conversion/cast.hpp>
 

	
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include <sys/stat.h>
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#else
 
#include <windows.h>
 
#include <process.h>
 
#define getpid _getpid
 
#endif
 

	
 
using namespace boost::filesystem;
 

	
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
namespace Util {
 

	
 
void createDirectories(Transport::Config *config, const boost::filesystem::path& ph) {
 
	if (ph.empty() || exists(ph)) {
 
		return;
 
	}
 

	
 
	// First create branch, by calling ourself recursively
 
	createDirectories(config, ph.branch_path());
 
	
 
	// Now that parent's path exists, create the directory
 
	create_directory(ph);
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(config, "service.group").empty() && !CONFIG_STRING(config, "service.user").empty()) {
 
		struct group *gr;
 
		if ((gr = getgrnam(CONFIG_STRING(config, "service.group").c_str())) == NULL) {
 
			std::cerr << "Invalid service.group name " << CONFIG_STRING(config, "service.group") << "\n";
 
		}
 
		struct passwd *pw;
 
		if ((pw = getpwnam(CONFIG_STRING(config, "service.user").c_str())) == NULL) {
 
			std::cerr << "Invalid service.user name " << CONFIG_STRING(config, "service.user") << "\n";
 
		}
 
		chown(ph.string().c_str(), pw->pw_uid, gr->gr_gid);
 
	}
 
#endif
 
}
 

	
 
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t) {
 
	BOOST_FOREACH(const std::string &dir, dirs) {
 
		path p(dir);
 

	
 
		try {
 
			if (!exists(p)) {
 
@@ -55,13 +95,13 @@ void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t) {
 
							remove(itr->path());
 
						}
 
						else if (is_directory(itr->path())) {
 
							std::vector<std::string> nextDirs;
 
							nextDirs.push_back(itr->path().string());
 
							removeEverythingOlderThan(nextDirs, t);
 
							if (is_empty(itr->path())) {
 
							if (boost::filesystem::is_empty(itr->path())) {
 
								remove_all(itr->path());
 
							}
 
						}
 
					}
 
					catch (const filesystem_error& ex) {
 
						
 
@@ -74,64 +114,12 @@ void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t) {
 
		catch (const filesystem_error& ex) {
 
			
 
		}
 
	}
 
}
 

	
 
std::string encryptPassword(const std::string &password, const std::string &key) {
 
	std::string encrypted;
 
	encrypted.resize(password.size());
 
	for (int i = 0; i < password.size(); i++) {
 
		char c = password[i];
 
		char keychar = key[i % key.size()];
 
		c += keychar;
 
		encrypted[i] = c;
 
	}
 

	
 
	encrypted = Swift::Base64::encode(Swift::createByteArray(encrypted));
 
	return encrypted;
 
}
 

	
 
std::string decryptPassword(std::string &encrypted, const std::string &key) {
 
	encrypted = Swift::byteArrayToString(Swift::Base64::decode(encrypted));
 
	std::string password;
 
	password.resize(encrypted.size());
 
	for (int i = 0; i < encrypted.size(); i++) {
 
		char c = encrypted[i];
 
		char keychar = key[i % key.size()];
 
		c -= keychar;
 
		password[i] = c;
 
	}
 

	
 
	return password;
 
}
 

	
 
std::string serializeGroups(const std::vector<std::string> &groups) {
 
	std::string ret;
 
	BOOST_FOREACH(const std::string &group, groups) {
 
		ret += group + "\n";
 
	}
 
	if (!ret.empty()) {
 
		ret.erase(ret.end() - 1);
 
	}
 
	return ret;
 
}
 

	
 
std::vector<std::string> deserializeGroups(std::string &groups) {
 
	std::vector<std::string> ret;
 
	if (groups.empty()) {
 
		return ret;
 
	}
 

	
 
	boost::split(ret, groups, boost::is_any_of("\n"));
 
	if (ret.back().empty()) {
 
		ret.erase(ret.end() - 1);
 
	}
 
	return ret;
 
}
 

	
 
int getRandomPort(const std::string &s) {
 
	unsigned long r = 0;
 
	BOOST_FOREACH(char c, s) {
 
		r += (int) c;
 
	}
 
	srand(time(NULL) + r);
0 comments (0 inline, 0 general)