Compare commits

..

No commits in common. "master" and "patch-1" have entirely different histories.

917 changed files with 4757 additions and 314076 deletions

43
.gitignore vendored
View file

@ -1,35 +1,10 @@
*.pb.cc _site/*
*.pb.h _theme_packages/*
plugin/python/protocol_pb2.py
Makefile
*.cmake
*.so
*.so.*
*.log
libtransport_test
CMakeFiles
spectrum2
transport_config.h
Doxyfile
moc_*
CMakeCache.txt
*.patch
*.orig
spectrum2_manager
dfrotz
spectrum2_frotz_backend
spectrum2_libcommuni_backend
spectrum2_libpurple_backend
spectrum2_skype_backend
spectrum2_smstools3_backend
spectrum2_swiften_backend
spectrum2_template_backend
spectrum2_twitter_backend
install_manifest.txt
slack.cfg
*.sqlite
localhost.port
*.a
core.*
*.pyc
Thumbs.db
.DS_Store
!.gitkeep
.rbenv-version
.rvmrc

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "msvc-deps/curl"]
path = msvc-deps/curl
url = https://github.com/bagder/curl.git

View file

@ -1,49 +0,0 @@
language: cpp
python:
- "2.7_with_system_site_packages"
virtualenv:
system_site_packages: true
matrix:
include:
- os: linux
dist: trusty
sudo: required
- os: osx
allow_failures:
- os: osx
before_script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
export DEBIAN_FRONTEND=noninteractive;
export APT_LISTCHANGES_FRONTEND=none;
echo force-confold | sudo tee -a /etc/dpkg/dpkg.cfg;
curl -k https://swift.im/keys/packages.key | sudo apt-key add -;
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse' | sudo tee /etc/apt/sources.list.d/xenial.list > /dev/null;
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-security main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
echo 'deb http://us.archive.ubuntu.com/ubuntu xenial-updates main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/xenial.list > /dev/null;
echo "deb http://packages.spectrum.im/spectrum2/ xenial main" | sudo tee -a /etc/apt/sources.list;
echo "deb http://swift.im/packages/ubuntu/xenial beta main" | sudo tee -a /etc/apt/sources.list;
echo "deb http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list;
sudo apt-get update -qq;
sudo apt-get purge chromium-browser;
sudo apt-get install -y --force-yes build-essential prosody ngircd python-sleekxmpp libswiften-dev libprotobuf-dev protobuf-compiler libpurple-dev libglib2.0-dev libdbus-glib-1-dev liblog4cxx10-dev libpopt-dev libboost-dev libboost-signals-dev libboost-system-dev libboost-thread-dev libboost-locale-dev libboost-filesystem-dev libboost-program-options-dev libboost-regex-dev libboost-date-time-dev libcppunit-dev libcommuni-dev libminiupnpc-dev libnatpmp-dev;
sudo killall lua5.1;
else
brew update;
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/e6e43cf6a3%5E/Formula/cppunit.rb;
brew install protobuf log4cxx popt boost;
travis_wait 30 brew install -s libswiften;
fi
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
pip install --user sleekxmpp;
fi
script:
- cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTS=ON . && make
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
make extended_test;
else
make test;
fi
notifications:
slack: spectrum2:CIlYHtxGMAaxs3qVHfwBzCuy

1
404.html Normal file
View file

@ -0,0 +1 @@
Sorry this page does not exist =(

View file

@ -1,475 +0,0 @@
cmake_minimum_required(VERSION 2.6)
project(libtransport)
if(${CMAKE_MAJOR_VERSION} GREATER 2)
cmake_policy(SET CMP0037 OLD)
endif()
include(CPack)
message(STATUS "Variables to override default places where to find libraries:")
message(STATUS "|- cppunit : -DCPPUNIT_INCLUDE_DIR, -DCPPUNIT_LIBRARY")
message(STATUS "|- swiften : -DSWIFTEN_INCLUDE_DIR, -DSWIFTEN_LIBRARY")
message(STATUS " |- zlib : -DZLIB_LIBRARY")
message(STATUS " |- expat : -DEXPAT_LIBRARY")
message(STATUS " |-libidn : -DLIBIDN_LIBRARY")
message(STATUS " |-libxml : -DLIBXML_LIBRARY")
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_XMPP "Build XMPP plugin" ON)
option(ENABLE_TWITTER "Build Twitter 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})
ENDFOREACH (value2)
ENDMACRO(LIST_CONTAINS)
if(NOT LIB_INSTALL_DIR)
set(LIB_INSTALL_DIR "lib")
endif()
set(CMAKE_MODULE_PATH "cmake_modules")
###### Prerequisites ######
# FIND SWIFTEN
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Swiften)
if(NOT SWIFTEN_FOUND)
if (ZLIB_LIBRARY)
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${ZLIB_LIBRARY})
endif()
if (EXPAT_LIBRARY)
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${EXPAT_LIBRARY})
endif()
if (LIBIDN_LIBRARY)
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBIDN_LIBRARY})
endif()
if (LIBXML_LIBRARY)
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBXML_LIBRARY})
endif()
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Dnsapi")
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Crypt32")
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Secur32")
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Iphlpapi")
set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Winscard")
message(STATUS "XXXUsing swiften: ${SWIFTEN_INCLUDE_DIR} ${SWIFTEN_LIBRARY}
Version: ${SWIFTEN_VERSION}")
endif()
# FIND BOOST
if (WIN32)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
endif(WIN32)
set(Boost_FIND_QUIETLY ON)
find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals locale REQUIRED)
message( STATUS "Found Boost: ${Boost_VERSION}, ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
if (${Boost_VERSION} GREATER 104999)
message( STATUS "Using BOOST_FILESYSTEM_VERSION=3")
add_definitions(-DBOOST_FILESYSTEM_VERSION=3)
endif()
# FIND POPT
if (NOT WIN32)
set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(popt REQUIRED)
endif()
###### Database ######
# FIND SQLITE3
if (ENABLE_SQLITE3)
if (MSVC)
set(SQLITE3_FOUND 1)
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps)
else()
if (WIN32)
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3)
else()
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(sqlite3)
endif()
endif()
endif()
# FIND MYSQL
if(ENABLE_MYSQL)
set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(mysql)
endif()
# FIND PQXX
if(ENABLE_PQXX)
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(pqxx)
endif()
###### 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)
endif()
# FIND LIBEVENT
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(event)
endif()
# FIND GLIB
if(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 PROTOBUF
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Protobuf REQUIRED)
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()
if (WIN32)
add_definitions(-DSWIFTEN_STATIC=1)
ADD_DEFINITIONS(-D_UNICODE)
ADD_DEFINITIONS(-DUNICODE)
endif()
if (CMAKE_COMPILER_IS_GNUCXX)
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(openssl)
endif()
if(ENABLE_IRC)
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Communi)
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)
####### Miscallanous ######
if(ENABLE_DOCS)
find_package(Doxygen)
endif()
# 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}")
else (SPECTRUM_VERSION)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
if (NOT GIT_EXECUTABLE)
set (GIT_EXECUTABLE git)
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
OUTPUT_VARIABLE GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(SPECTRUM_VERSION 2.0.5-git-${GIT_REVISION})
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
set(SPECTRUM_VERSION 2.0.5)
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
endif (SPECTRUM_VERSION)
message("Version : " ${SPECTRUM_VERSION})
if (SQLITE3_FOUND)
ADD_DEFINITIONS(-DWITH_SQLITE)
if (WIN32)
include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3")
message("SQLite3 : bundled")
else (WIN32)
include_directories(${SQLITE3_INCLUDE_DIR})
message("SQLite3 : yes")
endif (WIN32)
else (SQLITE3_FOUND)
set(SQLITE3_LIBRARIES "")
if(ENABLE_SQLITE3)
message("SQLite3 : no (install sqlite3)")
else(ENABLE_SQLITE3)
message("SQLite3 : no (user disabled)")
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 "")
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 "")
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()
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()
if(ENABLE_PURPLE)
message(" libev eventloop : no (install libev-devel)")
endif()
endif()
if(IRC_FOUND)
ADD_DEFINITIONS(-DIRC_SHARED)
message("IRC plugin : yes")
include_directories(${QT_QTNETWORK_INCLUDE_DIR})
include_directories(${IRC_INCLUDE_DIR})
include(${QT_USE_FILE})
else()
if(ENABLE_IRC)
message("IRC plugin : no (install libCommuni and libprotobuf-dev)")
else(ENABLE_IRC)
message("IRC plugin : no (user disabled)")
endif()
endif()
if(ENABLE_TWITTER)
message("Twitter plugin : yes")
else(ENABLE_TWITTER)
message("Twitter plugin : no (user disabled)")
endif()
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()
else()
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)")
endif()
if(ENABLE_XMPP)
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)")
message("Swiften plugin : no (install libprotobuf-dev)")
message("Twitter plugin : no (install libprotobuf-dev)")
endif()
if (LOG4CXX_FOUND)
message("Log4cxx : yes")
include_directories(${LOG4CXX_INCLUDE_DIR})
ADD_DEFINITIONS(-DWITH_LOG4CXX)
else()
set(LOG4CXX_LIBRARIES "")
if (WIN32)
message("Log4cxx : no (install log4cxx-devel)")
else()
message(FATAL_ERROR "Log4cxx : no (install log4cxx-devel)")
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)
endif()
# We cannot use boost:signals2, because Swiften does not use them,
# for now, just ignore the deprecation warning.
ADD_DEFINITIONS(-DBOOST_SIGNALS_NO_DEPRECATION_WARNING)
if(CMAKE_BUILD_TYPE MATCHES Debug)
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)
SET(TRANSPORT_VERSION 2.0)
SET(PROJECT_VERSION 2.0)
include_directories(include)
include_directories(${EVENT_INCLUDE_DIRS})
include_directories(${SWIFTEN_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS})
if (CMAKE_COMPILER_IS_GNUCXX)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
ADD_SUBDIRECTORY(libtransport)
ADD_SUBDIRECTORY(plugin)
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(spectrum)
ADD_SUBDIRECTORY(backends)
ADD_SUBDIRECTORY(tests)
if (NOT WIN32)
ADD_SUBDIRECTORY(spectrum_manager)
# ADD_SUBDIRECTORY(spectrum2_send_message)
endif()
if (CPPUNIT_FOUND)
message("tests : yes")
include_directories(${CPPUNIT_INCLUDE_DIR})
else()
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)
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()

1
CNAME Normal file
View file

@ -0,0 +1 @@
spectrum.im

251
ChangeLog
View file

@ -1,251 +0,0 @@
Version 2.0.5 (2017-08-09):
Minor bugfixes:
* fix purple-hangouts login
* fix Debian packages dependencies
Version 2.0.4 (2017-08-03):
General:
* Add support for Swiften 4.0rc2. Swiften 3.x and 2.x are still supported.
* Add support for passwordless libpurple backends (e.g. purple-hangouts).
* Partial support for groupchats with case-sensitive names (e.g. purple-telegram).
* Various small bugfixes, see Git commit descriptions for the full list of changes.
Version 2.0.3 (2016-02-29):
General:
* Swift 3.0rc2 is now minimum Swift 3.x version needed to compile Spectrum2,
Swith 2.x remains supported.
* Rename user when he tries to connect to room from the second client
with different nickname than he used with the first client.
* Send self presence as the first presence from the MUC room.
* Send the icon hash to the backend with other buddies information.
* Send unavailable presence as a response to presence for exiting
the room. Fixes room rejoin in Pidgin.
* Fix memory leak in HTTPRequest - currently used only in Slack frontend.
Slack frontend:
* For IRC allow registering without providing account name/password.
* Do not reconnect to Slack RTM when no URL is available after disconnect.
* Handle "account_inactive" Slack error.
Web interface:
* Show warning when trying to register already registered username.
* Allow registering with empty password for networks like IRC where
password is not needed.
* Allow showing examples of username or server in registration form. This
is configured in config file.
* Fix `service.base_location` setting for register.shtml page.
Libpurple backend:
* Make the conversation active according to chatstates notifications.
Should fix the issue with repeating messages with prpl-facebook.
* When `service.web_directory` and `service.web_url` is set, images sent
in messages are stored to `service.web_directory` and link is forwarded
to the user. Tested only with prpl-facebook for now.
* Treat empty password as fatal error - do no try to reconnect
automatically in that case.
Libcommuni backend:
* Latest libcommuni 3.4.0 is now needed.
* Libcommuni backend has been improved to use the newest libcommuni
features.
* Ports can now be set in `service.irc_server` option and in the JID. When
'+' character is used before the port number, SSL is used automatically.
When port 6697 is used, SSL is used automatically too.
Swiften backend:
* Respect the resource when connecting to 3rd-party XMPP network.
Version 2.0.2 (2016-02-09):
General:
* Fix joining the room when using JID Escaping even for '@' character.
* Fix Raw XML mode - fixes the Swiften backend.
* Allow backends to set avatars to buddies in room - currently no backend
uses it.
* Set the room list per frontend user - this fixes possible information
for networks like Skype or Facebook where the room list is not global
per network.
* Support usage of aliases in the rooms, so backends can use the
network-based UID for the buddies in the room while still setting
user-friendly aliases to them.
* Fix leaving the room when user is connected to transport using two
clients, but only one of them joined the room and that one disconnects
the transport without leaving the room (For example when he just
quits the client).
XMPP frontend:
* Handle the XMPP VCard changes - updating avatar should work now for
backends supporting it.
Slack frontend:
* Slack frontend is now completely managed by the web interface, old
way of managing (".spectrum2 ..." commands sent to Spectrum 2 bot)
are not supported.
* Slack channels are now created automatically on Slack when you join them
using web-interface. The same applies also to the Main channel.
* Logging has been improved to show the name of Slack team for each log
line.
Libpurple backend:
* Forward the room topic to frontend.
* Fix joining the rooms on networks when the nickname in the room cannot
be changed (Skype or Facebook). Libpurple backend changes your nickname
to the right one in that case.
* Show the buddies aliases in the Facebook rooms instead of Facebook
buddies numbers.
Twitter backend:
* Fix compilation with newer gcc.
Swiften backend:
* Swiften backend works as before the frontends introduction.
Skype backend:
* The old skype backend has been removed. Use purple-skypeweb instead.
Web interface:
* Allow setting "port" and "base_location" in the config file.
* Allow maintaining joined rooms in the Web interface for the Slack
frontend.
* "[identity] name" config variables is now used as a name of the
transport.
Version 2.0.1 (2016-01-25):
General:
* Fix wrong nickname when joining room with some backends.
* Leave room when disconnected from 3rd-party network because of an error.
Fixes a bug when users were not able to rejoin the room after Spectrum 2
disconnected them from 3rd-party network.
* Fix building on Windows.
* Support case-sensitive buddy names transparently - boost_locale is now
needed as a new dependency.
Spectrum2_manager:
* Add simple web interface, can be tested using "spectrum2_manager server".
XMPP frontend:
* Show MUC feature in room disco#info response.
Slack frontend:
* Slack frontend is now working as Slack app, so you need to obtain the
client_id and client_secret from Slack to setup your own server and to
do the OAuth2 flow, you have to setup the Spectrum2_manager Server. Read
the documentation for more info.
* Fix OAuth2 registration flow.
* Fix multiple crashes when disconnected from Slack network or from
3rd-party network.
* Slack frontend should still be used only for testing, it is till under
the development.
Libpurple backend:
* Forward room list to frontend.
* Fix compatibility with latest telegram-purple - You mean need to
unregister the transport and register it again if you experience
compatibility problems.
Twitter backend:
* Fix default value of fetch timer.
* Disable useless Curl verbose output.
* Fix crash when populating roster when using Swiften 3.
* Do not set status message for buddies not in Friends list - fixes a bug
when buddies who are not in Friends list have been added to roster.
Version 2.0.0 (2015-12-29):
General:
* Fix compilation with new versions of Spectrum 2 dependencies.
* Added support for multiple frontends - Slack frontend is the first one.
* Log errors related to backend spawning (Show proper log message for
example when path to backend binary is not found).
* Set SQLite3 as default database backend.
* Fixed disconnecting from server caused by sending VCard response
with bad "from" attribute.
* Added Munin plugin (Thanks to Askovpen).
* Added support for more admin_jid JIDs (Thanks to Askovpen).
* Fixed allowed_servers option.
* Options from config file can now be set also using command line like
--service.jid=domain.tld .
* Do not send password in IQ-get registration response.
* Added support for AdHoc commands.
* Do not store buddies with empty name in database.
* Improved MySQL storage backend performance.
* Fix crash caused by two XMPP users using single PurpleAccount instance.
* Support for [registration] allowed_usernames.
Spectrum2_manager:
* Rewritten to provide more features. Check the documentation.
Libpurple:
* prpl-gg: Fetch the contact list properly (#252).
* Added support for prpl-novell as it was in Spectrum 1.
Twitter:
* Added Twitter support using Twitter backend. Thanks to Sarang and
Google Summer of Code.
Skype:
* Skype backend is now deprecated, use libpurple purple-skypeweb plugin
as a replacement.
Backend API:
* Added Python NetworkPlugin class, so it is now easier to write backends
in Python (Thanks to Sarang).
Version 2.0.0-beta2 (2012-03-28):
General:
* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
repeatedly.
* Backends related logs now contain the backend PID.
* Fixed username_mask setting.
* Added new fields into statistics (backends_crashed, messages related
stats).
* Chatstates are now not counted as incoming messages in stats.
* Log4cxx is now optional dependency. Without Log4cxx, Spectrum 2 logs
to standard output.
* Fixed crash when Log4cxx configuration file didn't exist.
* Admin can now see "Admin" contact in server-mode.
libpurple:
* Added initial support for MUC for prpl-jabber protocol.
LibCommuni IRC backend:
* Fixed sending/receiving UTF8 messages.
* Using the [registration] auto_register=1 config option, users don't
have to register manually when connecting IRC network.
Skype:
* Memory usage statistic now includes the Skype client.
* Fixed logging issue when the logs were not stored in the proper instance
directory.
* Skype backend includes also Skype client memory usage into the account.
* Working buddies adding/removing.
* Information about missed call is now forwarded to XMPP user.
* Fixed bug when Skype client instance wasn't killed by backend.
Version 2.0.0-beta (2012-02-28):
General:
* Added PostreSQL support (thanks to Jadestorm).
* Added XEP-0100 (Gateway interaction) support.
* Send presences only "from" bare JID (fixed bug with buddies appearing
twice in the roster and potential unregistering issues).
* Fixed potential MySQL/SQLite3 deadlocks.
* Fixed disconnecting in server-mode when client does not send unavailable
presence before disconnection.
* Fixed crash in server-mode when client send its custom jabber:iq:storage
payload.
* Fixed registration from Pidgin.
* Unsubscribe presence sent to some buddy doesn't disconnect the account.
* Remote Roster requests are not sent to resources, but to bare JID.
* Added automatic reconnection in case of non-fatal error.
* Added more error messages.
Skype:
* Initial support for Skype added, read more on
http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_Skype_backend
SMSTools3:
* Initial support for SMSTools3, read more on
http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_SMSTools3_backend
version 2.0.0 alpha (2011-12-06):
General:
* First Spectrum 2.0.0 alpha release, check more on
http://spectrum.im/projects/spectrum/wiki/Spectrum_200_alpha

View file

@ -1,91 +0,0 @@
FROM fedora:23
EXPOSE 5222
VOLUME ["/etc/spectrum2/transports", "/var/lib/spectrum2"]
ARG commit=unknown
RUN echo $commit
# Spectrum 2
RUN dnf install protobuf protobuf swiften gcc gcc-c++ make libpqxx-devel libpurple-devel protobuf-devel swiften-devel rpm-build avahi-devel boost-devel cmake cppunit-devel expat-devel libcommuni-devel libidn-devel libsqlite3x-devel log4cxx-devel gettext libgcrypt-devel libwebp-devel libpurple-devel zlib-devel json-glib-devel python-pip zlib-devel libjpeg-devel python-devel mysql-devel popt-devel git libevent-devel qt-devel dbus-glib-devel libcurl-devel wget mercurial libtool libgnome-keyring-devel nss-devel -y && \
echo "---> Installing Spectrum 2" && \
git clone git://github.com/hanzz/spectrum2.git && \
cd spectrum2 && \
./packaging/fedora/build_rpm.sh && \
rpm -U /root/rpmbuild/RPMS/x86_64/*.rpm && \
cp ./packaging/docker/run.sh /run.sh && \
cd .. && \
rm -rf spectrum2 && \
rm -rf ~/rpmbuild && \
echo "---> Installing purple-facebook" && \
wget https://github.com/dequis/purple-facebook/releases/download/v0.9.5-9ff9acf9fa14/purple-facebook-0.9.5-9ff9acf9fa14.tar.gz && \
tar -xf purple-facebook-0.9.5-9ff9acf9fa14.tar.gz && \
cd purple-facebook-0.9.5-9ff9acf9fa14 && \
./autogen.sh && \
./configure && \
make && \
make install && \
cd .. && \
rm -rf purple-facebook* && \
echo "---> Installing skype4pidgin" && \
git clone git://github.com/EionRobb/skype4pidgin.git && \
cd skype4pidgin/skypeweb && \
make CFLAGS=-DFEDORA=1 && \
make install && \
cd ../.. && \
rm -rf skype4pidgin && \
echo "---> Installing transwhat" && \
pip install --pre e4u protobuf python-dateutil yowsup2 Pillow==2.9.0 &&\
git clone git://github.com/stv0g/transwhat.git &&\
git clone git://github.com/tgalal/yowsup.git &&\
cd transwhat &&\
git worktree add /opt/transwhat &&\
cd .. &&\
cd yowsup &&\
cp -R yowsup /opt/transwhat/yowsup &&\
cd .. &&\
rm -r transwhat &&\
rm -r yowsup &&\
rm -rf /opt/transwhat/.git &&\
rm -rf /opt/transwhat/.gitignore &&\
echo "---> Installing Telegram" && \
git clone --recursive https://github.com/majn/telegram-purple && \
cd telegram-purple && \
./configure && \
make && \
make install && \
cd .. && \
rm -rf telegram-purple && \
echo "---> Install Discord" && \
git clone https://github.com/EionRobb/purple-discord.git && \
cd purple-discord && \
make && \
make install && \
cd .. && \
rm -rf purple-discord && \
echo "---> Install Steam" && \
git clone https://github.com/EionRobb/pidgin-opensteamworks.git && \
cd pidgin-opensteamworks/steam-mobile && \
make && \
make install && \
cd ../.. && \
rm -rf pidgin-opensteamworks && \
echo "---> cleanup" && \
rm -rf /usr/share/locale/* && \
rm -rf /usr/share/doc/* && \
rm -rf /usr/share/icons/* && \
rm -rf /usr/share/cracklib* && \
rm -rf /usr/share/hwdata* && \
rm -rf /usr/lib64/libQtGui* && \
rm -rf /usr/lib64/libQtSvg* && \
rm -rf /usr/lib64/libQtDeclarative* && \
rm -rf /usr/lib64/libQtOpenGL* && \
rm -rf /usr/lib64/libQtScriptTools* && \
rm -rf /usr/lib64/libQtMultimedia* && \
rm -rf /usr/lib64/libQtHelp* && \
rm -rf /usr/lib64/libQtDesigner* && \
rm -rf /usr/lib64/libQt3* && \
dnf remove protobuf-devel swiften-devel gcc gcc-c++ libpqxx-devel libevent-devel qt-devel dbus-glib-devel libpurple-devel make rpm-build avahi-devel boost-devel cmake cppunit-devel expat-devel libcommuni-devel libidn-devel libsqlite3x-devel libgcrypt-devel libwebp-devel libpurple-devel zlib-devel json-glib-devel zlib-devel libjpeg-devel python-devel log4cxx-devel mysql-devel popt-devel libcurl-devel spectrum2-debuginfo yum perl wget -y && \
dnf clean all -y && \
rm -rf /var/lib/rpm/*
CMD "/run.sh"

3
Gemfile Normal file
View file

@ -0,0 +1,3 @@
source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins
gem 'jekyll-sitemap', group: :jekyll_plugins

201
Gemfile.lock Normal file
View file

@ -0,0 +1,201 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.7)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
colorator (1.1.0)
ethon (0.10.1)
ffi (>= 1.3.0)
execjs (2.7.0)
faraday (0.12.1)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
forwardable-extended (2.6.0)
gemoji (3.0.0)
github-pages (134)
activesupport (= 4.2.7)
github-pages-health-check (= 1.3.3)
jekyll (= 3.4.3)
jekyll-avatar (= 0.4.2)
jekyll-coffeescript (= 1.0.1)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.9.2)
jekyll-gist (= 1.4.0)
jekyll-github-metadata (= 2.3.1)
jekyll-mentions (= 1.2.0)
jekyll-optional-front-matter (= 0.1.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.1.0)
jekyll-redirect-from (= 0.12.1)
jekyll-relative-links (= 0.4.0)
jekyll-sass-converter (= 1.5.0)
jekyll-seo-tag (= 2.2.0)
jekyll-sitemap (= 1.0.0)
jekyll-swiss (= 0.4.0)
jekyll-theme-architect (= 0.0.4)
jekyll-theme-cayman (= 0.0.4)
jekyll-theme-dinky (= 0.0.4)
jekyll-theme-hacker (= 0.0.4)
jekyll-theme-leap-day (= 0.0.4)
jekyll-theme-merlot (= 0.0.4)
jekyll-theme-midnight (= 0.0.4)
jekyll-theme-minimal (= 0.0.4)
jekyll-theme-modernist (= 0.0.4)
jekyll-theme-primer (= 0.1.8)
jekyll-theme-slate (= 0.0.4)
jekyll-theme-tactile (= 0.0.4)
jekyll-theme-time-machine (= 0.0.4)
jekyll-titles-from-headings (= 0.1.5)
jemoji (= 0.8.0)
kramdown (= 1.13.2)
liquid (= 3.0.6)
listen (= 3.0.6)
mercenary (~> 0.3)
minima (= 2.0.0)
rouge (= 1.11.1)
terminal-table (~> 1.4)
github-pages-health-check (1.3.3)
addressable (~> 2.3)
net-dns (~> 0.8)
octokit (~> 4.0)
public_suffix (~> 2.0)
typhoeus (~> 0.7)
html-pipeline (2.5.0)
activesupport (>= 2)
nokogiri (>= 1.4)
i18n (0.8.1)
jekyll (3.4.3)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 3.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (~> 1.7)
safe_yaml (~> 1.0)
jekyll-avatar (0.4.2)
jekyll (~> 3.0)
jekyll-coffeescript (1.0.1)
coffee-script (~> 2.2)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.9.2)
jekyll (~> 3.3)
jekyll-gist (1.4.0)
octokit (~> 4.2)
jekyll-github-metadata (2.3.1)
jekyll (~> 3.1)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.2.0)
activesupport (~> 4.0)
html-pipeline (~> 2.3)
jekyll (~> 3.0)
jekyll-optional-front-matter (0.1.2)
jekyll (~> 3.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.1.0)
jekyll (~> 3.0)
jekyll-redirect-from (0.12.1)
jekyll (~> 3.3)
jekyll-relative-links (0.4.0)
jekyll (~> 3.3)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-seo-tag (2.2.0)
jekyll (~> 3.3)
jekyll-sitemap (1.0.0)
jekyll (~> 3.3)
jekyll-swiss (0.4.0)
jekyll-theme-architect (0.0.4)
jekyll (~> 3.3)
jekyll-theme-cayman (0.0.4)
jekyll (~> 3.3)
jekyll-theme-dinky (0.0.4)
jekyll (~> 3.3)
jekyll-theme-hacker (0.0.4)
jekyll (~> 3.3)
jekyll-theme-leap-day (0.0.4)
jekyll (~> 3.3)
jekyll-theme-merlot (0.0.4)
jekyll (~> 3.3)
jekyll-theme-midnight (0.0.4)
jekyll (~> 3.3)
jekyll-theme-minimal (0.0.4)
jekyll (~> 3.3)
jekyll-theme-modernist (0.0.4)
jekyll (~> 3.3)
jekyll-theme-primer (0.1.8)
jekyll (~> 3.3)
jekyll-theme-slate (0.0.4)
jekyll (~> 3.3)
jekyll-theme-tactile (0.0.4)
jekyll (~> 3.3)
jekyll-theme-time-machine (0.0.4)
jekyll (~> 3.3)
jekyll-titles-from-headings (0.1.5)
jekyll (~> 3.3)
jekyll-watch (1.5.0)
listen (~> 3.0, < 3.1)
jemoji (0.8.0)
activesupport (~> 4.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0)
json (1.8.6)
kramdown (1.13.2)
liquid (3.0.6)
listen (3.0.6)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9.7)
mercenary (0.3.6)
mini_portile2 (2.1.0)
minima (2.0.0)
minitest (5.10.1)
multipart-post (2.0.0)
net-dns (0.8.0)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.14.0)
forwardable-extended (~> 2.6)
public_suffix (2.0.5)
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
rouge (1.11.1)
safe_yaml (1.0.4)
sass (3.4.23)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
terminal-table (1.7.3)
unicode-display_width (~> 1.1.1)
thread_safe (0.3.6)
typhoeus (0.8.0)
ethon (>= 0.8.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
unicode-display_width (1.1.3)
PLATFORMS
ruby
DEPENDENCIES
github-pages
jekyll-sitemap
BUNDLED WITH
1.15.3

View file

@ -1,9 +1,42 @@
[![Build Status](https://travis-ci.org/SpectrumIM/spectrum2.svg?branch=master)](https://travis-ci.org/SpectrumIM/spectrum2) # Jekyll-Bootstrap
![](http://spectrum.im/animation.gif) The quickest way to start and publish your Jekyll powered blog. 100% compatible with GitHub pages
Spectrum 2 is an open source instant messaging transport. ## Usage
It allows users to chat together even when they are using different IM networks. For all usage and documentation please see: <http://jekyllbootstrap.com>
It acts as a transport layer between the users as showed in the animation above. ## Version
0.2.13 - stable and versioned using [semantic versioning](http://semver.org/).
## Contributing
This repository tracks 2 projects:
- **Jekyll-Bootstrap Framework.**
The framework for which users should clone and build their blog on top of is available in the master branch.
To contribute to the framework please make sure to checkout your branch based on `jb-development`!!
This is very important as it allows me to accept your pull request without having to publish a public version release.
Small, atomic Features, bugs, etc.
Use the `jb-development` branch but note it will likely change fast as pull requests are accepted.
Please rebase as often as possible when working.
Work on small, atomic features/bugs to avoid upstream commits affecting/breaking your development work.
For Big Features or major API extensions/edits:
This is the one case where I'll accept pull-requests based off the master branch.
This allows you to work in isolation but it means I'll have to manually merge your work into the next public release.
Translation : it might take a bit longer so please be patient! (but sincerely thank you).
- **Jekyll-Bootstrap Documentation Website.**
The documentation website at <http://jekyllbootstrap.com> is maintained in the gh-pages branch.
Please fork and contribute documentation additions to this branch only.
The master and gh-pages branch do not share the same ancestry. Please treat them as completely separate git repositories!
## License
[Creative Commons](http://creativecommons.org/licenses/by-nc-sa/3.0/)

308
Rakefile Normal file
View file

@ -0,0 +1,308 @@
require "rubygems"
require 'rake'
require 'yaml'
require 'time'
SOURCE = "."
CONFIG = {
'version' => "0.2.13",
'themes' => File.join(SOURCE, "_includes", "themes"),
'layouts' => File.join(SOURCE, "_layouts"),
'posts' => File.join(SOURCE, "_posts"),
'post_ext' => "md",
'theme_package_version' => "0.1.0"
}
# Path configuration helper
module JB
class Path
SOURCE = "."
Paths = {
:layouts => "_layouts",
:themes => "_includes/themes",
:theme_assets => "assets/themes",
:theme_packages => "_theme_packages",
:posts => "_posts"
}
def self.base
SOURCE
end
# build a path relative to configured path settings.
def self.build(path, opts = {})
opts[:root] ||= SOURCE
path = "#{opts[:root]}/#{Paths[path.to_sym]}/#{opts[:node]}".split("/")
path.compact!
File.__send__ :join, path
end
end #Path
end #JB
# Usage: rake post title="A Title" [date="2012-02-09"]
desc "Begin a new post in #{CONFIG['posts']}"
task :post do
abort("rake aborted: '#{CONFIG['posts']}' directory not found.") unless FileTest.directory?(CONFIG['posts'])
title = ENV["title"] || "new-post"
slug = title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
begin
date = (ENV['date'] ? Time.parse(ENV['date']) : Time.now).strftime('%Y-%m-%d')
rescue Exception => e
puts "Error - date format must be YYYY-MM-DD, please check you typed it correctly!"
exit -1
end
filename = File.join(CONFIG['posts'], "#{date}-#{slug}.#{CONFIG['post_ext']}")
if File.exist?(filename)
abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
end
puts "Creating new post: #{filename}"
open(filename, 'w') do |post|
post.puts "---"
post.puts "layout: post"
post.puts "title: \"#{title.gsub(/-/,' ')}\""
post.puts 'description: ""'
post.puts "category: "
post.puts "tags: []"
post.puts "---"
post.puts "{% include JB/setup %}"
end
end # task :post
# Usage: rake page name="about.html"
# You can also specify a sub-directory path.
# If you don't specify a file extention we create an index.html at the path specified
desc "Create a new page."
task :page do
name = ENV["name"] || "new-page.md"
filename = File.join(SOURCE, "#{name}")
filename = File.join(filename, "index.html") if File.extname(filename) == ""
title = File.basename(filename, File.extname(filename)).gsub(/[\W\_]/, " ").gsub(/\b\w/){$&.upcase}
if File.exist?(filename)
abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
end
mkdir_p File.dirname(filename)
puts "Creating new page: #{filename}"
open(filename, 'w') do |post|
post.puts "---"
post.puts "layout: page"
post.puts "title: \"#{title}\""
post.puts 'description: ""'
post.puts "---"
post.puts "{% include JB/setup %}"
end
end # task :page
desc "Launch preview environment"
task :preview do
system "jekyll --auto --server"
end # task :preview
# Public: Alias - Maintains backwards compatability for theme switching.
task :switch_theme => "theme:switch"
namespace :theme do
# Public: Switch from one theme to another for your blog.
#
# name - String, Required. name of the theme you want to switch to.
# The the theme must be installed into your JB framework.
#
# Examples
#
# rake theme:switch name="the-program"
#
# Returns Success/failure messages.
desc "Switch between Jekyll-bootstrap themes."
task :switch do
theme_name = ENV["name"].to_s
theme_path = File.join(CONFIG['themes'], theme_name)
settings_file = File.join(theme_path, "settings.yml")
non_layout_files = ["settings.yml"]
abort("rake aborted: name cannot be blank") if theme_name.empty?
abort("rake aborted: '#{theme_path}' directory not found.") unless FileTest.directory?(theme_path)
abort("rake aborted: '#{CONFIG['layouts']}' directory not found.") unless FileTest.directory?(CONFIG['layouts'])
Dir.glob("#{theme_path}/*") do |filename|
next if non_layout_files.include?(File.basename(filename).downcase)
puts "Generating '#{theme_name}' layout: #{File.basename(filename)}"
open(File.join(CONFIG['layouts'], File.basename(filename)), 'w') do |page|
if File.basename(filename, ".html").downcase == "default"
page.puts "---"
page.puts File.read(settings_file) if File.exist?(settings_file)
page.puts "---"
else
page.puts "---"
page.puts "layout: default"
page.puts "---"
end
page.puts "{% include JB/setup %}"
page.puts "{% include themes/#{theme_name}/#{File.basename(filename)} %}"
end
end
puts "=> Theme successfully switched!"
puts "=> Reload your web-page to check it out =)"
end # task :switch
# Public: Install a theme using the theme packager.
# Version 0.1.0 simple 1:1 file matching.
#
# git - String, Optional path to the git repository of the theme to be installed.
# name - String, Optional name of the theme you want to install.
# Passing name requires that the theme package already exist.
#
# Examples
#
# rake theme:install git="https://github.com/jekyllbootstrap/theme-twitter.git"
# rake theme:install name="cool-theme"
#
# Returns Success/failure messages.
desc "Install theme"
task :install do
if ENV["git"]
manifest = theme_from_git_url(ENV["git"])
name = manifest["name"]
else
name = ENV["name"].to_s.downcase
end
packaged_theme_path = JB::Path.build(:theme_packages, :node => name)
abort("rake aborted!
=> ERROR: 'name' cannot be blank") if name.empty?
abort("rake aborted!
=> ERROR: '#{packaged_theme_path}' directory not found.
=> Installable themes can be added via git. You can find some here: http://github.com/jekyllbootstrap
=> To download+install run: `rake theme:install git='[PUBLIC-CLONE-URL]'`
=> example : rake theme:install git='git@github.com:jekyllbootstrap/theme-the-program.git'
") unless FileTest.directory?(packaged_theme_path)
manifest = verify_manifest(packaged_theme_path)
# Get relative paths to packaged theme files
# Exclude directories as they'll be recursively created. Exclude meta-data files.
packaged_theme_files = []
FileUtils.cd(packaged_theme_path) {
Dir.glob("**/*.*") { |f|
next if ( FileTest.directory?(f) || f =~ /^(manifest|readme|packager)/i )
packaged_theme_files << f
}
}
# Mirror each file into the framework making sure to prompt if already exists.
packaged_theme_files.each do |filename|
file_install_path = File.join(JB::Path.base, filename)
if File.exist? file_install_path
next if ask("#{file_install_path} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
else
mkdir_p File.dirname(file_install_path)
cp_r File.join(packaged_theme_path, filename), file_install_path
end
end
puts "=> #{name} theme has been installed!"
puts "=> ---"
if ask("=> Want to switch themes now?", ['y', 'n']) == 'y'
system("rake switch_theme name='#{name}'")
end
end
# Public: Package a theme using the theme packager.
# The theme must be structured using valid JB API.
# In other words packaging is essentially the reverse of installing.
#
# name - String, Required name of the theme you want to package.
#
# Examples
#
# rake theme:package name="twitter"
#
# Returns Success/failure messages.
desc "Package theme"
task :package do
name = ENV["name"].to_s.downcase
theme_path = JB::Path.build(:themes, :node => name)
asset_path = JB::Path.build(:theme_assets, :node => name)
abort("rake aborted: name cannot be blank") if name.empty?
abort("rake aborted: '#{theme_path}' directory not found.") unless FileTest.directory?(theme_path)
abort("rake aborted: '#{asset_path}' directory not found.") unless FileTest.directory?(asset_path)
## Mirror theme's template directory (_includes)
packaged_theme_path = JB::Path.build(:themes, :root => JB::Path.build(:theme_packages, :node => name))
mkdir_p packaged_theme_path
cp_r theme_path, packaged_theme_path
## Mirror theme's asset directory
packaged_theme_assets_path = JB::Path.build(:theme_assets, :root => JB::Path.build(:theme_packages, :node => name))
mkdir_p packaged_theme_assets_path
cp_r asset_path, packaged_theme_assets_path
## Log packager version
packager = {"packager" => {"version" => CONFIG["theme_package_version"].to_s } }
open(JB::Path.build(:theme_packages, :node => "#{name}/packager.yml"), "w") do |page|
page.puts packager.to_yaml
end
puts "=> '#{name}' theme is packaged and available at: #{JB::Path.build(:theme_packages, :node => name)}"
end
end # end namespace :theme
# Internal: Download and process a theme from a git url.
# Notice we don't know the name of the theme until we look it up in the manifest.
# So we'll have to change the folder name once we get the name.
#
# url - String, Required url to git repository.
#
# Returns theme manifest hash
def theme_from_git_url(url)
tmp_path = JB::Path.build(:theme_packages, :node => "_tmp")
abort("rake aborted: system call to git clone failed") if !system("git clone #{url} #{tmp_path}")
manifest = verify_manifest(tmp_path)
new_path = JB::Path.build(:theme_packages, :node => manifest["name"])
if File.exist?(new_path) && ask("=> #{new_path} theme package already exists. Override?", ['y', 'n']) == 'n'
remove_dir(tmp_path)
abort("rake aborted: '#{manifest["name"]}' already exists as theme package.")
end
remove_dir(new_path) if File.exist?(new_path)
mv(tmp_path, new_path)
manifest
end
# Internal: Process theme package manifest file.
#
# theme_path - String, Required. File path to theme package.
#
# Returns theme manifest hash
def verify_manifest(theme_path)
manifest_path = File.join(theme_path, "manifest.yml")
manifest_file = File.open( manifest_path )
abort("rake aborted: repo must contain valid manifest.yml") unless File.exist? manifest_file
manifest = YAML.load( manifest_file )
manifest_file.close
manifest
end
def ask(message, valid_options)
if valid_options
answer = get_stdin("#{message} #{valid_options.to_s.gsub(/"/, '').gsub(/, /,'/')} ") while !valid_options.include?(answer)
else
answer = get_stdin(message)
end
answer
end
def get_stdin(message)
print message
STDIN.gets.chomp
end
#Load custom rake scripts
Dir['_rake/*.rake'].each { |r| load r }

128
_config.yml Normal file
View file

@ -0,0 +1,128 @@
# This is the default format.
# For more see: https://github.com/mojombo/jekyll/wiki/Permalinks
#permalink: /:categories/:year/:month/:day/:title
exclude: [".rvmrc", ".rbenv-version", "README.md", "Rakefile", "changelog.md"]
#highlighter: pygments
# Themes are encouraged to use these universal variables
# so be sure to set them if your theme uses them.
#
title : Spectrum 2
tagline: Spectrum 2 transport
author :
name : Jan Kaluza
email : hanzz.k@gmail.com
github : hanzz
# twitter : username
# feedburner : feedname
# The production_url is only used when full-domain names are needed
# such as sitemap.txt
# Most places will/should use BASE_PATH to make the urls
#
# If you have set a CNAME (pages.github.com) set your custom domain here.
# Else if you are pushing to username.github.com, replace with your username.
# Finally if you are pushing to a GitHub project page, include the project name at the end.
#
production_url : http://spectrum.im
# All Jekyll-Bootstrap specific configurations are namespaced into this hash
#
JB :
version : 0.2.13
# All links will be namespaced by BASE_PATH if defined.
# Links in your website should always be prefixed with {{BASE_PATH}}
# however this value will be dynamically changed depending on your deployment situation.
#
# CNAME (http://yourcustomdomain.com)
# DO NOT SET BASE_PATH
# (urls will be prefixed with "/" and work relatively)
#
# GitHub Pages (http://username.github.com)
# DO NOT SET BASE_PATH
# (urls will be prefixed with "/" and work relatively)
#
# GitHub Project Pages (http://username.github.com/project-name)
#
# A GitHub Project site exists in the `gh-pages` branch of one of your repositories.
# REQUIRED! Set BASE_PATH to: http://username.github.com/project-name
#
# CAUTION:
# - When in Localhost, your site will run from root "/" regardless of BASE_PATH
# - Only the following values are falsy: ["", null, false]
# - When setting BASE_PATH it must be a valid url.
# This means always setting the protocol (http|https) or prefixing with "/"
BASE_PATH : http://spectrum.im
# By default, the asset_path is automatically defined relative to BASE_PATH plus the enabled theme.
# ex: [BASE_PATH]/assets/themes/[THEME-NAME]
#
# Override this by defining an absolute path to assets here.
# ex:
# http://s3.amazonaws.com/yoursite/themes/watermelon
# /assets
#
ASSET_PATH : http://spectrum.im
# These paths are to the main pages Jekyll-Bootstrap ships with.
# Some JB helpers refer to these paths; change theme here if needed.
#
#archive_path: /archive.html
#categories_path : /categories.html
#tags_path : /tags.html
# Settings for comments helper
# Set 'provider' to the comment provider you want to use.
# Set 'provider' to false to turn commenting off globally.
#
# comments :
# provider : disqus
# disqus :
# short_name : jekyllbootstrap
# livefyre :
# site_id : 123
# intensedebate :
# account : 123abc
# facebook :
# appid : 123
# num_posts: 5
# width: 580
# colorscheme: light
# Settings for analytics helper
# Set 'provider' to the analytics provider you want to use.
# Set 'provider' to false to turn analytics off globally.
#
# analytics :
# provider : google
# google :
# tracking_id : 'UA-123-12'
# getclicky :
# site_id :
# mixpanel :
# token : '_MIXPANEL_TOKEN_'
# Settings for sharing helper.
# Sharing is for things like tweet, plusone, like, reddit buttons etc.
# Set 'provider' to the sharing provider you want to use.
# Set 'provider' to false to turn sharing off globally.
#
# sharing :
# provider : false
# Settings for all other include helpers can be defined by creating
# a hash with key named for the given helper. ex:
#
# pages_list :
# provider : "custom"
#
# Setting any helper's provider to 'custom' will bypass the helper code
# and include your custom code. Your custom file must be defined at:
# ./_includes/custom/[HELPER]
# where [HELPER] is the name of the helper you are overriding.
gems:
- jekyll-redirect-from
- jekyll-sitemap

14
_includes/JB/analytics Normal file
View file

@ -0,0 +1,14 @@
{% if site.safe and site.JB.analytics.provider and page.JB.analytics != false %}
{% case site.JB.analytics.provider %}
{% when "google" %}
{% include JB/analytics-providers/google %}
{% when "getclicky" %}
{% include JB/analytics-providers/getclicky %}
{% when "mixpanel" %}
{% include JB/analytics-providers/mixpanel %}
{% when "custom" %}
{% include custom/analytics %}
{% endcase %}
{% endif %}

View file

@ -0,0 +1,12 @@
<script type="text/javascript">
var clicky_site_ids = clicky_site_ids || [];
clicky_site_ids.push({{ site.JB.analytics.getclicky.site_id }});
(function() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = '//static.getclicky.com/js';
( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s );
})();
</script>
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/{{ site.JB.analytics.getclicky.site_id }}ns.gif" /></p></noscript>

View file

@ -0,0 +1,11 @@
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{{ site.JB.analytics.google.tracking_id }}']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

View file

@ -0,0 +1,11 @@
<script type="text/javascript">
var mpq = [];
mpq.push(["init", "{{ site.JB.analytics.mixpanel.token}}"]);
(function(){var b,a,e,d,c;b=document.createElement("script");b.type="text/javascript";
b.async=true;b.src=(document.location.protocol==="https:"?"https:":"http:")+
"//api.mixpanel.com/site_media/js/api/mixpanel.js";a=document.getElementsByTagName("script")[0];
a.parentNode.insertBefore(b,a);e=function(f){return function(){mpq.push(
[f].concat(Array.prototype.slice.call(arguments,0)))}};d=["init","track","track_links",
"track_forms","register","register_once","identify","name_tag","set_config"];for(c=0;c<
d.length;c++){mpq[d[c]]=e(d[c])}})();
</script>

View file

@ -0,0 +1,37 @@
{% comment %}<!--
The categories_list include is a listing helper for categories.
Usage:
1) assign the 'categories_list' variable to a valid array of tags.
2) include JB/categories_list
example:
<ul>
{% assign categories_list = site.categories %}
{% include JB/categories_list %}
</ul>
Notes:
Categories can be either a Hash of Category objects (hashes) or an Array of category-names (strings).
The encapsulating 'if' statement checks whether categories_list is a Hash or Array.
site.categories is a Hash while page.categories is an array.
This helper can be seen in use at: ../_layouts/default.html
-->{% endcomment %}
{% if site.JB.categories_list.provider == "custom" %}
{% include custom/categories_list %}
{% else %}
{% if categories_list.first[0] == null %}
{% for category in categories_list %}
<li><a href="{{ BASE_PATH }}{{ site.JB.categories_path }}#{{ category }}-ref">
{{ category | join: "/" }} <span>{{ site.categories[category].size }}</span>
</a></li>
{% endfor %}
{% else %}
{% for category in categories_list %}
<li><a href="{{ BASE_PATH }}{{ site.JB.categories_path }}#{{ category[0] }}-ref">
{{ category[0] | join: "/" }} <span>{{ category[1].size }}</span>
</a></li>
{% endfor %}
{% endif %}
{% endif %}
{% assign categories_list = nil %}

16
_includes/JB/comments Normal file
View file

@ -0,0 +1,16 @@
{% if site.JB.comments.provider and page.comments != false %}
{% case site.JB.comments.provider %}
{% when "disqus" %}
{% include JB/comments-providers/disqus %}
{% when "livefyre" %}
{% include JB/comments-providers/livefyre %}
{% when "intensedebate" %}
{% include JB/comments-providers/intensedebate %}
{% when "facebook" %}
{% include JB/comments-providers/facebook %}
{% when "custom" %}
{% include custom/comments %}
{% endcase %}
{% endif %}

View file

@ -0,0 +1,14 @@
<div id="disqus_thread"></div>
<script type="text/javascript">
{% if site.safe == false %}var disqus_developer = 1;{% endif %}
var disqus_shortname = '{{ site.JB.comments.disqus.short_name }}'; // required: replace example with your forum shortname
{% if page.wordpress_id %}var disqus_identifier = '{{page.wordpress_id}} {{site.production_url}}/?p={{page.wordpress_id}}';{% endif %}
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>

View file

@ -0,0 +1,9 @@
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId={{ site.JB.comments.facebook.appid }}";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<div class="fb-comments" data-href="{{ site.production_url }}" data-num-posts="{{ site.JB.comments.facebook.num_posts }}" data-width="{{ site.JB.comments.facebook.width }}" data-colorscheme="{{ site.JB.comments.facebook.colorscheme }}"></div>

View file

@ -0,0 +1,6 @@
<script>
var idcomments_acct = '{{ site.JB.comments.intensedebate.account }}';
var idcomments_post_id;
var idcomments_post_url;
</script>
<script type="text/javascript" src="http://www.intensedebate.com/js/genericLinkWrapperV2.js"></script>

View file

@ -0,0 +1,6 @@
<script type='text/javascript' src='http://zor.livefyre.com/wjs/v1.0/javascripts/livefyre_init.js'></script>
<script type='text/javascript'>
var fyre = LF({
site_id: {{ site.JB.comments.livefyre.site_id }}
});
</script>

32
_includes/JB/liquid_raw Normal file
View file

@ -0,0 +1,32 @@
{% comment%}<!--
The liquid_raw helper is a way to display raw liquid code, as opposed to parsing it.
Normally you'd use Liquid's built in 'raw' tag.
The problem is GitHub Jekyll does not support the current Liquid release.
GitHub Jekyll supports the deprecated 'literal' tag.
Using one will break the other if you plan to deploy to GitHub pages.
see: https://github.com/mojombo/jekyll/issues/425
Since I don't want to mess with Liquid versions, I'll just rewrite the way I
intend to give liquid examples. It's not an elegant by any means:
Usage:
1) Define a 'text' variable with the block of liquid code you intend to display.
2) Pass the text variable to include JB/liquid_raw
example:
{% capture text %}|.% for tag in tags_list %.|
<li><a href="|.{ site.var.tags_path }.||.{ tag[0] }.|-ref">|.{ tag[0] }.| <span>|.{tag[1].size}.|</span></a></li>
|.% endfor %.|
|.% assign tags_list = null %.|{% endcapture %}
{% include JB/liquid_raw %}
As seen here, you must use "|." and ".|" as opening and closing brackets.
-->{% endcomment%}
{% if site.JB.liquid_raw.provider == "custom" %}
{% include custom/liquid_raw %}
{% else %}
<pre><code>{{text | replace:"|.", "&#123;" | replace:".|", "&#125;" | replace:">", "&gt;" | replace:"<", "&lt;" }}</code></pre>
{% endif %}
{% assign text = nil %}

39
_includes/JB/pages_list Normal file
View file

@ -0,0 +1,39 @@
{% comment %}<!--
The pages_list include is a listing helper.
Usage:
1) assign the 'pages_list' variable to a valid array of pages or posts.
2) include JB/pages_list
example:
<ul>
{% assign pages_list = site.pages %}
{% include JB/pages_list %}
</ul>
Grouping: (optional):
assign the 'group' variable to constrain the list to only pages/posts
in the given group. Note you must define the group manually in the page/post
meta-data to use this feature.
Grouping is mainly helpful for non-post pages.
If you want to group posts, it's easier/better to tag them, then pass the tagged posts array.
i.e. site.tags.cool_tag (this returns an array of posts tagged: cool_tag)
This helper can be seen in use at: ../_layouts/default.html
-->{% endcomment %}
{% if site.JB.pages_list.provider == "custom" %}
{% include custom/pages_list %}
{% else %}
{% for node in pages_list %}
{% if node.title != null %}
{% if group == null or group == node.group %}
{% if page.url == node.url %}
<li class="active"><a href="{{ BASE_PATH }}{{node.url}}" class="active">{{node.title}}</a></li>
{% else %}
<li><a href="{{ BASE_PATH }}{{node.url}}">{{node.title}}</a></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% assign pages_list = nil %}
{% assign group = nil %}

View file

@ -0,0 +1,55 @@
{% comment %}<!--
Collate_posts helper. Collated posts by year and month.
Usage:
1) assign the 'posts_collate' variable to a valid array of posts.
2) include JB/posts_collate
example:
{% assign posts_collate = site.posts %}
{% include JB/posts_collate %}
Ordering:
Posts are displayed in reverse chronological order.
For normal chronological order:
1) Change the for loop to this:
=> 'for post in site.posts reversed'
2) Next make sure to change 'post.previous.date' to:
=> 'post.next.date'
-->{% endcomment %}
{% if site.JB.posts_collate.provider == "custom" %}
{% include custom/posts_collate %}
{% else %}
{% for post in posts_collate %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}
{% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
{% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}
{% if forloop.first %}
<h2>{{this_year}}</h2>
<h3>{{this_month}}</h3>
<ul>
{% endif %}
<li><span>{{ post.date | date: "%B %e, %Y" }}</span> &raquo; <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
{% if forloop.last %}
</ul>
{% else %}
{% if this_year != next_year %}
</ul>
<h2>{{next_year}}</h2>
<h3>{{next_month}}</h3>
<ul>
{% else %}
{% if this_month != next_month %}
</ul>
<h3>{{next_month}}</h3>
<ul>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% assign posts_collate = nil %}

22
_includes/JB/setup Normal file
View file

@ -0,0 +1,22 @@
{% capture jbcache %}
<!--
- Dynamically set liquid variables for working with URLs/paths
-->
{% if site.JB.setup.provider == "custom" %}
{% include custom/setup %}
{% else %}
{% if site.safe and site.JB.BASE_PATH and site.JB.BASE_PATH != '' %}
{% assign BASE_PATH = site.JB.BASE_PATH %}
{% assign HOME_PATH = site.JB.BASE_PATH %}
{% else %}
{% assign BASE_PATH = nil %}
{% assign HOME_PATH = "/" %}
{% endif %}
{% if site.JB.ASSET_PATH %}
{% assign ASSET_PATH = site.JB.ASSET_PATH %}
{% else %}
{% capture ASSET_PATH %}{{ BASE_PATH }}/assets/themes/{{ layout.theme.name }}{% endcapture %}
{% endif %}
{% endif %}
{% endcapture %}{% assign jbcache = nil %}

8
_includes/JB/sharing Normal file
View file

@ -0,0 +1,8 @@
{% if site.safe and site.JB.sharing.provider and page.JB.sharing != false %}
{% case site.JB.sharing.provider %}
{% when "custom" %}
{% include custom/sharing %}
{% endcase %}
{% endif %}

33
_includes/JB/tags_list Normal file
View file

@ -0,0 +1,33 @@
{% comment %}<!--
The tags_list include is a listing helper for tags.
Usage:
1) assign the 'tags_list' variable to a valid array of tags.
2) include JB/tags_list
example:
<ul>
{% assign tags_list = site.tags %}
{% include JB/tags_list %}
</ul>
Notes:
Tags can be either a Hash of tag objects (hashes) or an Array of tag-names (strings).
The encapsulating 'if' statement checks whether tags_list is a Hash or Array.
site.tags is a Hash while page.tags is an array.
This helper can be seen in use at: ../_layouts/default.html
-->{% endcomment %}
{% if site.JB.tags_list.provider == "custom" %}
{% include custom/tags_list %}
{% else %}
{% if tags_list.first[0] == null %}
{% for tag in tags_list %}
<li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag }}-ref">{{ tag }} <span>{{ site.tags[tag].size }}</span></a></li>
{% endfor %}
{% else %}
{% for tag in tags_list %}
<li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag[0] }}-ref">{{ tag[0] }} <span>{{ tag[1].size }}</span></a></li>
{% endfor %}
{% endif %}
{% endif %}
{% assign tags_list = nil %}

View file

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports" />
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all">
<title>Spectrum 2</title>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<a id="forkme_banner" href="https://github.com/SpectrumIM/spectrum2">View on GitHub</a>
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;"/>
<section id="menu" style="text-align: center;">
<a class="menuitem" href="http://spectrum.im">About</a>
<a class="menuitem" href="http://spectrum.im/documentation">Documentation</a>
<a class="menuitem" href="http://spectrum.im/download">Download</a>
<a class="menuitem" href="http://spectrum.im/discussion">Discussion</a>
<a class="menuitem" href="https://github.com/SpectrumIM/spectrum2/issues">Issue tracker</a>
</section>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright">Spectrum 2 maintained by <a href="https://github.com/SpectrumIM">Spectrum Transports Team</a></p>
</footer>
</div>
</body>
</html>

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports" />
<link href="/css/style_config.css" rel="stylesheet" type="text/css" media="all">
<title>Spectrum 2</title>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner2">
<a id="forkme_banner" href="https://github.com/SpectrumIM/spectrum2">View on GitHub</a>
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;"/>
<section id="menu" style="text-align: center;">
<a class="menuitem" href="http://spectrum.im">About</a>
<a class="menuitem" href="http://spectrum.im/documentation">Documentation</a>
<a class="menuitem" href="http://spectrum.im/download">Download</a>
<a class="menuitem" href="http://spectrum.im/discussion">Discussion</a>
<a class="menuitem" href="https://github.com/SpectrumIM/spectrum2/issues">Issue tracker</a>
</section>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<div class="preinner">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright">Spectrum 2 maintained by <a href="https://github.com/SpectrumIM">Spectrum Transports Team</a></p>
</footer>
</div>
</body>
</html>

View file

@ -0,0 +1,2 @@
theme :
name : twitter

4
_layouts/config.html Normal file
View file

@ -0,0 +1,4 @@
---
layout: null
---
{% include themes/twitter/myconfig.html %}

4
_layouts/page.html Normal file
View file

@ -0,0 +1,4 @@
---
layout: null
---
{% include themes/twitter/my.html %}

38
_plugins/debug.rb Normal file
View file

@ -0,0 +1,38 @@
# A simple way to inspect liquid template variables.
# Usage:
# Can be used anywhere liquid syntax is parsed (templates, includes, posts/pages)
# {{ site | debug }}
# {{ site.posts | debug }}
#
require 'pp'
module Jekyll
# Need to overwrite the inspect method here because the original
# uses < > to encapsulate the psuedo post/page objects in which case
# the output is taken for HTML tags and hidden from view.
#
class Post
def inspect
"#Jekyll:Post @id=#{self.id.inspect}"
end
end
class Page
def inspect
"#Jekyll:Page @name=#{self.name.inspect}"
end
end
end # Jekyll
module Jekyll
module DebugFilter
def debug(obj, stdout=false)
puts obj.pretty_inspect if stdout
"<pre>#{obj.class}\n#{obj.pretty_inspect}</pre>"
end
end # DebugFilter
end # Jekyll
Liquid::Template.register_filter(Jekyll::DebugFilter)

BIN
animation.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

View file

@ -0,0 +1,432 @@
/*******************************************************************************
Slate Theme for Github Pages
by Jason Costello, @jsncostello
*******************************************************************************/
@import url(pygment_trac.css);
/*******************************************************************************
MeyerWeb Reset
*******************************************************************************/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
blockquote, q {
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
a:focus {
outline: none;
}
/*******************************************************************************
Theme Styles
*******************************************************************************/
body {
box-sizing: border-box;
color:#373737;
background: #212121;
font-size: 16px;
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6 {
margin: 10px 0;
font-weight: 700;
color:#222222;
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
letter-spacing: -1px;
}
h1 {
font-size: 36px;
font-weight: 700;
}
h2 {
padding-bottom: 10px;
font-size: 32px;
background: url('../images/bg_hr.png') repeat-x bottom;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 21px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
p {
margin: 10px 0 15px 0;
}
footer p {
color: #f2f2f2;
}
a {
text-decoration: none;
color: #007edf;
text-shadow: none;
transition: color 0.5s ease;
transition: text-shadow 0.5s ease;
-webkit-transition: color 0.5s ease;
-webkit-transition: text-shadow 0.5s ease;
-moz-transition: color 0.5s ease;
-moz-transition: text-shadow 0.5s ease;
-o-transition: color 0.5s ease;
-o-transition: text-shadow 0.5s ease;
-ms-transition: color 0.5s ease;
-ms-transition: text-shadow 0.5s ease;
}
#main_content a:hover {
color: #0069ba;
text-shadow: #0090ff 0px 0px 2px;
}
footer a:hover {
color: #43adff;
text-shadow: #0090ff 0px 0px 2px;
}
em {
font-style: italic;
}
strong {
font-weight: bold;
}
img {
position: relative;
margin: 0 auto;
max-width: 739px;
padding: 5px;
margin: 10px 0 10px 0;
border: 1px solid #ebebeb;
box-shadow: 0 0 5px #ebebeb;
-webkit-box-shadow: 0 0 5px #ebebeb;
-moz-box-shadow: 0 0 5px #ebebeb;
-o-box-shadow: 0 0 5px #ebebeb;
-ms-box-shadow: 0 0 5px #ebebeb;
}
pre, code {
width: 100%;
color: #222;
background-color: #fff;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
pre {
width: 100%;
padding: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
overflow: auto;
}
code {
padding: 3px;
margin: 0 3px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
pre code {
display: block;
box-shadow: none;
}
blockquote {
color: #666;
margin-bottom: 20px;
padding: 0 0 0 20px;
border-left: 3px solid #bbb;
}
ul, ol, dl {
margin-bottom: 15px
}
ul li {
list-style: inside;
padding-left: 20px;
}
ol li {
list-style: decimal inside;
padding-left: 20px;
}
dl dt {
font-weight: bold;
}
dl dd {
padding-left: 20px;
font-style: italic;
}
dl p {
padding-left: 20px;
font-style: italic;
}
hr {
height: 1px;
margin-bottom: 5px;
border: none;
background: url('../images/bg_hr.png') repeat-x center;
}
table {
border: 1px solid #373737;
margin-bottom: 20px;
text-align: left;
}
th {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 10px;
background: #373737;
color: #fff;
}
td {
padding: 10px;
border: 1px solid #373737;
}
form {
background: #f2f2f2;
padding: 20px;
}
img {
width: 100%;
max-width: 100%;
}
/*******************************************************************************
Full-Width Styles
*******************************************************************************/
.outer {
width: 100%;
}
.inner {
position: relative;
max-width: 640px;
padding: 20px 10px;
margin: 0 auto;
}
#forkme_banner {
display: block;
position: absolute;
top:0;
right: 10px;
z-index: 10;
padding: 10px 50px 10px 10px;
color: #fff;
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0,0,0,.5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
#header_wrap {
background: #212121;
background: -moz-linear-gradient(top, #373737, #212121);
background: -webkit-linear-gradient(top, #373737, #212121);
background: -ms-linear-gradient(top, #373737, #212121);
background: -o-linear-gradient(top, #373737, #212121);
background: linear-gradient(top, #373737, #212121);
}
#header_wrap .inner {
padding: 50px 10px 30px 10px;
}
#project_title {
margin: 0;
color: #fff;
font-size: 42px;
font-weight: 700;
text-shadow: #111 0px 0px 10px;
}
#project_tagline {
color: #fff;
font-size: 24px;
font-weight: 300;
background: none;
text-shadow: #111 0px 0px 10px;
}
#downloads {
position: absolute;
width: 210px;
z-index: 10;
bottom: -40px;
right: 0;
height: 70px;
background: url('../images/icon_download.png') no-repeat 0% 90%;
}
.zip_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom left;
}
.tar_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom right;
margin-left: 10px;
}
.zip_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top left;
}
.tar_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top right;
}
#main_content_wrap {
background: #f2f2f2;
border-top: 1px solid #111;
border-bottom: 1px solid #111;
}
#main_content {
padding-top: 40px;
}
#footer_wrap {
background: #212121;
}
/*******************************************************************************
Small Device Styles
*******************************************************************************/
@media screen and (max-width: 480px) {
body {
font-size:14px;
}
#downloads {
display: none;
}
.inner {
min-width: 320px;
max-width: 480px;
}
#project_title {
font-size: 32px;
}
h1 {
font-size: 28px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 21px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 12px;
}
code, pre {
min-width: 320px;
max-width: 480px;
font-size: 11px;
}
}

28
atom.xml Normal file
View file

@ -0,0 +1,28 @@
---
layout: null
title : Atom Feed
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ site.title }}</title>
<link href="{{ site.production_url }}/atom.xml" rel="self"/>
<link href="{{ site.production_url }}"/>
<updated>{{ site.time | date_to_xmlschema }}</updated>
<id>{{ site.production_url }}</id>
<author>
<name>{{ site.author.name }}</name>
<email>{{ site.author.email }}</email>
</author>
{% for post in site.posts %}
<entry>
<title>{{ post.title }}</title>
<link href="{{ site.production_url }}{{ post.url }}"/>
<updated>{{ post.date | date_to_xmlschema }}</updated>
<id>{{ site.production_url }}{{ post.id }}</id>
<content type="html">{{ post.content | xml_escape }}</content>
</entry>
{% endfor %}
</feed>

View file

@ -1,26 +0,0 @@
if (PROTOBUF_FOUND)
if (PURPLE_FOUND)
ADD_SUBDIRECTORY(libpurple)
endif()
if (IRC_FOUND)
ADD_SUBDIRECTORY(libcommuni)
endif()
if (ENABLE_XMPP)
ADD_SUBDIRECTORY(swiften)
endif()
ADD_SUBDIRECTORY(template)
if(ENABLE_TWITTER)
ADD_SUBDIRECTORY(twitter)
endif()
if (NOT WIN32)
if(ENABLE_SMSTOOLS3)
ADD_SUBDIRECTORY(smstools3)
endif()
if(ENABLE_FROTZ)
ADD_SUBDIRECTORY(frotz)
endif()
endif()
endif()

View file

@ -1,12 +0,0 @@
cmake_minimum_required(VERSION 2.6)
ADD_SUBDIRECTORY(dfrotz)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum2_frotz_backend ${SRC})
target_link_libraries(spectrum2_frotz_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
INSTALL(TARGETS spectrum2_frotz_backend RUNTIME DESTINATION bin)

View file

@ -1,9 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC common/*.c dumb/*.c)
ADD_EXECUTABLE(dfrotz ${SRC})
# target_link_libraries(dfrotz)
INSTALL(TARGETS dfrotz RUNTIME DESTINATION bin)

View file

@ -1,2 +0,0 @@
This is patched version of dfrotz. frotz_backend won't work with dfrotz from
your distribution.

View file

@ -1,152 +0,0 @@
/* buffer.c - Text buffering and word wrapping
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
extern void stream_char (zchar);
extern void stream_word (const zchar *);
extern void stream_new_line (void);
static zchar buffer[TEXT_BUFFER_SIZE];
static int bufpos = 0;
static zchar prev_c = 0;
/*
* flush_buffer
*
* Copy the contents of the text buffer to the output streams.
*
*/
void flush_buffer (void)
{
static bool locked = FALSE;
/* Make sure we stop when flush_buffer is called from flush_buffer.
Note that this is difficult to avoid as we might print a newline
during flush_buffer, which might cause a newline interrupt, that
might execute any arbitrary opcode, which might flush the buffer. */
if (locked || bufpos == 0)
return;
/* Send the buffer to the output streams */
buffer[bufpos] = 0;
locked = TRUE;
stream_word (buffer);
#ifdef SPEECH_OUTPUT
os_speech_output(buffer);
#endif
locked = FALSE;
/* Reset the buffer */
bufpos = 0;
prev_c = 0;
}/* flush_buffer */
/*
* print_char
*
* High level output function.
*
*/
void print_char (zchar c)
{
static bool flag = FALSE;
if (message || ostream_memory || enable_buffering) {
if (!flag) {
/* Characters 0 and ZC_RETURN are special cases */
if (c == ZC_RETURN)
{ new_line (); return; }
if (c == 0)
return;
/* Flush the buffer before a whitespace or after a hyphen */
if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (prev_c == '-' && c != '-'))
flush_buffer ();
/* Set the flag if this is part one of a style or font change */
if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
flag = TRUE;
/* Remember the current character code */
prev_c = c;
} else flag = FALSE;
/* Insert the character into the buffer */
buffer[bufpos++] = c;
if (bufpos == TEXT_BUFFER_SIZE)
runtime_error (ERR_TEXT_BUF_OVF);
} else stream_char (c);
}/* print_char */
/*
* new_line
*
* High level newline function.
*
*/
void new_line (void)
{
flush_buffer (); stream_new_line ();
}/* new_line */
/*
* init_buffer
*
* Initialize buffer variables.
*
*/
void init_buffer(void)
{
memset(buffer, 0, sizeof (zchar) * TEXT_BUFFER_SIZE);
bufpos = 0;
prev_c = 0;
}

View file

@ -1,154 +0,0 @@
/* err.c - Runtime error reporting functions
* Written by Jim Dunleavy <jim.dunleavy@erha.ie>
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
/* Define stuff for stricter Z-code error checking, for the generic
Unix/DOS/etc terminal-window interface. Feel free to change the way
player prefs are specified, or replace report_zstrict_error()
completely if you want to change the way errors are reported. */
/* int err_report_mode = ERR_DEFAULT_REPORT_MODE; */
static int error_count[ERR_NUM_ERRORS];
static char *err_messages[] = {
"Text buffer overflow",
"Store out of dynamic memory",
"Division by zero",
"Illegal object",
"Illegal attribute",
"No such property",
"Stack overflow",
"Call to illegal address",
"Call to non-routine",
"Stack underflow",
"Illegal opcode",
"Bad stack frame",
"Jump to illegal address",
"Can't save while in interrupt",
"Nesting stream #3 too deep",
"Illegal window",
"Illegal window property",
"Print at illegal address",
"@jin called with object 0",
"@get_child called with object 0",
"@get_parent called with object 0",
"@get_sibling called with object 0",
"@get_prop_addr called with object 0",
"@get_prop called with object 0",
"@put_prop called with object 0",
"@clear_attr called with object 0",
"@set_attr called with object 0",
"@test_attr called with object 0",
"@move_object called moving object 0",
"@move_object called moving into object 0",
"@remove_object called with object 0",
"@get_next_prop called with object 0"
};
static void print_long (unsigned long value, int base);
/*
* init_err
*
* Initialise error reporting.
*
*/
void init_err (void)
{
int i;
/* Initialize the counters. */
for (i = 0; i < ERR_NUM_ERRORS; i++)
error_count[i] = 0;
}
/*
* runtime_error
*
* An error has occurred. Ignore it, pass it to os_fatal or report
* it according to err_report_mode.
*
* errnum : Numeric code for error (1 to ERR_NUM_ERRORS)
*
*/
void runtime_error (int errnum)
{
int wasfirst;
if (errnum <= 0 || errnum > ERR_NUM_ERRORS)
return;
if (f_setup.err_report_mode == ERR_REPORT_FATAL
|| (!f_setup.ignore_errors && errnum <= ERR_MAX_FATAL)) {
flush_buffer ();
os_fatal (err_messages[errnum - 1]);
return;
}
wasfirst = (error_count[errnum - 1] == 0);
error_count[errnum - 1]++;
if ((f_setup.err_report_mode == ERR_REPORT_ALWAYS)
|| (f_setup.err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
long pc;
GET_PC (pc);
print_string ("Warning: ");
print_string (err_messages[errnum - 1]);
print_string (" (PC = ");
print_long (pc, 16);
print_char (')');
if (f_setup.err_report_mode == ERR_REPORT_ONCE) {
print_string (" (will ignore further occurrences)");
} else {
print_string (" (occurence ");
print_long (error_count[errnum - 1], 10);
print_char (')');
}
new_line ();
}
} /* report_error */
/*
* print_long
*
* Print an unsigned 32bit number in decimal or hex.
*
*/
static void print_long (unsigned long value, int base)
{
unsigned long i;
char c;
for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
if (value >= i || i == 1) {
c = (value / i) % base;
print_char (c + (c <= 9 ? '0' : 'a' - 10));
}
}/* print_long */

File diff suppressed because it is too large Load diff

View file

@ -1,566 +0,0 @@
/* files.c - Transscription, recording and playback
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <string.h>
#include "frotz.h"
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
extern void set_more_prompts (bool);
extern bool is_terminator (zchar);
extern bool read_yes_or_no (const char *);
char script_name[MAX_FILE_NAME + 1] = DEFAULT_SCRIPT_NAME;
char command_name[MAX_FILE_NAME + 1] = DEFAULT_COMMAND_NAME;
#ifdef __MSDOS__
extern char latin1_to_ibm[];
#endif
static int script_width = 0;
static FILE *sfp = NULL;
static FILE *rfp = NULL;
static FILE *pfp = NULL;
/*
* script_open
*
* Open the transscript file. 'AMFV' makes this more complicated as it
* turns transscription on/off several times to exclude some text from
* the transscription file. This wasn't a problem for the original V4
* interpreters which always sent transscription to the printer, but it
* means a problem to modern interpreters that offer to open a new file
* every time transscription is turned on. Our solution is to append to
* the old transscription file in V1 to V4, and to ask for a new file
* name in V5+.
*
*/
void script_open (void)
{
static bool script_valid = FALSE;
char new_name[MAX_FILE_NAME + 1];
h_flags &= ~SCRIPTING_FLAG;
if (h_version >= V5 || !script_valid) {
if (!os_read_file_name (new_name, script_name, FILE_SCRIPT))
goto done;
strcpy (script_name, new_name);
}
/* Opening in "at" mode doesn't work for script_erase_input... */
if ((sfp = fopen (script_name, "r+t")) != NULL || (sfp = fopen (script_name, "w+t")) != NULL) {
fseek (sfp, 0, SEEK_END);
h_flags |= SCRIPTING_FLAG;
script_valid = TRUE;
ostream_script = TRUE;
script_width = 0;
} else print_string ("Cannot open file\n");
done:
SET_WORD (H_FLAGS, h_flags)
}/* script_open */
/*
* script_close
*
* Stop transscription.
*
*/
void script_close (void)
{
h_flags &= ~SCRIPTING_FLAG;
SET_WORD (H_FLAGS, h_flags)
fclose (sfp); ostream_script = FALSE;
}/* script_close */
/*
* script_new_line
*
* Write a newline to the transscript file.
*
*/
void script_new_line (void)
{
if (fputc ('\n', sfp) == EOF)
script_close ();
script_width = 0;
}/* script_new_line */
/*
* script_char
*
* Write a single character to the transscript file.
*
*/
void script_char (zchar c)
{
if (c == ZC_INDENT && script_width != 0)
c = ' ';
if (c == ZC_INDENT)
{ script_char (' '); script_char (' '); script_char (' '); return; }
if (c == ZC_GAP)
{ script_char (' '); script_char (' '); return; }
#ifdef __MSDOS__
if (c >= ZC_LATIN1_MIN)
c = latin1_to_ibm[c - ZC_LATIN1_MIN];
#endif
fputc (c, sfp); script_width++;
}/* script_char */
/*
* script_word
*
* Write a string to the transscript file.
*
*/
void script_word (const zchar *s)
{
int width;
int i;
if (*s == ZC_INDENT && script_width != 0)
script_char (*s++);
for (i = 0, width = 0; s[i] != 0; i++)
if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT)
i++;
else if (s[i] == ZC_GAP)
width += 3;
else if (s[i] == ZC_INDENT)
width += 2;
else
width += 1;
if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols) {
if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
s++;
script_new_line ();
}
for (i = 0; s[i] != 0; i++)
if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
i++;
else
script_char (s[i]);
}/* script_word */
/*
* script_write_input
*
* Send an input line to the transscript file.
*
*/
void script_write_input (const zchar *buf, zchar key)
{
int width;
int i;
for (i = 0, width = 0; buf[i] != 0; i++)
width++;
if (f_setup.script_cols != 0 && script_width + width > f_setup.script_cols)
script_new_line ();
for (i = 0; buf[i] != 0; i++)
script_char (buf[i]);
if (key == ZC_RETURN)
script_new_line ();
}/* script_write_input */
/*
* script_erase_input
*
* Remove an input line from the transscript file.
*
*/
void script_erase_input (const zchar *buf)
{
int width;
int i;
for (i = 0, width = 0; buf[i] != 0; i++)
width++;
fseek (sfp, -width, SEEK_CUR); script_width -= width;
}/* script_erase_input */
/*
* script_mssg_on
*
* Start sending a "debugging" message to the transscript file.
*
*/
void script_mssg_on (void)
{
if (script_width != 0)
script_new_line ();
script_char (ZC_INDENT);
}/* script_mssg_on */
/*
* script_mssg_off
*
* Stop writing a "debugging" message.
*
*/
void script_mssg_off (void)
{
script_new_line ();
}/* script_mssg_off */
/*
* record_open
*
* Open a file to record the player's input.
*
*/
void record_open (void)
{
char new_name[MAX_FILE_NAME + 1];
if (os_read_file_name (new_name, command_name, FILE_RECORD)) {
strcpy (command_name, new_name);
if ((rfp = fopen (new_name, "wt")) != NULL)
ostream_record = TRUE;
else
print_string ("Cannot open file\n");
}
}/* record_open */
/*
* record_close
*
* Stop recording the player's input.
*
*/
void record_close (void)
{
fclose (rfp); ostream_record = FALSE;
}/* record_close */
/*
* record_code
*
* Helper function for record_char.
*
*/
static void record_code (int c, bool force_encoding)
{
if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) {
int i;
fputc ('[', rfp);
for (i = 10000; i != 0; i /= 10)
if (c >= i || i == 1)
fputc ('0' + (c / i) % 10, rfp);
fputc (']', rfp);
} else fputc (c, rfp);
}/* record_code */
/*
* record_char
*
* Write a character to the command file.
*
*/
static void record_char (zchar c)
{
if (c != ZC_RETURN) {
if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) {
record_code (translate_to_zscii (c), FALSE);
if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
record_code (mouse_x, TRUE);
record_code (mouse_y, TRUE);
}
} else record_code (1000 + c - ZC_HKEY_MIN, TRUE);
}
}/* record_char */
/*
* record_write_key
*
* Copy a keystroke to the command file.
*
*/
void record_write_key (zchar key)
{
record_char (key);
if (fputc ('\n', rfp) == EOF)
record_close ();
}/* record_write_key */
/*
* record_write_input
*
* Copy a line of input to a command file.
*
*/
void record_write_input (const zchar *buf, zchar key)
{
zchar c;
while ((c = *buf++) != 0)
record_char (c);
record_char (key);
if (fputc ('\n', rfp) == EOF)
record_close ();
}/* record_write_input */
/*
* replay_open
*
* Open a file of commands for playback.
*
*/
void replay_open (void)
{
char new_name[MAX_FILE_NAME + 1];
if (os_read_file_name (new_name, command_name, FILE_PLAYBACK)) {
strcpy (command_name, new_name);
if ((pfp = fopen (new_name, "rt")) != NULL) {
set_more_prompts (read_yes_or_no ("Do you want MORE prompts"));
istream_replay = TRUE;
} else print_string ("Cannot open file\n");
}
}/* replay_open */
/*
* replay_close
*
* Stop playback of commands.
*
*/
void replay_close (void)
{
set_more_prompts (TRUE);
fclose (pfp); istream_replay = FALSE;
}/* replay_close */
/*
* replay_code
*
* Helper function for replay_key and replay_line.
*
*/
static int replay_code (void)
{
int c;
if ((c = fgetc (pfp)) == '[') {
int c2;
c = 0;
while ((c2 = fgetc (pfp)) != EOF && c2 >= '0' && c2 <= '9')
c = 10 * c + c2 - '0';
return (c2 == ']') ? c : EOF;
} else return c;
}/* replay_code */
/*
* replay_char
*
* Read a character from the command file.
*
*/
static zchar replay_char (void)
{
int c;
if ((c = replay_code ()) != EOF) {
if (c != '\n') {
if (c < 1000) {
c = translate_from_zscii (c);
if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
mouse_x = replay_code ();
mouse_y = replay_code ();
}
return c;
} else return ZC_HKEY_MIN + c - 1000;
}
ungetc ('\n', pfp);
return ZC_RETURN;
} else return ZC_BAD;
}/* replay_char */
/*
* replay_read_key
*
* Read a keystroke from a command file.
*
*/
zchar replay_read_key (void)
{
zchar key;
key = replay_char ();
if (fgetc (pfp) != '\n') {
replay_close ();
return ZC_BAD;
} else return key;
}/* replay_read_key */
/*
* replay_read_input
*
* Read a line of input from a command file.
*
*/
zchar replay_read_input (zchar *buf)
{
zchar c;
for (;;) {
c = replay_char ();
if (c == ZC_BAD || is_terminator (c))
break;
*buf++ = c;
}
*buf = 0;
if (fgetc (pfp) != '\n') {
replay_close ();
return ZC_BAD;
} else return c;
}/* replay_read_input */

View file

@ -1,617 +0,0 @@
/*
* frotz.h
*
* Global declarations and definitions
*
*/
/* Unfortunately, frotz's bool definition conflicts with that of curses.
But since no os_* function uses it, it's safe to let the frotz core see
this definition, but have the unix port see the curses version. */
/* #include "../config.h" */
#ifndef __UNIX_PORT_FILE
#include <signal.h>
typedef int bool;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#endif /* __UNIX_PORT_FILE */
#include <stdio.h>
typedef unsigned char zbyte;
typedef unsigned short zword;
enum story {
BEYOND_ZORK,
SHERLOCK,
ZORK_ZERO,
SHOGUN,
ARTHUR,
JOURNEY,
LURKING_HORROR,
UNKNOWN
};
typedef unsigned char zchar;
/*** Constants that may be set at compile time ***/
#ifndef MAX_UNDO_SLOTS
#define MAX_UNDO_SLOTS 500
#endif
#ifndef MAX_FILE_NAME
#define MAX_FILE_NAME 80
#endif
#ifndef TEXT_BUFFER_SIZE
#define TEXT_BUFFER_SIZE 200
#endif
#ifndef INPUT_BUFFER_SIZE
#define INPUT_BUFFER_SIZE 200
#endif
#ifndef STACK_SIZE
#define STACK_SIZE 1024
#endif
#ifndef DEFAULT_SAVE_NAME
#define DEFAULT_SAVE_NAME "story.sav"
#endif
#ifndef DEFAULT_SCRIPT_NAME
#define DEFAULT_SCRIPT_NAME "story.scr"
#endif
#ifndef DEFAULT_COMMAND_NAME
#define DEFAULT_COMMAND_NAME "story.rec"
#endif
#ifndef DEFAULT_AUXILARY_NAME
#define DEFAULT_AUXILARY_NAME "story.aux"
#endif
#ifndef DEFAULT_SAVE_DIR /* DG */
#define DEFAULT_SAVE_DIR ".frotz-saves"
#endif
/*** Story file header format ***/
#define H_VERSION 0
#define H_CONFIG 1
#define H_RELEASE 2
#define H_RESIDENT_SIZE 4
#define H_START_PC 6
#define H_DICTIONARY 8
#define H_OBJECTS 10
#define H_GLOBALS 12
#define H_DYNAMIC_SIZE 14
#define H_FLAGS 16
#define H_SERIAL 18
#define H_ABBREVIATIONS 24
#define H_FILE_SIZE 26
#define H_CHECKSUM 28
#define H_INTERPRETER_NUMBER 30
#define H_INTERPRETER_VERSION 31
#define H_SCREEN_ROWS 32
#define H_SCREEN_COLS 33
#define H_SCREEN_WIDTH 34
#define H_SCREEN_HEIGHT 36
#define H_FONT_HEIGHT 38 /* this is the font width in V5 */
#define H_FONT_WIDTH 39 /* this is the font height in V5 */
#define H_FUNCTIONS_OFFSET 40
#define H_STRINGS_OFFSET 42
#define H_DEFAULT_BACKGROUND 44
#define H_DEFAULT_FOREGROUND 45
#define H_TERMINATING_KEYS 46
#define H_LINE_WIDTH 48
#define H_STANDARD_HIGH 50
#define H_STANDARD_LOW 51
#define H_ALPHABET 52
#define H_EXTENSION_TABLE 54
#define H_USER_NAME 56
#define HX_TABLE_SIZE 0
#define HX_MOUSE_X 1
#define HX_MOUSE_Y 2
#define HX_UNICODE_TABLE 3
/*** Various Z-machine constants ***/
#define V1 1
#define V2 2
#define V3 3
#define V4 4
#define V5 5
#define V6 6
#define V7 7
#define V8 8
#define CONFIG_BYTE_SWAPPED 0x01 /* Story file is byte swapped - V3 */
#define CONFIG_TIME 0x02 /* Status line displays time - V3 */
#define CONFIG_TWODISKS 0x04 /* Story file occupied two disks - V3 */
#define CONFIG_TANDY 0x08 /* Tandy licensed game - V3 */
#define CONFIG_NOSTATUSLINE 0x10 /* Interpr can't support status lines - V3 */
#define CONFIG_SPLITSCREEN 0x20 /* Interpr supports split screen mode - V3 */
#define CONFIG_PROPORTIONAL 0x40 /* Interpr uses proportional font - V3 */
#define CONFIG_COLOUR 0x01 /* Interpr supports colour - V5+ */
#define CONFIG_PICTURES 0x02 /* Interpr supports pictures - V6 */
#define CONFIG_BOLDFACE 0x04 /* Interpr supports boldface style - V4+ */
#define CONFIG_EMPHASIS 0x08 /* Interpr supports emphasis style - V4+ */
#define CONFIG_FIXED 0x10 /* Interpr supports fixed width style - V4+ */
#define CONFIG_SOUND 0x20 /* Interpr supports sound - V6 */
#define CONFIG_TIMEDINPUT 0x80 /* Interpr supports timed input - V4+ */
#define SCRIPTING_FLAG 0x0001 /* Outputting to transscription file - V1+ */
#define FIXED_FONT_FLAG 0x0002 /* Use fixed width font - V3+ */
#define REFRESH_FLAG 0x0004 /* Refresh the screen - V6 */
#define GRAPHICS_FLAG 0x0008 /* Game wants to use graphics - V5+ */
#define OLD_SOUND_FLAG 0x0010 /* Game wants to use sound effects - V3 */
#define UNDO_FLAG 0x0010 /* Game wants to use UNDO feature - V5+ */
#define MOUSE_FLAG 0x0020 /* Game wants to use a mouse - V5+ */
#define COLOUR_FLAG 0x0040 /* Game wants to use colours - V5+ */
#define SOUND_FLAG 0x0080 /* Game wants to use sound effects - V5+ */
#define MENU_FLAG 0x0100 /* Game wants to use menus - V6 */
#define INTERP_DEFAULT 0
#define INTERP_DEC_20 1
#define INTERP_APPLE_IIE 2
#define INTERP_MACINTOSH 3
#define INTERP_AMIGA 4
#define INTERP_ATARI_ST 5
#define INTERP_MSDOS 6
#define INTERP_CBM_128 7
#define INTERP_CBM_64 8
#define INTERP_APPLE_IIC 9
#define INTERP_APPLE_IIGS 10
#define INTERP_TANDY 11
#define BLACK_COLOUR 2
#define RED_COLOUR 3
#define GREEN_COLOUR 4
#define YELLOW_COLOUR 5
#define BLUE_COLOUR 6
#define MAGENTA_COLOUR 7
#define CYAN_COLOUR 8
#define WHITE_COLOUR 9
#define GREY_COLOUR 10 /* INTERP_MSDOS only */
#define LIGHTGREY_COLOUR 10 /* INTERP_AMIGA only */
#define MEDIUMGREY_COLOUR 11 /* INTERP_AMIGA only */
#define DARKGREY_COLOUR 12 /* INTERP_AMIGA only */
#define REVERSE_STYLE 1
#define BOLDFACE_STYLE 2
#define EMPHASIS_STYLE 4
#define FIXED_WIDTH_STYLE 8
#define TEXT_FONT 1
#define PICTURE_FONT 2
#define GRAPHICS_FONT 3
#define FIXED_WIDTH_FONT 4
#define BEEP_HIGH 1
#define BEEP_LOW 2
/*** Constants for os_restart_game */
#define RESTART_BEGIN 0
#define RESTART_WPROP_SET 1
#define RESTART_END 2
/*** Character codes ***/
#define ZC_TIME_OUT 0x00
#define ZC_NEW_STYLE 0x01
#define ZC_NEW_FONT 0x02
#define ZC_BACKSPACE 0x08
#define ZC_INDENT 0x09
#define ZC_GAP 0x0b
#define ZC_RETURN 0x0d
#define ZC_HKEY_MIN 0x0e
#define ZC_HKEY_RECORD 0x0e
#define ZC_HKEY_PLAYBACK 0x0f
#define ZC_HKEY_SEED 0x10
#define ZC_HKEY_UNDO 0x11
#define ZC_HKEY_RESTART 0x12
#define ZC_HKEY_QUIT 0x13
#define ZC_HKEY_DEBUG 0x14
#define ZC_HKEY_HELP 0x15
#define ZC_HKEY_MAX 0x15
#define ZC_ESCAPE 0x1b
#define ZC_ASCII_MIN 0x20
#define ZC_ASCII_MAX 0x7e
#define ZC_BAD 0x7f
#define ZC_ARROW_MIN 0x81
#define ZC_ARROW_UP 0x81
#define ZC_ARROW_DOWN 0x82
#define ZC_ARROW_LEFT 0x83
#define ZC_ARROW_RIGHT 0x84
#define ZC_ARROW_MAX 0x84
#define ZC_FKEY_MIN 0x85
#define ZC_FKEY_MAX 0x90
#define ZC_NUMPAD_MIN 0x91
#define ZC_NUMPAD_MAX 0x9a
#define ZC_SINGLE_CLICK 0x9b
#define ZC_DOUBLE_CLICK 0x9c
#define ZC_MENU_CLICK 0x9d
#define ZC_LATIN1_MIN 0xa0
#define ZC_LATIN1_MAX 0xff
/*** File types ***/
#define FILE_RESTORE 0
#define FILE_SAVE 1
#define FILE_SCRIPT 2
#define FILE_PLAYBACK 3
#define FILE_RECORD 4
#define FILE_LOAD_AUX 5
#define FILE_SAVE_AUX 6
/*** Data access macros ***/
#define SET_BYTE(addr,v) { zmp[addr] = v; }
#define LOW_BYTE(addr,v) { v = zmp[addr]; }
#define CODE_BYTE(v) { v = *pcp++; }
#if defined (AMIGA)
extern zbyte *pcp;
extern zbyte *zmp;
#define lo(v) ((zbyte *)&v)[1]
#define hi(v) ((zbyte *)&v)[0]
#define SET_WORD(addr,v) { zmp[addr] = hi(v); zmp[addr+1] = lo(v); }
#define LOW_WORD(addr,v) { hi(v) = zmp[addr]; lo(v) = zmp[addr+1]; }
#define HIGH_WORD(addr,v) { hi(v) = zmp[addr]; lo(v) = zmp[addr+1]; }
#define CODE_WORD(v) { hi(v) = *pcp++; lo(v) = *pcp++; }
#define GET_PC(v) { v = pcp - zmp; }
#define SET_PC(v) { pcp = zmp + v; }
#endif
/* A bunch of x86 assembly code previously appeared here. */
#if !defined (AMIGA) && !defined (MSDOS_16BIT)
extern zbyte *pcp;
extern zbyte *zmp;
#define lo(v) (v & 0xff)
#define hi(v) (v >> 8)
#define SET_WORD(addr,v) { zmp[addr] = hi(v); zmp[addr+1] = lo(v); }
#define LOW_WORD(addr,v) { v = ((zword) zmp[addr] << 8) | zmp[addr+1]; }
#define HIGH_WORD(addr,v) { v = ((zword) zmp[addr] << 8) | zmp[addr+1]; }
#define CODE_WORD(v) { v = ((zword) pcp[0] << 8) | pcp[1]; pcp += 2; }
#define GET_PC(v) { v = pcp - zmp; }
#define SET_PC(v) { pcp = zmp + v; }
#endif
/*** Story file header data ***/
extern zbyte h_version;
extern zbyte h_config;
extern zword h_release;
extern zword h_resident_size;
extern zword h_start_pc;
extern zword h_dictionary;
extern zword h_objects;
extern zword h_globals;
extern zword h_dynamic_size;
extern zword h_flags;
extern zbyte h_serial[6];
extern zword h_abbreviations;
extern zword h_file_size;
extern zword h_checksum;
extern zbyte h_interpreter_number;
extern zbyte h_interpreter_version;
extern zbyte h_screen_rows;
extern zbyte h_screen_cols;
extern zword h_screen_width;
extern zword h_screen_height;
extern zbyte h_font_height;
extern zbyte h_font_width;
extern zword h_functions_offset;
extern zword h_strings_offset;
extern zbyte h_default_background;
extern zbyte h_default_foreground;
extern zword h_terminating_keys;
extern zword h_line_width;
extern zbyte h_standard_high;
extern zbyte h_standard_low;
extern zword h_alphabet;
extern zword h_extension_table;
extern zbyte h_user_name[8];
extern zword hx_table_size;
extern zword hx_mouse_x;
extern zword hx_mouse_y;
extern zword hx_unicode_table;
/*** Various data ***/
extern char *story_name;
extern enum story story_id;
extern long story_size;
extern zword stack[STACK_SIZE];
extern zword *sp;
extern zword *fp;
extern zword frame_count;
extern zword zargs[8];
extern int zargc;
extern bool ostream_screen;
extern bool ostream_script;
extern bool ostream_memory;
extern bool ostream_record;
extern bool istream_replay;
extern bool message;
extern int cwin;
extern int mwin;
extern int mouse_x;
extern int mouse_y;
extern bool enable_wrapping;
extern bool enable_scripting;
extern bool enable_scrolling;
extern bool enable_buffering;
extern char *option_zcode_path; /* dg */
extern long reserve_mem;
/*** Blorb stuff ***/
/*
bb_err_t blorb_err;
bb_map_t *blorb_map;
*/
/*** Z-machine opcodes ***/
void z_add (void);
void z_and (void);
void z_art_shift (void);
void z_buffer_mode (void);
void z_call_n (void);
void z_call_s (void);
void z_catch (void);
void z_check_arg_count (void);
void z_check_unicode (void);
void z_clear_attr (void);
void z_copy_table (void);
void z_dec (void);
void z_dec_chk (void);
void z_div (void);
void z_draw_picture (void);
void z_encode_text (void);
void z_erase_line (void);
void z_erase_picture (void);
void z_erase_window (void);
void z_get_child (void);
void z_get_cursor (void);
void z_get_next_prop (void);
void z_get_parent (void);
void z_get_prop (void);
void z_get_prop_addr (void);
void z_get_prop_len (void);
void z_get_sibling (void);
void z_get_wind_prop (void);
void z_inc (void);
void z_inc_chk (void);
void z_input_stream (void);
void z_insert_obj (void);
void z_je (void);
void z_jg (void);
void z_jin (void);
void z_jl (void);
void z_jump (void);
void z_jz (void);
void z_load (void);
void z_loadb (void);
void z_loadw (void);
void z_log_shift (void);
void z_make_menu (void);
void z_mod (void);
void z_mouse_window (void);
void z_move_window (void);
void z_mul (void);
void z_new_line (void);
void z_nop (void);
void z_not (void);
void z_or (void);
void z_output_stream (void);
void z_picture_data (void);
void z_picture_table (void);
void z_piracy (void);
void z_pop (void);
void z_pop_stack (void);
void z_print (void);
void z_print_addr (void);
void z_print_char (void);
void z_print_form (void);
void z_print_num (void);
void z_print_obj (void);
void z_print_paddr (void);
void z_print_ret (void);
void z_print_table (void);
void z_print_unicode (void);
void z_pull (void);
void z_push (void);
void z_push_stack (void);
void z_put_prop (void);
void z_put_wind_prop (void);
void z_quit (void);
void z_random (void);
void z_read (void);
void z_read_char (void);
void z_read_mouse (void);
void z_remove_obj (void);
void z_restart (void);
void z_restore (void);
void z_restore_undo (void);
void z_ret (void);
void z_ret_popped (void);
void z_rfalse (void);
void z_rtrue (void);
void z_save (void);
void z_save_undo (void);
void z_scan_table (void);
void z_scroll_window (void);
void z_set_attr (void);
void z_set_font (void);
void z_set_colour (void);
void z_set_cursor (void);
void z_set_margins (void);
void z_set_window (void);
void z_set_text_style (void);
void z_show_status (void);
void z_sound_effect (void);
void z_split_window (void);
void z_store (void);
void z_storeb (void);
void z_storew (void);
void z_sub (void);
void z_test (void);
void z_test_attr (void);
void z_throw (void);
void z_tokenise (void);
void z_verify (void);
void z_window_size (void);
void z_window_style (void);
/* Definitions for error handling functions and error codes. */
/* extern int err_report_mode; */
void init_err (void);
void runtime_error (int);
/* Error codes */
#define ERR_TEXT_BUF_OVF 1 /* Text buffer overflow */
#define ERR_STORE_RANGE 2 /* Store out of dynamic memory */
#define ERR_DIV_ZERO 3 /* Division by zero */
#define ERR_ILL_OBJ 4 /* Illegal object */
#define ERR_ILL_ATTR 5 /* Illegal attribute */
#define ERR_NO_PROP 6 /* No such property */
#define ERR_STK_OVF 7 /* Stack overflow */
#define ERR_ILL_CALL_ADDR 8 /* Call to illegal address */
#define ERR_CALL_NON_RTN 9 /* Call to non-routine */
#define ERR_STK_UNDF 10 /* Stack underflow */
#define ERR_ILL_OPCODE 11 /* Illegal opcode */
#define ERR_BAD_FRAME 12 /* Bad stack frame */
#define ERR_ILL_JUMP_ADDR 13 /* Jump to illegal address */
#define ERR_SAVE_IN_INTER 14 /* Can't save while in interrupt */
#define ERR_STR3_NESTING 15 /* Nesting stream #3 too deep */
#define ERR_ILL_WIN 16 /* Illegal window */
#define ERR_ILL_WIN_PROP 17 /* Illegal window property */
#define ERR_ILL_PRINT_ADDR 18 /* Print at illegal address */
#define ERR_MAX_FATAL 18
/* Less serious errors */
#define ERR_JIN_0 19 /* @jin called with object 0 */
#define ERR_GET_CHILD_0 20 /* @get_child called with object 0 */
#define ERR_GET_PARENT_0 21 /* @get_parent called with object 0 */
#define ERR_GET_SIBLING_0 22 /* @get_sibling called with object 0 */
#define ERR_GET_PROP_ADDR_0 23 /* @get_prop_addr called with object 0 */
#define ERR_GET_PROP_0 24 /* @get_prop called with object 0 */
#define ERR_PUT_PROP_0 25 /* @put_prop called with object 0 */
#define ERR_CLEAR_ATTR_0 26 /* @clear_attr called with object 0 */
#define ERR_SET_ATTR_0 27 /* @set_attr called with object 0 */
#define ERR_TEST_ATTR_0 28 /* @test_attr called with object 0 */
#define ERR_MOVE_OBJECT_0 29 /* @move_object called moving object 0 */
#define ERR_MOVE_OBJECT_TO_0 30 /* @move_object called moving into object 0 */
#define ERR_REMOVE_OBJECT_0 31 /* @remove_object called with object 0 */
#define ERR_GET_NEXT_PROP_0 32 /* @get_next_prop called with object 0 */
#define ERR_NUM_ERRORS (32)
/* There are four error reporting modes: never report errors;
report only the first time a given error type occurs; report
every time an error occurs; or treat all errors as fatal
errors, killing the interpreter. I strongly recommend
"report once" as the default. But you can compile in a
different default by changing the definition of
ERR_DEFAULT_REPORT_MODE. In any case, the player can
specify a report mode on the command line by typing "-Z 0"
through "-Z 3". */
#define ERR_REPORT_NEVER (0)
#define ERR_REPORT_ONCE (1)
#define ERR_REPORT_ALWAYS (2)
#define ERR_REPORT_FATAL (3)
#define ERR_DEFAULT_REPORT_MODE ERR_REPORT_ONCE
/*** Various global functions ***/
zchar translate_from_zscii (zbyte);
zbyte translate_to_zscii (zchar);
void flush_buffer (void);
void new_line (void);
void print_char (zchar);
void print_num (zword);
void print_object (zword);
void print_string (const char *);
void stream_mssg_on (void);
void stream_mssg_off (void);
void ret (zword);
void store (zword);
void branch (bool);
void storeb (zword, zbyte);
void storew (zword, zword);
/*** Interface functions ***/
void os_beep (int);
int os_char_width (zchar);
void os_display_char (zchar);
void os_display_string (const zchar *);
void os_draw_picture (int, int, int);
void os_erase_area (int, int, int, int);
void os_fatal (const char *);
void os_finish_with_sample (int);
int os_font_data (int, int *, int *);
void os_init_screen (void);
void os_more_prompt (void);
int os_peek_colour (void);
int os_picture_data (int, int *, int *);
void os_prepare_sample (int);
void os_process_arguments (int, char *[]);
int os_random_seed (void);
int os_read_file_name (char *, const char *, int);
zchar os_read_key (int, int);
zchar os_read_line (int, zchar *, int, int, int);
void os_reset_screen (void);
void os_restart_game (int);
void os_scroll_area (int, int, int, int, int);
void os_set_colour (int, int);
void os_set_cursor (int, int);
void os_set_font (int);
void os_set_text_style (int);
void os_start_sample (int, int, int, zword);
void os_stop_sample (int);
int os_string_width (const zchar *);
void os_init_setup (void);
int os_speech_output(const zchar *);
#include "setup.h"

View file

@ -1,72 +0,0 @@
/*
* getopt.c
*
* Replacement for a Unix style getopt function
*
* Quick, clean, and portable to funky systems that don't have getopt()
* for whatever reason.
*
*/
#include <stdio.h>
#include <string.h>
#ifndef MSDOS_16BIT
#define cdecl
#endif
int optind = 1;
int optopt = 0;
const char *optarg = NULL;
int cdecl getopt (int argc, char *argv[], const char *options)
{
static int pos = 1;
const char *p;
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == 0)
return EOF;
optopt = argv[optind][pos++];
optarg = NULL;
if (argv[optind][pos] == 0)
{ pos = 1; optind++; }
p = strchr (options, optopt);
if (optopt == ':' || p == NULL) {
fputs ("illegal option -- ", stdout);
goto error;
} else if (p[1] == ':') {
if (optind >= argc) {
fputs ("option requires an argument -- ", stdout);
goto error;
} else {
optarg = argv[optind];
if (pos != 1)
optarg += pos;
pos = 1; optind++;
}
}
return optopt;
error:
fputc (optopt, stdout);
fputc ('\n', stdout);
return '?';
}/* getopt */

View file

@ -1,258 +0,0 @@
/* hotkey.c - Hot key functions
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
extern int restore_undo (void);
extern int read_number (void);
extern bool read_yes_or_no (const char *);
extern void replay_open (void);
extern void replay_close (void);
extern void record_open (void);
extern void record_close (void);
extern void seed_random (int);
/*
* hot_key_debugging
*
* ...allows user to toggle cheating options on/off.
*
*/
static bool hot_key_debugging (void)
{
print_string ("Debugging options\n");
f_setup.attribute_assignment = read_yes_or_no ("Watch attribute assignment");
f_setup.attribute_testing = read_yes_or_no ("Watch attribute testing");
f_setup.object_movement = read_yes_or_no ("Watch object movement");
f_setup.object_locating = read_yes_or_no ("Watch object locating");
return FALSE;
}/* hot_key_debugging */
/*
* hot_key_help
*
* ...displays a list of all hot keys.
*
*/
static bool hot_key_help (void) {
print_string ("Help\n");
print_string (
"\n"
"Alt-D debugging options\n"
"Alt-H help\n"
"Alt-N new game\n"
"Alt-P playback on\n"
"Alt-R recording on/off\n"
"Alt-S seed random numbers\n"
"Alt-U undo one turn\n"
"Alt-X exit game\n");
return FALSE;
}/* hot_key_help */
/*
* hot_key_playback
*
* ...allows user to turn playback on.
*
*/
static bool hot_key_playback (void)
{
print_string ("Playback on\n");
if (!istream_replay)
replay_open ();
return FALSE;
}/* hot_key_playback */
/*
* hot_key_recording
*
* ...allows user to turn recording on/off.
*
*/
static bool hot_key_recording (void)
{
if (istream_replay) {
print_string ("Playback off\n");
replay_close ();
} else if (ostream_record) {
print_string ("Recording off\n");
record_close ();
} else {
print_string ("Recording on\n");
record_open ();
}
return FALSE;
}/* hot_key_recording */
/*
* hot_key_seed
*
* ...allows user to seed the random number seed.
*
*/
static bool hot_key_seed (void)
{
print_string ("Seed random numbers\n");
print_string ("Enter seed value (or return to randomize): ");
seed_random (read_number ());
return FALSE;
}/* hot_key_seed */
/*
* hot_key_undo
*
* ...allows user to undo the previous turn.
*
*/
static bool hot_key_undo (void)
{
print_string ("Undo one turn\n");
if (restore_undo ()) {
if (h_version >= V5) { /* for V5+ games we must */
store (2); /* store 2 (for success) */
return TRUE; /* and abort the input */
}
if (h_version <= V3) { /* for V3- games we must */
z_show_status (); /* draw the status line */
return FALSE; /* and continue input */
}
} else print_string ("No more undo information available.\n");
return FALSE;
}/* hot_key_undo */
/*
* hot_key_restart
*
* ...allows user to start a new game.
*
*/
static bool hot_key_restart (void)
{
print_string ("New game\n");
if (read_yes_or_no ("Do you wish to restart")) {
z_restart ();
return TRUE;
} else return FALSE;
}/* hot_key_restart */
/*
* hot_key_quit
*
* ...allows user to exit the game.
*
*/
static bool hot_key_quit (void)
{
print_string ("Exit game\n");
if (read_yes_or_no ("Do you wish to quit")) {
z_quit ();
return TRUE;
} else return FALSE;
}/* hot_key_quit */
/*
* handle_hot_key
*
* Perform the action associated with a so-called hot key. Return
* true to abort the current input action.
*
*/
bool handle_hot_key (zchar key)
{
if (cwin == 0) {
bool aborting;
aborting = FALSE;
print_string ("\nHot key -- ");
switch (key) {
case ZC_HKEY_RECORD: aborting = hot_key_recording (); break;
case ZC_HKEY_PLAYBACK: aborting = hot_key_playback (); break;
case ZC_HKEY_SEED: aborting = hot_key_seed (); break;
case ZC_HKEY_UNDO: aborting = hot_key_undo (); break;
case ZC_HKEY_RESTART: aborting = hot_key_restart (); break;
case ZC_HKEY_QUIT: aborting = hot_key_quit (); break;
case ZC_HKEY_DEBUG: aborting = hot_key_debugging (); break;
case ZC_HKEY_HELP: aborting = hot_key_help (); break;
}
if (aborting)
return TRUE;
print_string ("\nContinue input...\n");
}
return FALSE;
}/* handle_hot_key */

View file

@ -1,323 +0,0 @@
/* input.c - High level input functions
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
extern int save_undo (void);
extern zchar stream_read_key (zword, zword, bool);
extern zchar stream_read_input (int, zchar *, zword, zword, bool, bool);
extern void tokenise_line (zword, zword, zword, bool);
/*
* is_terminator
*
* Check if the given key is an input terminator.
*
*/
bool is_terminator (zchar key)
{
if (key == ZC_TIME_OUT)
return TRUE;
if (key == ZC_RETURN)
return TRUE;
if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX)
return TRUE;
if (h_terminating_keys != 0)
if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) {
zword addr = h_terminating_keys;
zbyte c;
do {
LOW_BYTE (addr, c)
if (c == 255 || key == translate_from_zscii (c))
return TRUE;
addr++;
} while (c != 0);
}
return FALSE;
}/* is_terminator */
/*
* z_make_menu, add or remove a menu and branch if successful.
*
* zargs[0] = number of menu
* zargs[1] = table of menu entries or 0 to remove menu
*
*/
void z_make_menu (void)
{
/* This opcode was only used for the Macintosh version of Journey.
It controls menus with numbers greater than 2 (menus 0, 1 and 2
are system menus). Frotz doesn't implement menus yet. */
branch (FALSE);
}/* z_make_menu */
/*
* read_yes_or_no
*
* Ask the user a question; return true if the answer is yes.
*
*/
bool read_yes_or_no (const char *s)
{
zchar key;
print_string (s);
print_string ("? (y/n) >");
key = stream_read_key (0, 0, FALSE);
if (key == 'y' || key == 'Y') {
print_string ("y\n");
return TRUE;
} else {
print_string ("n\n");
return FALSE;
}
}/* read_yes_or_no */
/*
* read_string
*
* Read a string from the current input stream.
*
*/
void read_string (int max, zchar *buffer)
{
zchar key;
buffer[0] = 0;
do {
key = stream_read_input (max, buffer, 0, 0, FALSE, FALSE);
} while (key != ZC_RETURN);
}/* read_string */
/*
* read_number
*
* Ask the user to type in a number and return it.
*
*/
int read_number (void)
{
zchar buffer[6];
int value = 0;
int i;
read_string (5, buffer);
for (i = 0; buffer[i] != 0; i++)
if (buffer[i] >= '0' && buffer[i] <= '9')
value = 10 * value + buffer[i] - '0';
return value;
}/* read_number */
/*
* z_read, read a line of input and (in V5+) store the terminating key.
*
* zargs[0] = address of text buffer
* zargs[1] = address of token buffer
* zargs[2] = timeout in tenths of a second (optional)
* zargs[3] = packed address of routine to be called on timeout
*
*/
void z_read (void)
{
zchar buffer[INPUT_BUFFER_SIZE];
zword addr;
zchar key;
zbyte max, size;
zbyte c;
int i;
/* Supply default arguments */
if (zargc < 3)
zargs[2] = 0;
/* Get maximum input size */
addr = zargs[0];
LOW_BYTE (addr, max)
if (h_version <= V4)
max--;
if (max >= INPUT_BUFFER_SIZE)
max = INPUT_BUFFER_SIZE - 1;
/* Get initial input size */
if (h_version >= V5) {
addr++;
LOW_BYTE (addr, size)
} else size = 0;
/* Copy initial input to local buffer */
for (i = 0; i < size; i++) {
addr++;
LOW_BYTE (addr, c)
buffer[i] = translate_from_zscii (c);
}
buffer[i] = 0;
/* Draw status line for V1 to V3 games */
if (h_version <= V3)
z_show_status ();
/* Read input from current input stream */
key = stream_read_input (
max, buffer, /* buffer and size */
zargs[2], /* timeout value */
zargs[3], /* timeout routine */
TRUE, /* enable hot keys */
h_version == V6); /* no script in V6 */
if (key == ZC_BAD)
return;
/* Perform save_undo for V1 to V4 games */
if (h_version <= V4)
save_undo ();
/* Copy local buffer back to dynamic memory */
for (i = 0; buffer[i] != 0; i++) {
if (key == ZC_RETURN) {
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += 'a' - 'A';
if (buffer[i] >= 0xc0 && buffer[i] <= 0xde && buffer[i] != 0xd7)
buffer[i] += 0x20;
}
storeb ((zword) (zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii (buffer[i]));
}
/* Add null character (V1-V4) or write input length into 2nd byte */
if (h_version <= V4)
storeb ((zword) (zargs[0] + 1 + i), 0);
else
storeb ((zword) (zargs[0] + 1), i);
/* Tokenise line if a token buffer is present */
if (key == ZC_RETURN && zargs[1] != 0)
tokenise_line (zargs[0], zargs[1], 0, FALSE);
/* Store key */
if (h_version >= V5)
store (translate_to_zscii (key));
}/* z_read */
/*
* z_read_char, read and store a key.
*
* zargs[0] = input device (must be 1)
* zargs[1] = timeout in tenths of a second (optional)
* zargs[2] = packed address of routine to be called on timeout
*
*/
void z_read_char (void)
{
zchar key;
/* Supply default arguments */
if (zargc < 2)
zargs[1] = 0;
/* Read input from the current input stream */
key = stream_read_key (
zargs[1], /* timeout value */
zargs[2], /* timeout routine */
TRUE); /* enable hot keys */
if (key == ZC_BAD)
return;
/* Store key */
store (translate_to_zscii (key));
}/* z_read_char */
/*
* z_read_mouse, write the current mouse status into a table.
*
* zargs[0] = address of table
*
*/
void z_read_mouse (void)
{
zword btn;
/* Read the mouse position and which buttons are down */
btn = os_read_mouse ();
hx_mouse_y = mouse_y;
hx_mouse_x = mouse_x;
storew ((zword) (zargs[0] + 0), hx_mouse_y);
storew ((zword) (zargs[0] + 2), hx_mouse_x);
storew ((zword) (zargs[0] + 4), btn); /* mouse button bits */
storew ((zword) (zargs[0] + 6), 0); /* menu selection */
}/* z_read_mouse */

View file

@ -1,197 +0,0 @@
/* main.c - Frotz V2.40 main function
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* This is an interpreter for Infocom V1 to V6 games. It also supports
* the recently defined V7 and V8 games. Please report bugs to
*
* s.jokisch@avu.de
*
*/
#include "frotz.h"
#ifndef MSDOS_16BIT
#define cdecl
#endif
extern void interpret (void);
extern void init_memory (void);
extern void init_undo (void);
extern void reset_memory (void);
/* Story file name, id number and size */
char *story_name = 0;
enum story story_id = UNKNOWN;
long story_size = 0;
/* Story file header data */
zbyte h_version = 0;
zbyte h_config = 0;
zword h_release = 0;
zword h_resident_size = 0;
zword h_start_pc = 0;
zword h_dictionary = 0;
zword h_objects = 0;
zword h_globals = 0;
zword h_dynamic_size = 0;
zword h_flags = 0;
zbyte h_serial[6] = { 0, 0, 0, 0, 0, 0 };
zword h_abbreviations = 0;
zword h_file_size = 0;
zword h_checksum = 0;
zbyte h_interpreter_number = 0;
zbyte h_interpreter_version = 0;
zbyte h_screen_rows = 0;
zbyte h_screen_cols = 0;
zword h_screen_width = 0;
zword h_screen_height = 0;
zbyte h_font_height = 1;
zbyte h_font_width = 1;
zword h_functions_offset = 0;
zword h_strings_offset = 0;
zbyte h_default_background = 0;
zbyte h_default_foreground = 0;
zword h_terminating_keys = 0;
zword h_line_width = 0;
zbyte h_standard_high = 1;
zbyte h_standard_low = 0;
zword h_alphabet = 0;
zword h_extension_table = 0;
zbyte h_user_name[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
zword hx_table_size = 0;
zword hx_mouse_x = 0;
zword hx_mouse_y = 0;
zword hx_unicode_table = 0;
/* Stack data */
zword stack[STACK_SIZE];
zword *sp = 0;
zword *fp = 0;
zword frame_count = 0;
/* IO streams */
bool ostream_screen = TRUE;
bool ostream_script = FALSE;
bool ostream_memory = FALSE;
bool ostream_record = FALSE;
bool istream_replay = FALSE;
bool message = FALSE;
/* Current window and mouse data */
int cwin = 0;
int mwin = 0;
int mouse_y = 0;
int mouse_x = 0;
/* Window attributes */
bool enable_wrapping = FALSE;
bool enable_scripting = FALSE;
bool enable_scrolling = FALSE;
bool enable_buffering = FALSE;
/* User options */
/*
int option_attribute_assignment = 0;
int option_attribute_testing = 0;
int option_context_lines = 0;
int option_object_locating = 0;
int option_object_movement = 0;
int option_left_margin = 0;
int option_right_margin = 0;
int option_ignore_errors = 0;
int option_piracy = 0;
int option_undo_slots = MAX_UNDO_SLOTS;
int option_expand_abbreviations = 0;
int option_script_cols = 80;
int option_save_quetzal = 1;
*/
int option_sound = 1;
char *option_zcode_path;
/* Size of memory to reserve (in bytes) */
long reserve_mem = 0;
/*
* z_piracy, branch if the story file is a legal copy.
*
* no zargs used
*
*/
void z_piracy (void)
{
branch (!f_setup.piracy);
}/* z_piracy */
/*
* main
*
* Prepare and run the game.
*
*/
int cdecl main (int argc, char *argv[])
{
os_init_setup ();
os_process_arguments (argc, argv);
init_buffer ();
init_err ();
init_memory ();
init_process ();
init_sound ();
os_init_screen ();
init_undo ();
z_restart ();
interpret ();
reset_memory ();
os_reset_screen ();
return 0;
}/* main */

View file

@ -1,261 +0,0 @@
/* math.c - Arithmetic, compare and logical opcodes
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
/*
* z_add, 16bit addition.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_add (void)
{
store ((zword) ((short) zargs[0] + (short) zargs[1]));
}/* z_add */
/*
* z_and, bitwise AND operation.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_and (void)
{
store ((zword) (zargs[0] & zargs[1]));
}/* z_and */
/*
* z_art_shift, arithmetic SHIFT operation.
*
* zargs[0] = value
* zargs[1] = #positions to shift left (positive) or right
*
*/
void z_art_shift (void)
{
if ((short) zargs[1] > 0)
store ((zword) ((short) zargs[0] << (short) zargs[1]));
else
store ((zword) ((short) zargs[0] >> - (short) zargs[1]));
}/* z_art_shift */
/*
* z_div, signed 16bit division.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_div (void)
{
if (zargs[1] == 0)
runtime_error (ERR_DIV_ZERO);
store ((zword) ((short) zargs[0] / (short) zargs[1]));
}/* z_div */
/*
* z_je, branch if the first value equals any of the following.
*
* zargs[0] = first value
* zargs[1] = second value (optional)
* ...
* zargs[3] = fourth value (optional)
*
*/
void z_je (void)
{
branch (
zargc > 1 && (zargs[0] == zargs[1] || (
zargc > 2 && (zargs[0] == zargs[2] || (
zargc > 3 && (zargs[0] == zargs[3]))))));
}/* z_je */
/*
* z_jg, branch if the first value is greater than the second.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_jg (void)
{
branch ((short) zargs[0] > (short) zargs[1]);
}/* z_jg */
/*
* z_jl, branch if the first value is less than the second.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_jl (void)
{
branch ((short) zargs[0] < (short) zargs[1]);
}/* z_jl */
/*
* z_jz, branch if value is zero.
*
* zargs[0] = value
*
*/
void z_jz (void)
{
branch ((short) zargs[0] == 0);
}/* z_jz */
/*
* z_log_shift, logical SHIFT operation.
*
* zargs[0] = value
* zargs[1] = #positions to shift left (positive) or right (negative)
*
*/
void z_log_shift (void)
{
if ((short) zargs[1] > 0)
store ((zword) (zargs[0] << (short) zargs[1]));
else
store ((zword) (zargs[0] >> - (short) zargs[1]));
}/* z_log_shift */
/*
* z_mod, remainder after signed 16bit division.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_mod (void)
{
if (zargs[1] == 0)
runtime_error (ERR_DIV_ZERO);
store ((zword) ((short) zargs[0] % (short) zargs[1]));
}/* z_mod */
/*
* z_mul, 16bit multiplication.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_mul (void)
{
store ((zword) ((short) zargs[0] * (short) zargs[1]));
}/* z_mul */
/*
* z_not, bitwise NOT operation.
*
* zargs[0] = value
*
*/
void z_not (void)
{
store ((zword) ~zargs[0]);
}/* z_not */
/*
* z_or, bitwise OR operation.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_or (void)
{
store ((zword) (zargs[0] | zargs[1]));
}/* z_or */
/*
* z_sub, 16bit substraction.
*
* zargs[0] = first value
* zargs[1] = second value
*
*/
void z_sub (void)
{
store ((zword) ((short) zargs[0] - (short) zargs[1]));
}/* z_sub */
/*
* z_test, branch if all the flags of a bit mask are set in a value.
*
* zargs[0] = value to be examined
* zargs[1] = bit mask
*
*/
void z_test (void)
{
branch ((zargs[0] & zargs[1]) == zargs[1]);
}/* z_test */

File diff suppressed because it is too large Load diff

View file

@ -1,798 +0,0 @@
/* process.c - Interpreter loop and program control
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
#ifdef DJGPP
#include "djfrotz.h"
#endif
zword zargs[8];
int zargc;
static int finished = 0;
static void __extended__ (void);
static void __illegal__ (void);
void (*op0_opcodes[0x10]) (void) = {
z_rtrue,
z_rfalse,
z_print,
z_print_ret,
z_nop,
z_save,
z_restore,
z_restart,
z_ret_popped,
z_catch,
z_quit,
z_new_line,
z_show_status,
z_verify,
__extended__,
z_piracy
};
void (*op1_opcodes[0x10]) (void) = {
z_jz,
z_get_sibling,
z_get_child,
z_get_parent,
z_get_prop_len,
z_inc,
z_dec,
z_print_addr,
z_call_s,
z_remove_obj,
z_print_obj,
z_ret,
z_jump,
z_print_paddr,
z_load,
z_call_n
};
void (*var_opcodes[0x40]) (void) = {
__illegal__,
z_je,
z_jl,
z_jg,
z_dec_chk,
z_inc_chk,
z_jin,
z_test,
z_or,
z_and,
z_test_attr,
z_set_attr,
z_clear_attr,
z_store,
z_insert_obj,
z_loadw,
z_loadb,
z_get_prop,
z_get_prop_addr,
z_get_next_prop,
z_add,
z_sub,
z_mul,
z_div,
z_mod,
z_call_s,
z_call_n,
z_set_colour,
z_throw,
__illegal__,
__illegal__,
__illegal__,
z_call_s,
z_storew,
z_storeb,
z_put_prop,
z_read,
z_print_char,
z_print_num,
z_random,
z_push,
z_pull,
z_split_window,
z_set_window,
z_call_s,
z_erase_window,
z_erase_line,
z_set_cursor,
z_get_cursor,
z_set_text_style,
z_buffer_mode,
z_output_stream,
z_input_stream,
z_sound_effect,
z_read_char,
z_scan_table,
z_not,
z_call_n,
z_call_n,
z_tokenise,
z_encode_text,
z_copy_table,
z_print_table,
z_check_arg_count
};
void (*ext_opcodes[0x1d]) (void) = {
z_save,
z_restore,
z_log_shift,
z_art_shift,
z_set_font,
z_draw_picture,
z_picture_data,
z_erase_picture,
z_set_margins,
z_save_undo,
z_restore_undo,
z_print_unicode,
z_check_unicode,
__illegal__,
__illegal__,
__illegal__,
z_move_window,
z_window_size,
z_window_style,
z_get_wind_prop,
z_scroll_window,
z_pop_stack,
z_read_mouse,
z_mouse_window,
z_push_stack,
z_put_wind_prop,
z_print_form,
z_make_menu,
z_picture_table
};
/*
* init_process
*
* Initialize process variables.
*
*/
void init_process (void)
{
finished = 0;
} /* init_process */
/*
* load_operand
*
* Load an operand, either a variable or a constant.
*
*/
static void load_operand (zbyte type)
{
zword value;
if (type & 2) { /* variable */
zbyte variable;
CODE_BYTE (variable)
if (variable == 0)
value = *sp++;
else if (variable < 16)
value = *(fp - variable);
else {
zword addr = h_globals + 2 * (variable - 16);
LOW_WORD (addr, value)
}
} else if (type & 1) { /* small constant */
zbyte bvalue;
CODE_BYTE (bvalue)
value = bvalue;
} else CODE_WORD (value) /* large constant */
zargs[zargc++] = value;
}/* load_operand */
/*
* load_all_operands
*
* Given the operand specifier byte, load all (up to four) operands
* for a VAR or EXT opcode.
*
*/
static void load_all_operands (zbyte specifier)
{
int i;
for (i = 6; i >= 0; i -= 2) {
zbyte type = (specifier >> i) & 0x03;
if (type == 3)
break;
load_operand (type);
}
}/* load_all_operands */
/*
* interpret
*
* Z-code interpreter main loop
*
*/
void interpret (void)
{
do {
zbyte opcode;
CODE_BYTE (opcode)
zargc = 0;
if (opcode < 0x80) { /* 2OP opcodes */
load_operand ((zbyte) (opcode & 0x40) ? 2 : 1);
load_operand ((zbyte) (opcode & 0x20) ? 2 : 1);
var_opcodes[opcode & 0x1f] ();
} else if (opcode < 0xb0) { /* 1OP opcodes */
load_operand ((zbyte) (opcode >> 4));
op1_opcodes[opcode & 0x0f] ();
} else if (opcode < 0xc0) { /* 0OP opcodes */
op0_opcodes[opcode - 0xb0] ();
} else { /* VAR opcodes */
zbyte specifier1;
zbyte specifier2;
if (opcode == 0xec || opcode == 0xfa) { /* opcodes 0xec */
CODE_BYTE (specifier1) /* and 0xfa are */
CODE_BYTE (specifier2) /* call opcodes */
load_all_operands (specifier1); /* with up to 8 */
load_all_operands (specifier2); /* arguments */
} else {
CODE_BYTE (specifier1)
load_all_operands (specifier1);
}
var_opcodes[opcode - 0xc0] ();
}
#if defined(DJGPP) && defined(SOUND_SUPPORT)
if (end_of_sound_flag)
end_of_sound ();
#endif
} while (finished == 0);
finished--;
}/* interpret */
/*
* call
*
* Call a subroutine. Save PC and FP then load new PC and initialise
* new stack frame. Note that the caller may legally provide less or
* more arguments than the function actually has. The call type "ct"
* can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
*
*/
void call (zword routine, int argc, zword *args, int ct)
{
long pc;
zword value;
zbyte count;
int i;
if (sp - stack < 4)
runtime_error (ERR_STK_OVF);
GET_PC (pc)
*--sp = (zword) (pc >> 9);
*--sp = (zword) (pc & 0x1ff);
*--sp = (zword) (fp - stack - 1);
*--sp = (zword) (argc | (ct << (f_setup.save_quetzal ? 12 : 8)));
fp = sp;
frame_count++;
/* Calculate byte address of routine */
if (h_version <= V3)
pc = (long) routine << 1;
else if (h_version <= V5)
pc = (long) routine << 2;
else if (h_version <= V7)
pc = ((long) routine << 2) + ((long) h_functions_offset << 3);
else /* h_version == V8 */
pc = (long) routine << 3;
if (pc >= story_size)
runtime_error (ERR_ILL_CALL_ADDR);
SET_PC (pc)
/* Initialise local variables */
CODE_BYTE (count)
if (count > 15)
runtime_error (ERR_CALL_NON_RTN);
if (sp - stack < count)
runtime_error (ERR_STK_OVF);
if (f_setup.save_quetzal)
fp[0] |= (zword) count << 8; /* Save local var count for Quetzal. */
value = 0;
for (i = 0; i < count; i++) {
if (h_version <= V4) /* V1 to V4 games provide default */
CODE_WORD (value) /* values for all local variables */
*--sp = (zword) ((argc-- > 0) ? args[i] : value);
}
/* Start main loop for direct calls */
if (ct == 2)
interpret ();
}/* call */
/*
* ret
*
* Return from the current subroutine and restore the previous stack
* frame. The result may be stored (0), thrown away (1) or pushed on
* the stack (2). In the latter case a direct call has been finished
* and we must exit the interpreter loop.
*
*/
void ret (zword value)
{
long pc;
int ct;
if (sp > fp)
runtime_error (ERR_STK_UNDF);
sp = fp;
ct = *sp++ >> (f_setup.save_quetzal ? 12 : 8);
frame_count--;
fp = stack + 1 + *sp++;
pc = *sp++;
pc = ((long) *sp++ << 9) | pc;
SET_PC (pc)
/* Handle resulting value */
if (ct == 0)
store (value);
if (ct == 2)
*--sp = value;
/* Stop main loop for direct calls */
if (ct == 2)
finished++;
}/* ret */
/*
* branch
*
* Take a jump after an instruction based on the flag, either true or
* false. The branch can be short or long; it is encoded in one or two
* bytes respectively. When bit 7 of the first byte is set, the jump
* takes place if the flag is true; otherwise it is taken if the flag
* is false. When bit 6 of the first byte is set, the branch is short;
* otherwise it is long. The offset occupies the bottom 6 bits of the
* first byte plus all the bits in the second byte for long branches.
* Uniquely, an offset of 0 means return false, and an offset of 1 is
* return true.
*
*/
void branch (bool flag)
{
long pc;
zword offset;
zbyte specifier;
zbyte off1;
zbyte off2;
CODE_BYTE (specifier)
off1 = specifier & 0x3f;
if (!flag)
specifier ^= 0x80;
if (!(specifier & 0x40)) { /* it's a long branch */
if (off1 & 0x20) /* propagate sign bit */
off1 |= 0xc0;
CODE_BYTE (off2)
offset = (off1 << 8) | off2;
} else offset = off1; /* it's a short branch */
if (specifier & 0x80) {
if (offset > 1) { /* normal branch */
GET_PC (pc)
pc += (short) offset - 2;
SET_PC (pc)
} else ret (offset); /* special case, return 0 or 1 */
}
}/* branch */
/*
* store
*
* Store an operand, either as a variable or pushed on the stack.
*
*/
void store (zword value)
{
zbyte variable;
CODE_BYTE (variable)
if (variable == 0)
*--sp = value;
else if (variable < 16)
*(fp - variable) = value;
else {
zword addr = h_globals + 2 * (variable - 16);
SET_WORD (addr, value)
}
}/* store */
/*
* direct_call
*
* Call the interpreter loop directly. This is necessary when
*
* - a sound effect has been finished
* - a read instruction has timed out
* - a newline countdown has hit zero
*
* The interpreter returns the result value on the stack.
*
*/
int direct_call (zword addr)
{
zword saved_zargs[8];
int saved_zargc;
int i;
/* Calls to address 0 return false */
if (addr == 0)
return 0;
/* Save operands and operand count */
for (i = 0; i < 8; i++)
saved_zargs[i] = zargs[i];
saved_zargc = zargc;
/* Call routine directly */
call (addr, 0, 0, 2);
/* Restore operands and operand count */
for (i = 0; i < 8; i++)
zargs[i] = saved_zargs[i];
zargc = saved_zargc;
/* Resulting value lies on top of the stack */
return (short) *sp++;
}/* direct_call */
/*
* __extended__
*
* Load and execute an extended opcode.
*
*/
static void __extended__ (void)
{
zbyte opcode;
zbyte specifier;
CODE_BYTE (opcode)
CODE_BYTE (specifier)
load_all_operands (specifier);
if (opcode < 0x1d) /* extended opcodes from 0x1d on */
ext_opcodes[opcode] (); /* are reserved for future spec' */
}/* __extended__ */
/*
* __illegal__
*
* Exit game because an unknown opcode has been hit.
*
*/
static void __illegal__ (void)
{
runtime_error (ERR_ILL_OPCODE);
}/* __illegal__ */
/*
* z_catch, store the current stack frame for later use with z_throw.
*
* no zargs used
*
*/
void z_catch (void)
{
store (f_setup.save_quetzal ? frame_count : (zword) (fp - stack));
}/* z_catch */
/*
* z_throw, go back to the given stack frame and return the given value.
*
* zargs[0] = value to return
* zargs[1] = stack frame
*
*/
void z_throw (void)
{
if (f_setup.save_quetzal) {
if (zargs[1] > frame_count)
runtime_error (ERR_BAD_FRAME);
/* Unwind the stack a frame at a time. */
for (; frame_count > zargs[1]; --frame_count)
fp = stack + 1 + fp[1];
} else {
if (zargs[1] > STACK_SIZE)
runtime_error (ERR_BAD_FRAME);
fp = stack + zargs[1];
}
ret (zargs[0]);
}/* z_throw */
/*
* z_call_n, call a subroutine and discard its result.
*
* zargs[0] = packed address of subroutine
* zargs[1] = first argument (optional)
* ...
* zargs[7] = seventh argument (optional)
*
*/
void z_call_n (void)
{
if (zargs[0] != 0)
call (zargs[0], zargc - 1, zargs + 1, 1);
}/* z_call_n */
/*
* z_call_s, call a subroutine and store its result.
*
* zargs[0] = packed address of subroutine
* zargs[1] = first argument (optional)
* ...
* zargs[7] = seventh argument (optional)
*
*/
void z_call_s (void)
{
if (zargs[0] != 0)
call (zargs[0], zargc - 1, zargs + 1, 0);
else
store (0);
}/* z_call_s */
/*
* z_check_arg_count, branch if subroutine was called with >= n arg's.
*
* zargs[0] = number of arguments
*
*/
void z_check_arg_count (void)
{
if (fp == stack + STACK_SIZE)
branch (zargs[0] == 0);
else
branch (zargs[0] <= (*fp & 0xff));
}/* z_check_arg_count */
/*
* z_jump, jump unconditionally to the given address.
*
* zargs[0] = PC relative address
*
*/
void z_jump (void)
{
long pc;
GET_PC (pc)
pc += (short) zargs[0] - 2;
if (pc >= story_size)
runtime_error (ERR_ILL_JUMP_ADDR);
SET_PC (pc)
}/* z_jump */
/*
* z_nop, no operation.
*
* no zargs used
*
*/
void z_nop (void)
{
/* Do nothing */
}/* z_nop */
/*
* z_quit, stop game and exit interpreter.
*
* no zargs used
*
*/
void z_quit (void)
{
finished = 9999;
}/* z_quit */
/*
* z_ret, return from a subroutine with the given value.
*
* zargs[0] = value to return
*
*/
void z_ret (void)
{
ret (zargs[0]);
}/* z_ret */
/*
* z_ret_popped, return from a subroutine with a value popped off the stack.
*
* no zargs used
*
*/
void z_ret_popped (void)
{
ret (*sp++);
}/* z_ret_popped */
/*
* z_rfalse, return from a subroutine with false (0).
*
* no zargs used
*
*/
void z_rfalse (void)
{
ret (0);
}/* z_rfalse */
/*
* z_rtrue, return from a subroutine with true (1).
*
* no zargs used
*
*/
void z_rtrue (void)
{
ret (1);
}/* z_rtrue */

View file

@ -1,562 +0,0 @@
/* quetzal.c - Saving and restoring of Quetzal files.
* Written by Martin Frost <mdf@doc.ic.ac.uk>
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <string.h>
#include "frotz.h"
#ifdef MSDOS_16BIT
#include <alloc.h>
#define malloc(size) farmalloc (size)
#define realloc(size,p) farrealloc (size,p)
#define free(size) farfree (size)
#define memcpy(d,s,n) _fmemcpy (d,s,n)
#else
#include <stdlib.h>
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#define far
#endif
#define get_c fgetc
#define put_c fputc
typedef unsigned long zlong;
/*
* This is used only by save_quetzal. It probably should be allocated
* dynamically rather than statically.
*/
static zword frames[STACK_SIZE/4+1];
/*
* ID types.
*/
#define makeid(a,b,c,d) ((zlong) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)))
#define ID_FORM makeid ('F','O','R','M')
#define ID_IFZS makeid ('I','F','Z','S')
#define ID_IFhd makeid ('I','F','h','d')
#define ID_UMem makeid ('U','M','e','m')
#define ID_CMem makeid ('C','M','e','m')
#define ID_Stks makeid ('S','t','k','s')
#define ID_ANNO makeid ('A','N','N','O')
/*
* Various parsing states within restoration.
*/
#define GOT_HEADER 0x01
#define GOT_STACK 0x02
#define GOT_MEMORY 0x04
#define GOT_NONE 0x00
#define GOT_ALL 0x07
#define GOT_ERROR 0x80
/*
* Macros used to write the files.
*/
#define write_byte(fp,b) (put_c (b, fp) != EOF)
#define write_bytx(fp,b) write_byte (fp, (b) & 0xFF)
#define write_word(fp,w) \
(write_bytx (fp, (w) >> 8) && write_bytx (fp, (w)))
#define write_long(fp,l) \
(write_bytx (fp, (l) >> 24) && write_bytx (fp, (l) >> 16) && \
write_bytx (fp, (l) >> 8) && write_bytx (fp, (l)))
#define write_chnk(fp,id,len) \
(write_long (fp, (id)) && write_long (fp, (len)))
#define write_run(fp,run) \
(write_byte (fp, 0) && write_byte (fp, (run)))
/* Read one word from file; return TRUE if OK. */
static bool read_word (FILE *f, zword *result)
{
int a, b;
if ((a = get_c (f)) == EOF) return FALSE;
if ((b = get_c (f)) == EOF) return FALSE;
*result = ((zword) a << 8) | (zword) b;
return TRUE;
}
/* Read one long from file; return TRUE if OK. */
static bool read_long (FILE *f, zlong *result)
{
int a, b, c, d;
if ((a = get_c (f)) == EOF) return FALSE;
if ((b = get_c (f)) == EOF) return FALSE;
if ((c = get_c (f)) == EOF) return FALSE;
if ((d = get_c (f)) == EOF) return FALSE;
*result = ((zlong) a << 24) | ((zlong) b << 16) |
((zlong) c << 8) | (zlong) d;
return TRUE;
}
/*
* Restore a saved game using Quetzal format. Return 2 if OK, 0 if an error
* occurred before any damage was done, -1 on a fatal error.
*/
zword restore_quetzal (FILE *svf, FILE *stf)
{
zlong ifzslen, currlen, tmpl;
zlong pc;
zword i, tmpw;
zword fatal = 0; /* Set to -1 when errors must be fatal. */
zbyte skip, progress = GOT_NONE;
int x, y;
/* Check it's really an `IFZS' file. */
if (!read_long (svf, &tmpl)
|| !read_long (svf, &ifzslen)
|| !read_long (svf, &currlen)) return 0;
if (tmpl != ID_FORM || currlen != ID_IFZS)
{
print_string ("This is not a saved game file!\n");
return 0;
}
if ((ifzslen & 1) || ifzslen<4) /* Sanity checks. */ return 0;
ifzslen -= 4;
/* Read each chunk and process it. */
while (ifzslen > 0)
{
/* Read chunk header. */
if (ifzslen < 8) /* Couldn't contain a chunk. */ return 0;
if (!read_long (svf, &tmpl)
|| !read_long (svf, &currlen)) return 0;
ifzslen -= 8; /* Reduce remaining by size of header. */
/* Handle chunk body. */
if (ifzslen < currlen) /* Chunk goes past EOF?! */ return 0;
skip = currlen & 1;
ifzslen -= currlen + (zlong) skip;
switch (tmpl)
{
/* `IFhd' header chunk; must be first in file. */
case ID_IFhd:
if (progress & GOT_HEADER)
{
print_string ("Save file has two IFZS chunks!\n");
return fatal;
}
progress |= GOT_HEADER;
if (currlen < 13
|| !read_word (svf, &tmpw)) return fatal;
if (tmpw != h_release)
progress = GOT_ERROR;
for (i=H_SERIAL; i<H_SERIAL+6; ++i)
{
if ((x = get_c (svf)) == EOF) return fatal;
if (x != zmp[i])
progress = GOT_ERROR;
}
if (!read_word (svf, &tmpw)) return fatal;
if (tmpw != h_checksum)
progress = GOT_ERROR;
if (progress & GOT_ERROR)
{
print_string ("File was not saved from this story!\n");
return fatal;
}
if ((x = get_c (svf)) == EOF) return fatal;
pc = (zlong) x << 16;
if ((x = get_c (svf)) == EOF) return fatal;
pc |= (zlong) x << 8;
if ((x = get_c (svf)) == EOF) return fatal;
pc |= (zlong) x;
fatal = -1; /* Setting PC means errors must be fatal. */
SET_PC (pc);
for (i=13; i<currlen; ++i)
(void) get_c (svf); /* Skip rest of chunk. */
break;
/* `Stks' stacks chunk; restoring this is quite complex. ;) */
case ID_Stks:
if (progress & GOT_STACK)
{
print_string ("File contains two stack chunks!\n");
break;
}
progress |= GOT_STACK;
fatal = -1; /* Setting SP means errors must be fatal. */
sp = stack + STACK_SIZE;
/*
* All versions other than V6 may use evaluation stack outside
* any function context. As a result a faked function context
* will be present in the file here. We skip this context, but
* load the associated stack onto the stack proper...
*/
if (h_version != V6)
{
if (currlen < 8) return fatal;
for (i=0; i<6; ++i)
if (get_c (svf) != 0) return fatal;
if (!read_word (svf, &tmpw)) return fatal;
if (tmpw > STACK_SIZE)
{
print_string ("Save-file has too much stack (and I can't cope).\n");
return fatal;
}
currlen -= 8;
if (currlen < tmpw*2) return fatal;
for (i=0; i<tmpw; ++i)
if (!read_word (svf, --sp)) return fatal;
currlen -= tmpw*2;
}
/* We now proceed to load the main block of stack frames. */
for (fp = stack+STACK_SIZE, frame_count = 0;
currlen > 0;
currlen -= 8, ++frame_count)
{
if (currlen < 8) return fatal;
if (sp - stack < 4) /* No space for frame. */
{
print_string ("Save-file has too much stack (and I can't cope).\n");
return fatal;
}
/* Read PC, procedure flag and formal param count. */
if (!read_long (svf, &tmpl)) return fatal;
y = (int) (tmpl & 0x0F); /* Number of formals. */
tmpw = y << 8;
/* Read result variable. */
if ((x = get_c (svf)) == EOF) return fatal;
/* Check the procedure flag... */
if (tmpl & 0x10)
{
tmpw |= 0x1000; /* It's a procedure. */
tmpl >>= 8; /* Shift to get PC value. */
}
else
{
/* Functions have type 0, so no need to or anything. */
tmpl >>= 8; /* Shift to get PC value. */
--tmpl; /* Point at result byte. */
/* Sanity check on result variable... */
if (zmp[tmpl] != (zbyte) x)
{
print_string ("Save-file has wrong variable number on stack (possibly wrong game version?)\n");
return fatal;
}
}
*--sp = (zword) (tmpl >> 9); /* High part of PC */
*--sp = (zword) (tmpl & 0x1FF); /* Low part of PC */
*--sp = (zword) (fp - stack - 1); /* FP */
/* Read and process argument mask. */
if ((x = get_c (svf)) == EOF) return fatal;
++x; /* Should now be a power of 2 */
for (i=0; i<8; ++i)
if (x & (1<<i))
break;
if (x ^ (1<<i)) /* Not a power of 2 */
{
print_string ("Save-file uses incomplete argument lists (which I can't handle)\n");
return fatal;
}
*--sp = tmpw | i;
fp = sp; /* FP for next frame. */
/* Read amount of eval stack used. */
if (!read_word (svf, &tmpw)) return fatal;
tmpw += y; /* Amount of stack + number of locals. */
if (sp - stack <= tmpw)
{
print_string ("Save-file has too much stack (and I can't cope).\n");
return fatal;
}
if (currlen < tmpw*2) return fatal;
for (i=0; i<tmpw; ++i)
if (!read_word (svf, --sp)) return fatal;
currlen -= tmpw*2;
}
/* End of `Stks' processing... */
break;
/* Any more special chunk types must go in HERE or ABOVE. */
/* `CMem' compressed memory chunk; uncompress it. */
case ID_CMem:
if (!(progress & GOT_MEMORY)) /* Don't complain if two. */
{
(void) fseek (stf, 0, SEEK_SET);
i=0; /* Bytes written to data area. */
for (; currlen > 0; --currlen)
{
if ((x = get_c (svf)) == EOF) return fatal;
if (x == 0) /* Start run. */
{
/* Check for bogus run. */
if (currlen < 2)
{
print_string ("File contains bogus `CMem' chunk.\n");
for (; currlen > 0; --currlen)
(void) get_c (svf); /* Skip rest. */
currlen = 1;
i = 0xFFFF;
break; /* Keep going; may be a `UMem' too. */
}
/* Copy story file to memory during the run. */
--currlen;
if ((x = get_c (svf)) == EOF) return fatal;
for (; x >= 0 && i<h_dynamic_size; --x, ++i)
if ((y = get_c (stf)) == EOF) return fatal;
else
zmp[i] = (zbyte) y;
}
else /* Not a run. */
{
if ((y = get_c (stf)) == EOF) return fatal;
zmp[i] = (zbyte) (x ^ y);
++i;
}
/* Make sure we don't load too much. */
if (i > h_dynamic_size)
{
print_string ("warning: `CMem' chunk too long!\n");
for (; currlen > 1; --currlen)
(void) get_c (svf); /* Skip rest. */
break; /* Keep going; there may be a `UMem' too. */
}
}
/* If chunk is short, assume a run. */
for (; i<h_dynamic_size; ++i)
if ((y = get_c (stf)) == EOF) return fatal;
else
zmp[i] = (zbyte) y;
if (currlen == 0)
progress |= GOT_MEMORY; /* Only if succeeded. */
break;
}
/* Fall right thru (to default) if already GOT_MEMORY */
/* `UMem' uncompressed memory chunk; load it. */
case ID_UMem:
if (!(progress & GOT_MEMORY)) /* Don't complain if two. */
{
/* Must be exactly the right size. */
if (currlen == h_dynamic_size)
{
if (fread (zmp, currlen, 1, svf) == 1)
{
progress |= GOT_MEMORY; /* Only on success. */
break;
}
}
else
print_string ("`UMem' chunk wrong size!\n");
/* Fall into default action (skip chunk) on errors. */
}
/* Fall thru (to default) if already GOT_MEMORY */
/* Unrecognised chunk type; skip it. */
default:
(void) fseek (svf, currlen, SEEK_CUR); /* Skip chunk. */
break;
}
if (skip)
(void) get_c (svf); /* Skip pad byte. */
}
/*
* We've reached the end of the file. For the restoration to have been a
* success, we must have had one of each of the required chunks.
*/
if (!(progress & GOT_HEADER))
print_string ("error: no valid header (`IFhd') chunk in file.\n");
if (!(progress & GOT_STACK))
print_string ("error: no valid stack (`Stks') chunk in file.\n");
if (!(progress & GOT_MEMORY))
print_string ("error: no valid memory (`CMem' or `UMem') chunk in file.\n");
return (progress == GOT_ALL ? 2 : fatal);
}
/*
* Save a game using Quetzal format. Return 1 if OK, 0 if failed.
*/
zword save_quetzal (FILE *svf, FILE *stf)
{
zlong ifzslen = 0, cmemlen = 0, stkslen = 0;
zlong pc;
zword i, j, n;
zword nvars, nargs, nstk, *p;
zbyte var;
long cmempos, stkspos;
int c;
/* Write `IFZS' header. */
if (!write_chnk (svf, ID_FORM, 0)) return 0;
if (!write_long (svf, ID_IFZS)) return 0;
/* Write `IFhd' chunk. */
GET_PC (pc);
if (!write_chnk (svf, ID_IFhd, 13)) return 0;
if (!write_word (svf, h_release)) return 0;
for (i=H_SERIAL; i<H_SERIAL+6; ++i)
if (!write_byte (svf, zmp[i])) return 0;
if (!write_word (svf, h_checksum)) return 0;
if (!write_long (svf, pc << 8)) /* Includes pad. */ return 0;
/* Write `CMem' chunk. */
if ((cmempos = ftell (svf)) < 0) return 0;
if (!write_chnk (svf, ID_CMem, 0)) return 0;
(void) fseek (stf, 0, SEEK_SET);
/* j holds current run length. */
for (i=0, j=0, cmemlen=0; i < h_dynamic_size; ++i)
{
if ((c = get_c (stf)) == EOF) return 0;
c ^= (int) zmp[i];
if (c == 0)
++j; /* It's a run of equal bytes. */
else
{
/* Write out any run there may be. */
if (j > 0)
{
for (; j > 0x100; j -= 0x100)
{
if (!write_run (svf, 0xFF)) return 0;
cmemlen += 2;
}
if (!write_run (svf, j-1)) return 0;
cmemlen += 2;
j = 0;
}
/* Any runs are now written. Write this (nonzero) byte. */
if (!write_byte (svf, (zbyte) c)) return 0;
++cmemlen;
}
}
/*
* Reached end of dynamic memory. We ignore any unwritten run there may be
* at this point.
*/
if (cmemlen & 1) /* Chunk length must be even. */
if (!write_byte (svf, 0)) return 0;
/* Write `Stks' chunk. You are not expected to understand this. ;) */
if ((stkspos = ftell (svf)) < 0) return 0;
if (!write_chnk (svf, ID_Stks, 0)) return 0;
/*
* We construct a list of frame indices, most recent first, in `frames'.
* These indices are the offsets into the `stack' array of the word before
* the first word pushed in each frame.
*/
frames[0] = sp - stack; /* The frame we'd get by doing a call now. */
for (i = fp - stack + 4, n=0; i < STACK_SIZE+4; i = stack[i-3] + 5)
frames[++n] = i;
/*
* All versions other than V6 can use evaluation stack outside a function
* context. We write a faked stack frame (most fields zero) to cater for
* this.
*/
if (h_version != V6)
{
for (i=0; i<6; ++i)
if (!write_byte (svf, 0)) return 0;
nstk = STACK_SIZE - frames[n];
if (!write_word (svf, nstk)) return 0;
for (j=STACK_SIZE-1; j >= frames[n]; --j)
if (!write_word (svf, stack[j])) return 0;
stkslen = 8 + 2*nstk;
}
/* Write out the rest of the stack frames. */
for (i=n; i>0; --i)
{
p = stack + frames[i] - 4; /* Points to call frame. */
nvars = (p[0] & 0x0F00) >> 8;
nargs = p[0] & 0x00FF;
nstk = frames[i] - frames[i-1] - nvars - 4;
pc = ((zlong) p[3] << 9) | p[2];
switch (p[0] & 0xF000) /* Check type of call. */
{
case 0x0000: /* Function. */
var = zmp[pc];
pc = ((pc + 1) << 8) | nvars;
break;
case 0x1000: /* Procedure. */
var = 0;
pc = (pc << 8) | 0x10 | nvars; /* Set procedure flag. */
break;
/* case 0x2000: */
default:
runtime_error (ERR_SAVE_IN_INTER);
return 0;
}
if (nargs != 0)
nargs = (1 << nargs) - 1; /* Make args into bitmap. */
/* Write the main part of the frame... */
if (!write_long (svf, pc)
|| !write_byte (svf, var)
|| !write_byte (svf, nargs)
|| !write_word (svf, nstk)) return 0;
/* Write the variables and eval stack. */
for (j=0, ++p; j<nvars+nstk; ++j, --p)
if (!write_word (svf, *p)) return 0;
/* Calculate length written thus far. */
stkslen += 8 + 2 * (nvars + nstk);
}
/* Fill in variable chunk lengths. */
ifzslen = 3*8 + 4 + 14 + cmemlen + stkslen;
if (cmemlen & 1)
++ifzslen;
(void) fseek (svf, 4, SEEK_SET);
if (!write_long (svf, ifzslen)) return 0;
(void) fseek (svf, cmempos+4, SEEK_SET);
if (!write_long (svf, cmemlen)) return 0;
(void) fseek (svf, stkspos+4, SEEK_SET);
if (!write_long (svf, stkslen)) return 0;
/* After all that, still nothing went wrong! */
return 1;
}

View file

@ -1,82 +0,0 @@
/* random.c - Z-machine random number generator
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
static long A = 1;
static int interval = 0;
static int counter = 0;
/*
* seed_random
*
* Set the seed value for the random number generator.
*
*/
void seed_random (int value)
{
if (value == 0) { /* ask interface for seed value */
A = os_random_seed ();
interval = 0;
} else if (value < 1000) { /* special seed value */
counter = 0;
interval = value;
} else { /* standard seed value */
A = value;
interval = 0;
}
}/* seed_random */
/*
* z_random, store a random number or set the random number seed.
*
* zargs[0] = range (positive) or seed value (negative)
*
*/
void z_random ()
{
if ((short) zargs[0] <= 0) { /* set random seed */
seed_random (- (short) zargs[0]);
store (0);
} else { /* generate random number */
zword result;
if (interval != 0) { /* ...in special mode */
result = counter++;
if (counter == interval) counter = 0;
} else { /* ...in standard mode */
A = 0x015a4e35L * A + 1;
result = (A >> 16) & 0x7fff;
}
store ((zword) (result % zargs[0] + 1));
}
}/* z_random */

View file

@ -1,172 +0,0 @@
/* redirect.c - Output redirection to Z-machine memory
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
#define MAX_NESTING 16
extern zword get_max_width (zword);
static int depth = -1;
static struct {
zword xsize;
zword table;
zword width;
zword total;
} redirect[MAX_NESTING];
/*
* memory_open
*
* Begin output redirection to the memory of the Z-machine.
*
*/
void memory_open (zword table, zword xsize, bool buffering)
{
if (++depth < MAX_NESTING) {
if (!buffering)
xsize = 0xffff;
if (buffering && (short) xsize <= 0)
xsize = get_max_width ((zword) (- (short) xsize));
storew (table, 0);
redirect[depth].table = table;
redirect[depth].width = 0;
redirect[depth].total = 0;
redirect[depth].xsize = xsize;
ostream_memory = TRUE;
} else runtime_error (ERR_STR3_NESTING);
}/* memory_open */
/*
* memory_new_line
*
* Redirect a newline to the memory of the Z-machine.
*
*/
void memory_new_line (void)
{
zword size;
zword addr;
redirect[depth].total += redirect[depth].width;
redirect[depth].width = 0;
addr = redirect[depth].table;
LOW_WORD (addr, size)
addr += 2;
if (redirect[depth].xsize != 0xffff) {
redirect[depth].table = addr + size;
size = 0;
} else storeb ((zword) (addr + (size++)), 13);
storew (redirect[depth].table, size);
}/* memory_new_line */
/*
* memory_word
*
* Redirect a string of characters to the memory of the Z-machine.
*
*/
void memory_word (const zchar *s)
{
zword size;
zword addr;
zchar c;
if (h_version == V6) {
int width = os_string_width (s);
if (redirect[depth].xsize != 0xffff)
if (redirect[depth].width + width > redirect[depth].xsize) {
if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
width = os_string_width (++s);
memory_new_line ();
}
redirect[depth].width += width;
}
addr = redirect[depth].table;
LOW_WORD (addr, size)
addr += 2;
while ((c = *s++) != 0)
storeb ((zword) (addr + (size++)), translate_to_zscii (c));
storew (redirect[depth].table, size);
}/* memory_word */
/*
* memory_close
*
* End of output redirection.
*
*/
void memory_close (void)
{
if (depth >= 0) {
if (redirect[depth].xsize != 0xffff)
memory_new_line ();
if (h_version == V6) {
h_line_width = (redirect[depth].xsize != 0xffff) ?
redirect[depth].total : redirect[depth].width;
SET_WORD (H_LINE_WIDTH, h_line_width)
}
if (depth == 0)
ostream_memory = FALSE;
depth--;
}
}/* memory_close */

File diff suppressed because it is too large Load diff

View file

@ -1,67 +0,0 @@
/*
* Various status thingies for the interpreter and interface.
*
*/
typedef struct frotz_setup_struct {
int attribute_assignment; /* done */
int attribute_testing; /* done */
int context_lines; /* done */
int object_locating; /* done */
int object_movement; /* done */
int left_margin; /* done */
int right_margin; /* done */
int ignore_errors; /* done */
int interpreter_number; /* Just dumb frotz now */
int piracy; /* done */
int undo_slots; /* done */
int expand_abbreviations; /* done */
int script_cols; /* done */
int save_quetzal; /* done */
int sound; /* done */
int err_report_mode; /* done */
} f_setup_t;
extern f_setup_t f_setup;
typedef struct zcode_header_struct {
zbyte h_version;
zbyte h_config;
zword h_release;
zword h_resident_size;
zword h_start_pc;
zword h_dictionary;
zword h_objects;
zword h_globals;
zword h_dynamic_size;
zword h_flags;
zbyte h_serial[6];
zword h_abbreviations;
zword h_file_size;
zword h_checksum;
zbyte h_interpreter_number;
zbyte h_interpreter_version;
zbyte h_screen_rows;
zbyte h_screen_cols;
zword h_screen_width;
zword h_screen_height;
zbyte h_font_height;
zbyte h_font_width;
zword h_functions_offset;
zword h_strings_offset;
zbyte h_default_background;
zbyte h_default_foreground;
zword h_terminating_keys;
zword h_line_width;
zbyte h_standard_high;
zbyte h_standard_low;
zword h_alphabet;
zword h_extension_table;
zbyte h_user_name[8];
zword hx_table_size;
zword hx_mouse_x;
zword hx_mouse_y;
zword hx_unicode_table;
} z_header_t;

View file

@ -1,204 +0,0 @@
/* sound.c - Sound effect function
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
#ifdef DJGPP
#include "djfrotz.h"
#endif
#define EFFECT_PREPARE 1
#define EFFECT_PLAY 2
#define EFFECT_STOP 3
#define EFFECT_FINISH_WITH 4
extern int direct_call (zword);
static zword routine = 0;
static int next_sample = 0;
static int next_volume = 0;
static bool locked = FALSE;
static bool playing = FALSE;
/*
* init_sound
*
* Initialize sound variables.
*
*/
void init_sound (void)
{
locked = FALSE;
playing = FALSE;
} /* init_sound */
/*
* start_sample
*
* Call the IO interface to play a sample.
*
*/
static void start_sample (int number, int volume, int repeats, zword eos)
{
static zbyte lh_repeats[] = {
0x00, 0x00, 0x00, 0x01, 0xff,
0x00, 0x01, 0x01, 0x01, 0x01,
0xff, 0x01, 0x01, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff
};
if (story_id == LURKING_HORROR)
repeats = lh_repeats[number];
os_start_sample (number, volume, repeats, eos);
routine = eos;
playing = TRUE;
}/* start_sample */
/*
* start_next_sample
*
* Play a sample that has been delayed until the previous sound effect has
* finished. This is necessary for two samples in The Lurking Horror that
* immediately follow other samples.
*
*/
static void start_next_sample (void)
{
if (next_sample != 0)
start_sample (next_sample, next_volume, 0, 0);
next_sample = 0;
next_volume = 0;
}/* start_next_sample */
/*
* end_of_sound
*
* Call the Z-code routine which was given as the last parameter of
* a sound_effect call. This function may be called from a hardware
* interrupt (which requires extremely careful programming).
*
*/
void end_of_sound (void)
{
#if defined(DJGPP) && defined(SOUND_SUPPORT)
end_of_sound_flag = 0;
#endif
playing = FALSE;
if (!locked) {
if (story_id == LURKING_HORROR)
start_next_sample ();
direct_call (routine);
}
}/* end_of_sound */
/*
* z_sound_effect, load / play / stop / discard a sound effect.
*
* zargs[0] = number of bleep (1 or 2) or sample
* zargs[1] = operation to perform (samples only)
* zargs[2] = repeats and volume (play sample only)
* zargs[3] = end-of-sound routine (play sample only, optional)
*
* Note: Volumes range from 1 to 8, volume 255 is the default volume.
* Repeats are stored in the high byte, 255 is infinite loop.
*
*/
void z_sound_effect (void)
{
zword number = zargs[0];
zword effect = zargs[1];
zword volume = zargs[2];
/* By default play sound 1 at volume 8 */
if (zargc < 1)
number = 1;
if (zargc < 2)
effect = EFFECT_PLAY;
if (zargc < 3)
volume = 8;
if (number >= 3 || number == 0) {
locked = TRUE;
if (story_id == LURKING_HORROR && (number == 9 || number == 16)) {
if (effect == EFFECT_PLAY) {
next_sample = number;
next_volume = volume;
locked = FALSE;
if (!playing)
start_next_sample ();
} else locked = FALSE;
return;
}
playing = FALSE;
switch (effect) {
case EFFECT_PREPARE:
os_prepare_sample (number);
break;
case EFFECT_PLAY:
start_sample (number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
break;
case EFFECT_STOP:
os_stop_sample (number);
break;
case EFFECT_FINISH_WITH:
os_finish_with_sample (number);
break;
}
locked = FALSE;
} else os_beep (number);
}/* z_sound_effect */

View file

@ -1,365 +0,0 @@
/* stream.c - IO stream implementation
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
extern bool handle_hot_key (zchar);
extern bool validate_click (void);
extern void replay_open (void);
extern void replay_close (void);
extern void memory_open (zword, zword, bool);
extern void memory_close (void);
extern void record_open (void);
extern void record_close (void);
extern void script_open (void);
extern void script_close (void);
extern void memory_word (const zchar *);
extern void memory_new_line (void);
extern void record_write_key (zchar);
extern void record_write_input (const zchar *, zchar);
extern void script_char (zchar);
extern void script_word (const zchar *);
extern void script_new_line (void);
extern void script_write_input (const zchar *, zchar);
extern void script_erase_input (const zchar *);
extern void script_mssg_on (void);
extern void script_mssg_off (void);
extern void screen_char (zchar);
extern void screen_word (const zchar *);
extern void screen_new_line (void);
extern void screen_write_input (const zchar *, zchar);
extern void screen_erase_input (const zchar *);
extern void screen_mssg_on (void);
extern void screen_mssg_off (void);
extern zchar replay_read_key (void);
extern zchar replay_read_input (zchar *);
extern zchar console_read_key (zword);
extern zchar console_read_input (int, zchar *, zword, bool);
extern int direct_call (zword);
/*
* stream_mssg_on
*
* Start printing a "debugging" message.
*
*/
void stream_mssg_on (void)
{
flush_buffer ();
if (ostream_screen)
screen_mssg_on ();
if (ostream_script && enable_scripting)
script_mssg_on ();
message = TRUE;
}/* stream_mssg_on */
/*
* stream_mssg_off
*
* Stop printing a "debugging" message.
*
*/
void stream_mssg_off (void)
{
flush_buffer ();
if (ostream_screen)
screen_mssg_off ();
if (ostream_script && enable_scripting)
script_mssg_off ();
message = FALSE;
}/* stream_mssg_off */
/*
* z_output_stream, open or close an output stream.
*
* zargs[0] = stream to open (positive) or close (negative)
* zargs[1] = address to redirect output to (stream 3 only)
* zargs[2] = width of redirected output (stream 3 only, optional)
*
*/
void z_output_stream (void)
{
flush_buffer ();
switch ((short) zargs[0]) {
case 1: ostream_screen = TRUE;
break;
case -1: ostream_screen = FALSE;
break;
case 2: if (!ostream_script) script_open ();
break;
case -2: if (ostream_script) script_close ();
break;
case 3: memory_open (zargs[1], zargs[2], zargc >= 3);
break;
case -3: memory_close ();
break;
case 4: if (!ostream_record) record_open ();
break;
case -4: if (ostream_record) record_close ();
break;
}
}/* z_output_stream */
/*
* stream_char
*
* Send a single character to the output stream.
*
*/
void stream_char (zchar c)
{
if (ostream_screen)
screen_char (c);
if (ostream_script && enable_scripting)
script_char (c);
}/* stream_char */
/*
* stream_word
*
* Send a string of characters to the output streams.
*
*/
void stream_word (const zchar *s)
{
if (ostream_memory && !message)
memory_word (s);
else {
if (ostream_screen)
screen_word (s);
if (ostream_script && enable_scripting)
script_word (s);
}
}/* stream_word */
/*
* stream_new_line
*
* Send a newline to the output streams.
*
*/
void stream_new_line (void)
{
if (ostream_memory && !message)
memory_new_line ();
else {
if (ostream_screen)
screen_new_line ();
if (ostream_script && enable_scripting)
script_new_line ();
}
}/* stream_new_line */
/*
* z_input_stream, select an input stream.
*
* zargs[0] = input stream to be selected
*
*/
void z_input_stream (void)
{
flush_buffer ();
if (zargs[0] == 0 && istream_replay)
replay_close ();
if (zargs[0] == 1 && !istream_replay)
replay_open ();
}/* z_input_stream */
/*
* stream_read_key
*
* Read a single keystroke from the current input stream.
*
*/
zchar stream_read_key ( zword timeout, zword routine,
bool hot_keys )
{
zchar key = ZC_BAD;
flush_buffer ();
/* Read key from current input stream */
continue_input:
do {
if (istream_replay)
key = replay_read_key ();
else
key = console_read_key (timeout);
} while (key == ZC_BAD);
/* Verify mouse clicks */
if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
if (!validate_click ())
goto continue_input;
/* Copy key to the command file */
if (ostream_record && !istream_replay)
record_write_key (key);
/* Handle timeouts */
if (key == ZC_TIME_OUT)
if (direct_call (routine) == 0)
goto continue_input;
/* Handle hot keys */
if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
if (h_version == V4 && key == ZC_HKEY_UNDO)
goto continue_input;
if (!handle_hot_key (key))
goto continue_input;
return ZC_BAD;
}
/* Return key */
return key;
}/* stream_read_key */
/*
* stream_read_input
*
* Read a line of input from the current input stream.
*
*/
zchar stream_read_input ( int max, zchar *buf,
zword timeout, zword routine,
bool hot_keys,
bool no_scripting )
{
zchar key = ZC_BAD;
flush_buffer ();
/* Remove initial input from the transscript file or from the screen */
if (ostream_script && enable_scripting && !no_scripting)
script_erase_input (buf);
if (istream_replay)
screen_erase_input (buf);
/* Read input line from current input stream */
continue_input:
do {
if (istream_replay)
key = replay_read_input (buf);
else
key = console_read_input (max, buf, timeout, key != ZC_BAD);
} while (key == ZC_BAD);
/* Verify mouse clicks */
if (key == ZC_SINGLE_CLICK || key == ZC_DOUBLE_CLICK)
if (!validate_click ())
goto continue_input;
/* Copy input line to the command file */
if (ostream_record && !istream_replay)
record_write_input (buf, key);
/* Handle timeouts */
if (key == ZC_TIME_OUT)
if (direct_call (routine) == 0)
goto continue_input;
/* Handle hot keys */
if (hot_keys && key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) {
if (!handle_hot_key (key))
goto continue_input;
return ZC_BAD;
}
/* Copy input line to transscript file or to the screen */
if (ostream_script && enable_scripting && !no_scripting)
script_write_input (buf, key);
if (istream_replay)
screen_write_input (buf, key);
/* Return terminating key */
return key;
}/* stream_read_input */

View file

@ -1,193 +0,0 @@
/* table.c - Table handling opcodes
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
/*
* z_copy_table, copy a table or fill it with zeroes.
*
* zargs[0] = address of table
* zargs[1] = destination address or 0 for fill
* zargs[2] = size of table
*
* Note: Copying is safe even when source and destination overlap; but
* if zargs[1] is negative the table _must_ be copied forwards.
*
*/
void z_copy_table (void)
{
zword addr;
zword size = zargs[2];
zbyte value;
int i;
if (zargs[1] == 0) /* zero table */
for (i = 0; i < size; i++)
storeb ((zword) (zargs[0] + i), 0);
else if ((short) size < 0 || zargs[0] > zargs[1]) /* copy forwards */
for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
addr = zargs[0] + i;
LOW_BYTE (addr, value)
storeb ((zword) (zargs[1] + i), value);
}
else /* copy backwards */
for (i = size - 1; i >= 0; i--) {
addr = zargs[0] + i;
LOW_BYTE (addr, value)
storeb ((zword) (zargs[1] + i), value);
}
}/* z_copy_table */
/*
* z_loadb, store a value from a table of bytes.
*
* zargs[0] = address of table
* zargs[1] = index of table entry to store
*
*/
void z_loadb (void)
{
zword addr = zargs[0] + zargs[1];
zbyte value;
LOW_BYTE (addr, value)
store (value);
}/* z_loadb */
/*
* z_loadw, store a value from a table of words.
*
* zargs[0] = address of table
* zargs[1] = index of table entry to store
*
*/
void z_loadw (void)
{
zword addr = zargs[0] + 2 * zargs[1];
zword value;
LOW_WORD (addr, value)
store (value);
}/* z_loadw */
/*
* z_scan_table, find and store the address of a target within a table.
*
* zargs[0] = target value to be searched for
* zargs[1] = address of table
* zargs[2] = number of table entries to check value against
* zargs[3] = type of table (optional, defaults to 0x82)
*
* Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
* it's a byte array. The lower bits hold the address step.
*
*/
void z_scan_table (void)
{
zword addr = zargs[1];
int i;
/* Supply default arguments */
if (zargc < 4)
zargs[3] = 0x82;
/* Scan byte or word array */
for (i = 0; i < zargs[2]; i++) {
if (zargs[3] & 0x80) { /* scan word array */
zword wvalue;
LOW_WORD (addr, wvalue)
if (wvalue == zargs[0])
goto finished;
} else { /* scan byte array */
zbyte bvalue;
LOW_BYTE (addr, bvalue)
if (bvalue == zargs[0])
goto finished;
}
addr += zargs[3] & 0x7f;
}
addr = 0;
finished:
store (addr);
branch (addr);
}/* z_scan_table */
/*
* z_storeb, write a byte into a table of bytes.
*
* zargs[0] = address of table
* zargs[1] = index of table entry
* zargs[2] = value to be written
*
*/
void z_storeb (void)
{
storeb ((zword) (zargs[0] + zargs[1]), zargs[2]);
}/* z_storeb */
/*
* z_storew, write a word into a table of words.
*
* zargs[0] = address of table
* zargs[1] = index of table entry
* zargs[2] = value to be written
*
*/
void z_storew (void)
{
storew ((zword) (zargs[0] + 2 * zargs[1]), zargs[2]);
}/* z_storew */

File diff suppressed because it is too large Load diff

View file

@ -1,304 +0,0 @@
/* variable.c - Variable and stack related opcodes
* Copyright (c) 1995-1997 Stefan Jokisch
*
* This file is part of Frotz.
*
* Frotz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Frotz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "frotz.h"
/*
* z_dec, decrement a variable.
*
* zargs[0] = variable to decrement
*
*/
void z_dec (void)
{
zword value;
if (zargs[0] == 0)
(*sp)--;
else if (zargs[0] < 16)
(*(fp - zargs[0]))--;
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
LOW_WORD (addr, value)
value--;
SET_WORD (addr, value)
}
}/* z_dec */
/*
* z_dec_chk, decrement a variable and branch if now less than value.
*
* zargs[0] = variable to decrement
* zargs[1] = value to check variable against
*
*/
void z_dec_chk (void)
{
zword value;
if (zargs[0] == 0)
value = --(*sp);
else if (zargs[0] < 16)
value = --(*(fp - zargs[0]));
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
LOW_WORD (addr, value)
value--;
SET_WORD (addr, value)
}
branch ((short) value < (short) zargs[1]);
}/* z_dec_chk */
/*
* z_inc, increment a variable.
*
* zargs[0] = variable to increment
*
*/
void z_inc (void)
{
zword value;
if (zargs[0] == 0)
(*sp)++;
else if (zargs[0] < 16)
(*(fp - zargs[0]))++;
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
LOW_WORD (addr, value)
value++;
SET_WORD (addr, value)
}
}/* z_inc */
/*
* z_inc_chk, increment a variable and branch if now greater than value.
*
* zargs[0] = variable to increment
* zargs[1] = value to check variable against
*
*/
void z_inc_chk (void)
{
zword value;
if (zargs[0] == 0)
value = ++(*sp);
else if (zargs[0] < 16)
value = ++(*(fp - zargs[0]));
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
LOW_WORD (addr, value)
value++;
SET_WORD (addr, value)
}
branch ((short) value > (short) zargs[1]);
}/* z_inc_chk */
/*
* z_load, store the value of a variable.
*
* zargs[0] = variable to store
*
*/
void z_load (void)
{
zword value;
if (zargs[0] == 0)
value = *sp;
else if (zargs[0] < 16)
value = *(fp - zargs[0]);
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
LOW_WORD (addr, value)
}
store (value);
}/* z_load */
/*
* z_pop, pop a value off the game stack and discard it.
*
* no zargs used
*
*/
void z_pop (void)
{
sp++;
}/* z_pop */
/*
* z_pop_stack, pop n values off the game or user stack and discard them.
*
* zargs[0] = number of values to discard
* zargs[1] = address of user stack (optional)
*
*/
void z_pop_stack (void)
{
if (zargc == 2) { /* it's a user stack */
zword size;
zword addr = zargs[1];
LOW_WORD (addr, size)
size += zargs[0];
storew (addr, size);
} else sp += zargs[0]; /* it's the game stack */
}/* z_pop_stack */
/*
* z_pull, pop a value off...
*
* a) ...the game or a user stack and store it (V6)
*
* zargs[0] = address of user stack (optional)
*
* b) ...the game stack and write it to a variable (other than V6)
*
* zargs[0] = variable to write value to
*
*/
void z_pull (void)
{
zword value;
if (h_version != V6) { /* not a V6 game, pop stack and write */
value = *sp++;
if (zargs[0] == 0)
*sp = value;
else if (zargs[0] < 16)
*(fp - zargs[0]) = value;
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
SET_WORD (addr, value)
}
} else { /* it's V6, but is there a user stack? */
if (zargc == 1) { /* it's a user stack */
zword size;
zword addr = zargs[0];
LOW_WORD (addr, size)
size++;
storew (addr, size);
addr += 2 * size;
LOW_WORD (addr, value)
} else value = *sp++; /* it's the game stack */
store (value);
}
}/* z_pull */
/*
* z_push, push a value onto the game stack.
*
* zargs[0] = value to push onto the stack
*
*/
void z_push (void)
{
*--sp = zargs[0];
}/* z_push */
/*
* z_push_stack, push a value onto a user stack then branch if successful.
*
* zargs[0] = value to push onto the stack
* zargs[1] = address of user stack
*
*/
void z_push_stack (void)
{
zword size;
zword addr = zargs[1];
LOW_WORD (addr, size)
if (size != 0) {
storew ((zword) (addr + 2 * size), zargs[0]);
size--;
storew (addr, size);
}
branch (size);
}/* z_push_stack */
/*
* z_store, write a value to a variable.
*
* zargs[0] = variable to be written to
* zargs[1] = value to write
*
*/
void z_store (void)
{
zword value = zargs[1];
if (zargs[0] == 0)
*sp = value;
else if (zargs[0] < 16)
*(fp - zargs[0]) = value;
else {
zword addr = h_globals + 2 * (zargs[0] - 16);
SET_WORD (addr, value)
}
}/* z_store */

View file

@ -1,42 +0,0 @@
/* dumb-frotz.h
* $Id: dumb-frotz.h,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
* Frotz os functions for a standard C library and a dumb terminal.
* Now you can finally play Zork Zero on your Teletype.
*
* Copyright 1997, 1998 Alembic Petrofsky <alembic@petrofsky.berkeley.ca.us>.
* Any use permitted provided this notice stays intact.
*/
#include "../common/frotz.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define VERSION "1.0"
/* from ../common/setup.h */
extern f_setup_t f_setup;
/* From input.c. */
bool is_terminator (zchar);
/* dumb-input.c */
bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup);
void dumb_init_input(void);
/* dumb-output.c */
void dumb_init_output(void);
bool dumb_output_handle_setting(const char *setting, bool show_cursor,
bool startup);
void dumb_show_screen(bool show_cursor);
void dumb_show_prompt(bool show_cursor, char line_type);
void dumb_dump_screen(void);
void dumb_display_user_input(char *);
void dumb_discard_old_input(int num_chars);
void dumb_elide_more_prompt(void);
void dumb_set_picture_cell(int row, int col, char c);
/* dumb-pic.c */
void dumb_init_pictures(char *graphics_filename);

View file

@ -1,234 +0,0 @@
/* dumb-init.c
* $Id: dumb-init.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
*
* Copyright 1997,1998 Alva Petrofsky <alva@petrofsky.berkeley.ca.us>.
* Any use permitted provided this notice stays intact.
*/
#include "dumb_frotz.h"
f_setup_t f_setup;
#define INFORMATION "\
An interpreter for all Infocom and other Z-Machine games.\n\
Complies with standard 1.0 of Graham Nelson's specification.\n\
\n\
Syntax: dfrotz [options] story-file\n\
-a watch attribute setting \t -Q use old-style save format\n\
-A watch attribute testing \t -R xxx do runtime setting \\xxx\n\
-h # screen height \t before starting (can be used repeatedly)\n\
-i ignore fatal errors \t -s # random number seed value\n\
-I # interpreter number \t -S # transscript width\n\
-o watch object movement \t -t set Tandy bit\n\
-O watch object locating \t -u # slots for multiple undo\n\
-p plain ASCII output only \t -w # screen width\n\
-P alter piracy opcode \t -x expand abbreviations g/x/z"
/*
static char usage[] = "\
\n\
FROTZ V2.32 - interpreter for all Infocom games. Complies with standard\n\
1.0 of Graham Nelson's specification. Written by Stefan Jokisch in 1995-7.\n\
\n\
DUMB-FROTZ V2.32R1 - port for all platforms. Somewhat complies with standard\n\
9899 of ISO's specification. Written by Alembic Petrofsky in 1997-8.\n\
\n\
Syntax: frotz [options] story-file [graphics-file]\n\
\n\
-a watch attribute setting\n\
-A watch attribute testing\n\
-h # screen height\n\
-i ignore runtime errors\n\
-I # interpreter number to report to game\n\
-o watch object movement\n\
-O watch object locating\n\
-p alter piracy opcode\n\
-P transliterate latin1 to plain ASCII\n\
-R xxx do runtime setting \\xxx before starting\n\
(this option can be used multiple times)\n\
-s # random number seed value\n\
-S # transscript width\n\
-t set Tandy bit\n\
-u # slots for multiple undo\n\
-w # screen width\n\
-x expand abbreviations g/x/z\n\
\n\
While running, enter \"\\help\" to list the runtime escape sequences.\n\
";
*/
/* A unix-like getopt, but with the names changed to avoid any problems. */
static int zoptind = 1;
static int zoptopt = 0;
static char *zoptarg = NULL;
static int zgetopt (int argc, char *argv[], const char *options)
{
static pos = 1;
const char *p;
if (zoptind >= argc || argv[zoptind][0] != '-' || argv[zoptind][1] == 0)
return EOF;
zoptopt = argv[zoptind][pos++];
zoptarg = NULL;
if (argv[zoptind][pos] == 0)
{ pos = 1; zoptind++; }
p = strchr (options, zoptopt);
if (zoptopt == ':' || p == NULL) {
fputs ("illegal option -- ", stderr);
goto error;
} else if (p[1] == ':')
if (zoptind >= argc) {
fputs ("option requires an argument -- ", stderr);
goto error;
} else {
zoptarg = argv[zoptind];
if (pos != 1)
zoptarg += pos;
pos = 1; zoptind++;
}
return zoptopt;
error:
fputc (zoptopt, stderr);
fputc ('\n', stderr);
return '?';
}/* zgetopt */
static int user_screen_width = 75;
static int user_screen_height = 24;
static int user_interpreter_number = -1;
static int user_random_seed = -1;
static int user_tandy_bit = 0;
static char *graphics_filename = NULL;
static bool plain_ascii = FALSE;
void os_process_arguments(int argc, char *argv[])
{
int c;
/* Parse the options */
do {
c = zgetopt(argc, argv, "aAh:iI:oOpPQs:R:S:tu:w:xZ:");
switch(c) {
case 'a': f_setup.attribute_assignment = 1; break;
case 'A': f_setup.attribute_testing = 1; break;
case 'h': user_screen_height = atoi(zoptarg); break;
case 'i': f_setup.ignore_errors = 1; break;
case 'I': f_setup.interpreter_number = atoi(zoptarg); break;
case 'o': f_setup.object_movement = 1; break;
case 'O': f_setup.object_locating = 1; break;
case 'P': f_setup.piracy = 1; break;
case 'p': plain_ascii = 1; break;
case 'Q': f_setup.save_quetzal = 0; break;
case 'R': dumb_handle_setting(zoptarg, FALSE, TRUE); break;
case 's': user_random_seed = atoi(zoptarg); break;
case 'S': f_setup.script_cols = atoi(zoptarg); break;
case 't': user_tandy_bit = 1; break;
case 'u': f_setup.undo_slots = atoi(zoptarg); break;
case 'w': user_screen_width = atoi(zoptarg); break;
case 'x': f_setup.expand_abbreviations = 1; break;
case 'Z': f_setup.err_report_mode = atoi(zoptarg);
if ((f_setup.err_report_mode < ERR_REPORT_NEVER) ||
(f_setup.err_report_mode > ERR_REPORT_FATAL))
f_setup.err_report_mode = ERR_DEFAULT_REPORT_MODE;
break;
}
} while (c != EOF);
if (((argc - zoptind) != 1) && ((argc - zoptind) != 2)) {
printf("FROTZ V%s\tdumb interface.\n", VERSION);
puts(INFORMATION);
printf("\t-Z # error checking mode (default = %d)\n"
"\t %d = don't report errors %d = report first error\n"
"\t %d = report all errors %d = exit after any error\n\n",
ERR_DEFAULT_REPORT_MODE, ERR_REPORT_NEVER,
ERR_REPORT_ONCE, ERR_REPORT_ALWAYS, ERR_REPORT_FATAL);
exit(1);
}
/*
if (((argc - zoptind) != 1) && ((argc - zoptind) != 2)) {
puts(usage);
exit(1);
}
*/
story_name = argv[zoptind++];
if (zoptind < argc)
graphics_filename = argv[zoptind++];
}
void os_init_screen(void)
{
if (h_version == V3 && user_tandy_bit)
h_config |= CONFIG_TANDY;
if (h_version >= V5 && f_setup.undo_slots == 0)
h_flags &= ~UNDO_FLAG;
h_screen_rows = user_screen_height;
h_screen_cols = user_screen_width;
if (user_interpreter_number > 0)
h_interpreter_number = user_interpreter_number;
else {
/* Use ms-dos for v6 (because that's what most people have the
* graphics files for), but don't use it for v5 (or Beyond Zork
* will try to use funky characters). */
h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20;
}
h_interpreter_version = 'F';
dumb_init_input();
dumb_init_output();
dumb_init_pictures(graphics_filename);
}
int os_random_seed (void)
{
if (user_random_seed == -1)
/* Use the epoch as seed value */
return (time(0) & 0x7fff);
else return user_random_seed;
}
void os_restart_game (int stage) {}
void os_fatal (const char *s)
{
fprintf(stderr, "\nFatal error: %s\n", s);
exit(1);
}
FILE *os_path_open(const char *name, const char *mode)
{
FILE *fp;
char buf[FILENAME_MAX + 1];
char *p;
/* Let's see if the file is in the currect directory */
/* or if the user gave us a full path. */
if ((fp = fopen(name, mode))) {
return fp;
}
/* Sorry, but dumb frotz is too dumb to care about searching paths. */
return NULL;
}
void os_init_setup(void)
{
f_setup.attribute_assignment = 0;
f_setup.attribute_testing = 0;
f_setup.context_lines = 0;
f_setup.object_locating = 0;
f_setup.object_movement = 0;
f_setup.left_margin = 0;
f_setup.right_margin = 0;
f_setup.ignore_errors = 0;
f_setup.piracy = 0;
f_setup.undo_slots = MAX_UNDO_SLOTS;
f_setup.expand_abbreviations = 0;
f_setup.script_cols = 80;
f_setup.save_quetzal = 1;
f_setup.sound = 1;
f_setup.err_report_mode = ERR_DEFAULT_REPORT_MODE;
}

View file

@ -1,430 +0,0 @@
/* dumb-input.c
* $Id: dumb-input.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
* Copyright 1997,1998 Alpine Petrofsky <alpine@petrofsky.berkeley.ca.us>.
* Any use permitted provided this notice stays intact.
*/
#include "dumb_frotz.h"
f_setup_t f_setup;
static char runtime_usage[] =
"DUMB-FROTZ runtime help:\n"
" General Commands:\n"
" \\help Show this message.\n"
" \\set Show the current values of runtime settings.\n"
" \\s Show the current contents of the whole screen.\n"
" \\d Discard the part of the input before the cursor.\n"
" \\wN Advance clock N/10 seconds, possibly causing the current\n"
" and subsequent inputs to timeout.\n"
" \\w Advance clock by the amount of real time since this input\n"
" started (times the current speed factor).\n"
" \\t Advance clock just enough to timeout the current input\n"
" Reverse-Video Display Method Settings:\n"
" \\rn none \\rc CAPS \\rd doublestrike \\ru underline\n"
" \\rbC show rv blanks as char C (orthogonal to above modes)\n"
" Output Compression Settings:\n"
" \\cn none: show whole screen before every input.\n"
" \\cm max: show only lines that have new nonblank characters.\n"
" \\cs spans: like max, but emit a blank line between each span of\n"
" screen lines shown.\n"
" \\chN Hide top N lines (orthogonal to above modes).\n"
" Misc Settings:\n"
" \\sfX Set speed factor to X. (0 = never timeout automatically).\n"
" \\mp Toggle use of MORE prompts\n"
" \\ln Toggle display of line numbers.\n"
" \\lt Toggle display of the line type identification chars.\n"
" \\vb Toggle visual bell.\n"
" \\pb Toggle display of picture outline boxes.\n"
" (Toggle commands can be followed by a 1 or 0 to set value ON or OFF.)\n"
" Character Escapes:\n"
" \\\\ backslash \\# backspace \\[ escape \\_ return\n"
" \\< \\> \\^ \\. cursor motion \\1 ..\\0 f1..f10\n"
" \\D ..\\X Standard Frotz hotkeys. Use \\H (help) to see the list.\n"
" Line Type Identification Characters:\n"
" Input lines:\n"
" untimed timed\n"
" > T A regular line-oriented input\n"
" ) t A single-character input\n"
" } D A line input with some input before the cursor.\n"
" (Use \\d to discard it.)\n"
" Output lines:\n"
" ] Output line that contains the cursor.\n"
" . A blank line emitted as part of span compression.\n"
" (blank) Any other output line.\n"
;
static float speed = 1;
static bool do_more_prompts = FALSE;
enum input_type {
INPUT_CHAR,
INPUT_LINE,
INPUT_LINE_CONTINUED,
};
/* get a character. Exit with no fuss on EOF. */
static int xgetchar(void)
{
int c = getchar();
if (c == EOF) {
if (feof(stdin)) {
fprintf(stderr, "\nEOT\n");
exit(0);
}
os_fatal(strerror(errno));
}
return c;
}
/* Read one line, including the newline, into s. Safely avoids buffer
* overruns (but that's kind of pointless because there are several
* other places where I'm not so careful). */
static void getline_(char *s)
{
int c;
char *p;
fflush(stdout);
p = s;
while (p < s + INPUT_BUFFER_SIZE - 1)
if ((*p++ = xgetchar()) == '\n') {
*p = '\0';
return;
}
p[-1] = '\n';
p[0] = '\0';
while ((c = xgetchar()) != '\n')
;
printf("Line too long, truncated to %s\n", s - INPUT_BUFFER_SIZE);
}
/* Translate in place all the escape characters in s. */
static void translate_special_chars(char *s)
{
char *src = s, *dest = s;
while (*src)
switch(*src++) {
default: *dest++ = src[-1]; break;
case '\n': *dest++ = ZC_RETURN; break;
case '\\':
switch (*src++) {
case '\n': *dest++ = ZC_RETURN; break;
case '\\': *dest++ = '\\'; break;
case '?': *dest++ = ZC_BACKSPACE; break;
case '[': *dest++ = ZC_ESCAPE; break;
case '_': *dest++ = ZC_RETURN; break;
case '^': *dest++ = ZC_ARROW_UP; break;
case '.': *dest++ = ZC_ARROW_DOWN; break;
case '<': *dest++ = ZC_ARROW_LEFT; break;
case '>': *dest++ = ZC_ARROW_RIGHT; break;
case 'R': *dest++ = ZC_HKEY_RECORD; break;
case 'P': *dest++ = ZC_HKEY_PLAYBACK; break;
case 'S': *dest++ = ZC_HKEY_SEED; break;
case 'U': *dest++ = ZC_HKEY_UNDO; break;
case 'N': *dest++ = ZC_HKEY_RESTART; break;
case 'X': *dest++ = ZC_HKEY_QUIT; break;
case 'D': *dest++ = ZC_HKEY_DEBUG; break;
case 'H': *dest++ = ZC_HKEY_HELP; break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
*dest++ = ZC_FKEY_MIN + src[-1] - '0' - 1; break;
case '0': *dest++ = ZC_FKEY_MIN + 9; break;
default:
fprintf(stderr, "DUMB-FROTZ: unknown escape char: %c\n", src[-1]);
fprintf(stderr, "Enter \\help to see the list\n");
}
}
*dest = '\0';
}
/* The time in tenths of seconds that the user is ahead of z time. */
static int time_ahead = 0;
/* Called from os_read_key and os_read_line if they have input from
* a previous call to dumb_read_line.
* Returns TRUE if we should timeout rather than use the read-ahead.
* (because the user is further ahead than the timeout). */
static bool check_timeout(int timeout)
{
if ((timeout == 0) || (timeout > time_ahead))
time_ahead = 0;
else
time_ahead -= timeout;
return time_ahead != 0;
}
/* If val is '0' or '1', set *var accordingly, otherwise toggle it. */
static void toggle(bool *var, char val)
{
*var = val == '1' || (val != '0' && !*var);
}
/* Handle input-related user settings and call dumb_output_handle_setting. */
bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup)
{
if (!strncmp(setting, "sf", 2)) {
speed = atof(&setting[2]);
printf("Speed Factor %g\n", speed);
} else if (!strncmp(setting, "mp", 2)) {
toggle(&do_more_prompts, setting[2]);
printf("More prompts %s\n", do_more_prompts ? "ON" : "OFF");
} else {
if (!strcmp(setting, "set")) {
printf("Speed Factor %g\n", speed);
printf("More Prompts %s\n", do_more_prompts ? "ON" : "OFF");
}
return dumb_output_handle_setting(setting, show_cursor, startup);
}
return TRUE;
}
/* Read a line, processing commands (lines that start with a backslash
* (that isn't the start of a special character)), and write the
* first non-command to s.
* Return true if timed-out. */
static bool dumb_read_line(char *s, char *prompt, bool show_cursor,
int timeout, enum input_type type,
zchar *continued_line_chars)
{
time_t start_time;
if (timeout) {
if (time_ahead >= timeout) {
time_ahead -= timeout;
return TRUE;
}
timeout -= time_ahead;
start_time = time(0);
}
time_ahead = 0;
dumb_show_screen(show_cursor);
for (;;) {
char *command;
if (prompt)
fputs(prompt, stdout);
else
dumb_show_prompt(show_cursor, (timeout ? "tTD" : ")>}")[type]);
getline_(s);
if ((s[0] != '\\') || ((s[1] != '\0') && !islower(s[1]))) {
/* Is not a command line. */
translate_special_chars(s);
if (timeout) {
int elapsed = (time(0) - start_time) * 10 * speed;
if (elapsed > timeout) {
time_ahead = elapsed - timeout;
return TRUE;
}
}
return FALSE;
}
/* Commands. */
/* Remove the \ and the terminating newline. */
command = s + 1;
command[strlen(command) - 1] = '\0';
if (!strcmp(command, "t")) {
if (timeout) {
time_ahead = 0;
s[0] = '\0';
return TRUE;
}
} else if (*command == 'w') {
if (timeout) {
int elapsed = atoi(&command[1]);
time_t now = time(0);
if (elapsed == 0)
elapsed = (now - start_time) * 10 * speed;
if (elapsed >= timeout) {
time_ahead = elapsed - timeout;
s[0] = '\0';
return TRUE;
}
timeout -= elapsed;
start_time = now;
}
} else if (!strcmp(command, "d")) {
if (type != INPUT_LINE_CONTINUED)
fprintf(stderr, "DUMB-FROTZ: No input to discard\n");
else {
dumb_discard_old_input(strlen(continued_line_chars));
continued_line_chars[0] = '\0';
type = INPUT_LINE;
}
} else if (!strcmp(command, "help")) {
if (!do_more_prompts)
fputs(runtime_usage, stdout);
else {
char *current_page, *next_page;
current_page = next_page = runtime_usage;
for (;;) {
int i;
for (i = 0; (i < h_screen_rows - 2) && *next_page; i++)
next_page = strchr(next_page, '\n') + 1;
printf("%.*s", next_page - current_page, current_page);
current_page = next_page;
if (!*current_page)
break;
printf("HELP: Type <return> for more, or q <return> to stop: ");
getline_(s);
if (!strcmp(s, "q\n"))
break;
}
}
} else if (!strcmp(command, "s")) {
dumb_dump_screen();
} else if (!dumb_handle_setting(command, show_cursor, FALSE)) {
fprintf(stderr, "DUMB-FROTZ: unknown command: %s\n", s);
fprintf(stderr, "Enter \\help to see the list of commands\n");
}
}
}
/* Read a line that is not part of z-machine input (more prompts and
* filename requests). */
static void dumb_read_misc_line(char *s, char *prompt)
{
dumb_read_line(s, prompt, 0, 0, 0, 0);
/* Remove terminating newline */
s[strlen(s) - 1] = '\0';
}
/* For allowing the user to input in a single line keys to be returned
* for several consecutive calls to read_char, with no screen update
* in between. Useful for traversing menus. */
static char read_key_buffer[INPUT_BUFFER_SIZE];
/* Similar. Useful for using function key abbreviations. */
static char read_line_buffer[INPUT_BUFFER_SIZE];
zchar os_read_key (int timeout, bool show_cursor)
{
char c;
int timed_out;
/* Discard any keys read for line input. */
read_line_buffer[0] = '\0';
if (read_key_buffer[0] == '\0') {
timed_out = dumb_read_line(read_key_buffer, NULL, show_cursor, timeout,
INPUT_CHAR, NULL);
/* An empty input line is reported as a single CR.
* If there's anything else in the line, we report only the line's
* contents and not the terminating CR. */
if (strlen(read_key_buffer) > 1)
read_key_buffer[strlen(read_key_buffer) - 1] = '\0';
} else
timed_out = check_timeout(timeout);
if (timed_out)
return ZC_TIME_OUT;
c = read_key_buffer[0];
memmove(read_key_buffer, read_key_buffer + 1, strlen(read_key_buffer));
/* TODO: error messages for invalid special chars. */
return c;
}
zchar os_read_line (int max, zchar *buf, int timeout, int width, int continued)
{
char *p;
int terminator;
static bool timed_out_last_time;
int timed_out;
/* Discard any keys read for single key input. */
read_key_buffer[0] = '\0';
/* After timing out, discard any further input unless we're continuing. */
if (timed_out_last_time && !continued)
read_line_buffer[0] = '\0';
if (read_line_buffer[0] == '\0')
timed_out = dumb_read_line(read_line_buffer, NULL, TRUE, timeout,
buf[0] ? INPUT_LINE_CONTINUED : INPUT_LINE,
buf);
else
timed_out = check_timeout(timeout);
if (timed_out) {
timed_out_last_time = TRUE;
return ZC_TIME_OUT;
}
/* find the terminating character. */
for (p = read_line_buffer;; p++) {
if (is_terminator(*p)) {
terminator = *p;
*p++ = '\0';
break;
}
}
/* TODO: Truncate to width and max. */
/* copy to screen */
dumb_display_user_input(read_line_buffer);
/* copy to the buffer and save the rest for next time. */
strcat(buf, read_line_buffer);
p = read_line_buffer + strlen(read_line_buffer) + 1;
memmove(read_line_buffer, p, strlen(p) + 1);
/* If there was just a newline after the terminating character,
* don't save it. */
if ((read_line_buffer[0] == '\r') && (read_line_buffer[1] == '\0'))
read_line_buffer[0] = '\0';
timed_out_last_time = FALSE;
return terminator;
}
int os_read_file_name (char *file_name, const char *default_name, int flag)
{
char buf[INPUT_BUFFER_SIZE], prompt[INPUT_BUFFER_SIZE];
FILE *fp;
sprintf(prompt, "Please enter a filename [%s]: ", default_name);
dumb_read_misc_line(buf, prompt);
if (strlen(buf) > MAX_FILE_NAME) {
printf("Filename too long\n");
return FALSE;
}
strcpy (file_name, buf[0] ? buf : default_name);
/* Warn if overwriting a file. */
// if ((flag == FILE_SAVE || flag == FILE_SAVE_AUX || flag == FILE_RECORD)
// && ((fp = fopen(file_name, "rb")) != NULL)) {
// fclose (fp);
// dumb_read_misc_line(buf, "Overwrite existing file? ");
// return(tolower(buf[0]) == 'y');
// }
return TRUE;
}
void os_more_prompt (void)
{
if (do_more_prompts) {
char buf[INPUT_BUFFER_SIZE];
dumb_read_misc_line(buf, "***MORE***");
} else
dumb_elide_more_prompt();
}
void dumb_init_input(void)
{
if ((h_version >= V4) && (speed != 0))
h_config |= CONFIG_TIMEDINPUT;
if (h_version >= V5)
h_flags &= ~(MOUSE_FLAG | MENU_FLAG);
}
zword os_read_mouse(void)
{
/* NOT IMPLEMENTED */
}

View file

@ -1,535 +0,0 @@
/* dumb-output.c
* $Id: dumb-output.c,v 1.2 2002/03/26 22:52:31 feedle Exp $
*
* Copyright 1997,1998 Alfresco Petrofsky <alfresco@petrofsky.berkeley.edu>.
* Any use permitted provided this notice stays intact.
*/
#include "dumb_frotz.h"
f_setup_t f_setup;
static bool show_line_numbers = FALSE;
static bool show_line_types = -1;
static bool show_pictures = TRUE;
static bool visual_bell = TRUE;
static bool plain_ascii = FALSE;
static char latin1_to_ascii[] =
" ! c L >o< Y | S '' C a << not - R _ "
"^0 +/- ^2 ^3 ' my P . , ^1 o >> 1/4 1/2 3/4 ? "
"A A A A Ae A AE C E E E E I I I I "
"Th N O O O O Oe * O U U U Ue Y Th ss "
"a a a a ae a ae c e e e e i i i i "
"th n o o o o oe : o u u u ue y th y "
;
/* h_screen_rows * h_screen_cols */
static int screen_cells;
/* The in-memory state of the screen. */
/* Each cell contains a style in the upper byte and a char in the lower. */
typedef unsigned short cell;
static cell *screen_data;
static cell make_cell(int style, char c) {return (style << 8) | (0xff & c);}
static char cell_char(cell c) {return c & 0xff;}
static int cell_style(cell c) {return c >> 8;}
/* A cell's style is REVERSE_STYLE, normal (0), or PICTURE_STYLE.
* PICTURE_STYLE means the character is part of an ascii image outline
* box. (This just buys us the ability to turn box display on and off
* with immediate effect. No, not very useful, but I wanted to give
* the rv bit some company in that huge byte I allocated for it.) */
#define PICTURE_STYLE 16
static int current_style = 0;
/* Which cells have changed (1 byte per cell). */
static char *screen_changes;
static int cursor_row = 0, cursor_col = 0;
/* Compression styles. */
static enum {
COMPRESSION_NONE, COMPRESSION_SPANS, COMPRESSION_MAX,
} compression_mode = COMPRESSION_SPANS;
static char *compression_names[] = {"NONE", "SPANS", "MAX"};
static int hide_lines = 0;
/* Reverse-video display styles. */
static enum {
RV_NONE, RV_DOUBLESTRIKE, RV_UNDERLINE, RV_CAPS,
} rv_mode = RV_NONE;
static char *rv_names[] = {"NONE", "DOUBLESTRIKE", "UNDERLINE", "CAPS"};
static char rv_blank_char = ' ';
static cell *dumb_row(int r) {return screen_data + r * h_screen_cols;}
static char *dumb_changes_row(int r)
{
return screen_changes + r * h_screen_cols;
}
int os_char_width (zchar z)
{
if (plain_ascii && z >= ZC_LATIN1_MIN && z <= ZC_LATIN1_MAX) {
char *p = latin1_to_ascii + 4 * (z - ZC_LATIN1_MIN);
return strchr(p, ' ') - p;
}
return 1;
}
int os_string_width (const zchar *s)
{
int width = 0;
zchar c;
while ((c = *s++) != 0)
if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT)
s++;
else
width += os_char_width(c);
return width;
}
void os_set_cursor(int row, int col)
{
cursor_row = row - 1; cursor_col = col - 1;
if (cursor_row >= h_screen_rows)
cursor_row = h_screen_rows - 1;
}
/* Set a cell and update screen_changes. */
static void dumb_set_cell(int row, int col, cell c)
{
dumb_changes_row(row)[col] = (c != dumb_row(row)[col]);
dumb_row(row)[col] = c;
}
void dumb_set_picture_cell(int row, int col, char c)
{
dumb_set_cell(row, col, make_cell(PICTURE_STYLE, c));
}
/* Copy a cell and copy its changedness state.
* This is used for scrolling. */
static void dumb_copy_cell(int dest_row, int dest_col,
int src_row, int src_col)
{
dumb_row(dest_row)[dest_col] = dumb_row(src_row)[src_col];
dumb_changes_row(dest_row)[dest_col] = dumb_changes_row(src_row)[src_col];
}
void os_set_text_style(int x)
{
current_style = x & REVERSE_STYLE;
}
/* put a character in the cell at the cursor and advance the cursor. */
static void dumb_display_char(char c)
{
dumb_set_cell(cursor_row, cursor_col, make_cell(current_style, c));
if (++cursor_col == h_screen_cols)
if (cursor_row == h_screen_rows - 1)
cursor_col--;
else {
cursor_row++;
cursor_col = 0;
}
}
void dumb_display_user_input(char *s)
{
/* copy to screen without marking it as a change. */
while (*s)
dumb_row(cursor_row)[cursor_col++] = make_cell(0, *s++);
}
void dumb_discard_old_input(int num_chars)
{
/* Weird discard stuff. Grep spec for 'pain in my butt'. */
/* The old characters should be on the screen just before the cursor.
* Erase them. */
cursor_col -= num_chars;
if (cursor_col < 0)
cursor_col = 0;
os_erase_area(cursor_row + 1, cursor_col + 1,
cursor_row + 1, cursor_col + num_chars);
}
void os_display_char (zchar c)
{
if (c >= ZC_LATIN1_MIN && c <= ZC_LATIN1_MAX) {
if (plain_ascii) {
char *ptr = latin1_to_ascii + 4 * (c - ZC_LATIN1_MIN);
do
dumb_display_char(*ptr++);
while (*ptr != ' ');
} else
dumb_display_char(c);
} else if (c >= 32 && c <= 126) {
dumb_display_char(c);
} else if (c == ZC_GAP) {
dumb_display_char(' '); dumb_display_char(' ');
} else if (c == ZC_INDENT) {
dumb_display_char(' '); dumb_display_char(' '); dumb_display_char(' ');
}
return;
}
/* Haxor your boxor? */
void os_display_string (const zchar *s)
{
zchar c;
while ((c = *s++) != 0)
if (c == ZC_NEW_FONT)
s++;
else if (c == ZC_NEW_STYLE)
os_set_text_style(*s++);
else {
os_display_char (c);
}
}
void os_erase_area (int top, int left, int bottom, int right)
{
int row, col;
top--; left--; bottom--; right--;
for (row = top; row <= bottom; row++)
for (col = left; col <= right; col++)
dumb_set_cell(row, col, make_cell(current_style, ' '));
}
void os_scroll_area (int top, int left, int bottom, int right, int units)
{
int row, col;
top--; left--; bottom--; right--;
if (units > 0) {
for (row = top; row <= bottom - units; row++)
for (col = left; col <= right; col++)
dumb_copy_cell(row, col, row + units, col);
os_erase_area(bottom - units + 2, left + 1, bottom + 1, right + 1);
} else if (units < 0) {
for (row = bottom; row >= top - units; row--)
for (col = left; col <= right; col++)
dumb_copy_cell(row, col, row + units, col);
os_erase_area(top + 1, left + 1, top - units, right + 1);
}
}
int os_font_data(int font, int *height, int *width)
{
if (font == TEXT_FONT) {
*height = 1; *width = 1; return 1;
}
return 0;
}
void os_set_colour (int x, int y) {}
void os_set_font (int x) {}
/* Print a cell to stdout. */
static void show_cell(cell cel)
{
char c = cell_char(cel);
switch (cell_style(cel)) {
case 0:
putchar(c);
break;
case PICTURE_STYLE:
putchar(show_pictures ? c : ' ');
break;
case REVERSE_STYLE:
if (c == ' ')
putchar(rv_blank_char);
else
switch (rv_mode) {
case RV_NONE: putchar(c); break;
case RV_CAPS: putchar(toupper(c)); break;
case RV_UNDERLINE: putchar('_'); putchar('\b'); putchar(c); break;
case RV_DOUBLESTRIKE: putchar(c); putchar('\b'); putchar(c); break;
}
break;
}
}
static bool will_print_blank(cell c)
{
return (((cell_style(c) == PICTURE_STYLE) && !show_pictures)
|| ((cell_char(c) == ' ')
&& ((cell_style(c) != REVERSE_STYLE) || (rv_blank_char == ' '))));
}
static void show_line_prefix(int row, char c)
{
if (show_line_numbers)
printf((row == -1) ? ".." : "%02d", (row + 1) % 100);
if (show_line_types)
putchar(c);
/* Add a separator char (unless there's nothing to separate). */
if (show_line_numbers || show_line_types)
putchar(' ');
}
/* Print a row to stdout. */
static void show_row(int r)
{
if (r == -1) {
show_line_prefix(-1, '.');
} else {
int c, last;
show_line_prefix(r, (r == cursor_row) ? ']' : ' ');
/* Don't print spaces at end of line. */
/* (Saves bandwidth and printhead wear.) */
/* TODO: compress spaces to tabs. */
for (last = h_screen_cols - 1; last >= 0; last--)
if (!will_print_blank(dumb_row(r)[last]))
break;
for (c = 0; c <= last; c++)
show_cell(dumb_row(r)[c]);
}
putchar('\n');
}
/* Print the part of the cursor row before the cursor. */
void dumb_show_prompt(bool show_cursor, char line_type)
{
int i;
show_line_prefix(show_cursor ? cursor_row : -1, line_type);
if (show_cursor)
for (i = 0; i < cursor_col; i++)
show_cell(dumb_row(cursor_row)[i]);
}
static void mark_all_unchanged(void)
{
memset(screen_changes, 0, screen_cells);
}
/* Check if a cell is a blank or will display as one.
* (Used to help decide if contents are worth printing.) */
static bool is_blank(cell c)
{
return ((cell_char(c) == ' ')
|| ((cell_style(c) == PICTURE_STYLE) && !show_pictures));
}
/* Show the current screen contents, or what's changed since the last
* call.
*
* If compressing, and show_cursor is true, and the cursor is past the
* last nonblank character on the last line that would be shown, then
* don't show that line (because it will be redundant with the prompt
* line just below it). */
void dumb_show_screen(bool show_cursor)
{
int r, c, first, last;
char changed_rows[0x100];
/* Easy case */
if (compression_mode == COMPRESSION_NONE) {
for (r = hide_lines; r < h_screen_rows; r++)
show_row(r);
mark_all_unchanged();
return;
}
/* Check which rows changed, and where the first and last change is. */
first = last = -1;
memset(changed_rows, 0, h_screen_rows);
for (r = hide_lines; r < h_screen_rows; r++) {
for (c = 0; c < h_screen_cols; c++)
if (dumb_changes_row(r)[c] && !is_blank(dumb_row(r)[c]))
break;
changed_rows[r] = (c != h_screen_cols);
if (changed_rows[r]) {
first = (first != -1) ? first : r;
last = r;
}
}
if (first == -1)
return;
/* The show_cursor rule described above */
if (show_cursor && (cursor_row == last)) {
for (c = cursor_col; c < h_screen_cols; c++)
if (!is_blank(dumb_row(last)[c]))
break;
if (c == h_screen_cols)
last--;
}
/* Display the appropriate rows. */
if (compression_mode == COMPRESSION_MAX) {
for (r = first; r <= last; r++)
if (changed_rows[r])
show_row(r);
} else {
/* COMPRESSION_SPANS */
for (r = first; r <= last; r++) {
if (changed_rows[r] || changed_rows[r + 1])
show_row(r);
else {
while (!changed_rows[r + 1])
r++;
show_row(-1);
}
}
if (show_cursor && (cursor_row > last + 1))
show_row((cursor_row == last + 2) ? (last + 1) : -1);
}
mark_all_unchanged();
}
/* Unconditionally show whole screen. For \s user command. */
void dumb_dump_screen(void)
{
int r;
for (r = 0; r < h_screen_height; r++)
show_row(r);
}
/* Called when it's time for a more prompt but user has them turned off. */
void dumb_elide_more_prompt(void)
{
dumb_show_screen(FALSE);
if (compression_mode == COMPRESSION_SPANS && hide_lines == 0) {
show_row(-1);
}
}
void os_reset_screen(void)
{
dumb_show_screen(FALSE);
}
void os_beep (int volume)
{
if (visual_bell)
printf("[%s-PITCHED BEEP]\n", (volume == 1) ? "HIGH" : "LOW");
else
putchar('\a'); /* so much for dumb. */
}
/* To make the common code happy */
void os_prepare_sample (int a) {}
void os_finish_with_sample (int a) {}
void os_start_sample (int a, int b, int c, zword d) {}
void os_stop_sample (int a) {}
/* if val is '0' or '1', set *var accordingly, else toggle it. */
static void toggle(bool *var, char val)
{
*var = val == '1' || (val != '0' && !*var);
}
bool dumb_output_handle_setting(const char *setting, bool show_cursor,
bool startup)
{
char *p;
int i;
if (!strncmp(setting, "pb", 2)) {
toggle(&show_pictures, setting[2]);
printf("Picture outlines display %s\n", show_pictures ? "ON" : "OFF");
if (startup)
return TRUE;
for (i = 0; i < screen_cells; i++)
screen_changes[i] = (cell_style(screen_data[i]) == PICTURE_STYLE);
dumb_show_screen(show_cursor);
} else if (!strncmp(setting, "vb", 2)) {
toggle(&visual_bell, setting[2]);
printf("Visual bell %s\n", visual_bell ? "ON" : "OFF");
os_beep(1); os_beep(2);
} else if (!strncmp(setting, "ln", 2)) {
toggle(&show_line_numbers, setting[2]);
printf("Line numbering %s\n", show_line_numbers ? "ON" : "OFF");
} else if (!strncmp(setting, "lt", 2)) {
toggle(&show_line_types, setting[2]);
printf("Line-type display %s\n", show_line_types ? "ON" : "OFF");
} else if (*setting == 'c') {
switch (setting[1]) {
case 'm': compression_mode = COMPRESSION_MAX; break;
case 's': compression_mode = COMPRESSION_SPANS; break;
case 'n': compression_mode = COMPRESSION_NONE; break;
case 'h': hide_lines = atoi(&setting[2]); break;
default: return FALSE;
}
printf("Compression mode %s, hiding top %d lines\n",
compression_names[compression_mode], hide_lines);
} else if (*setting == 'r') {
switch (setting[1]) {
case 'n': rv_mode = RV_NONE; break;
case 'o': rv_mode = RV_DOUBLESTRIKE; break;
case 'u': rv_mode = RV_UNDERLINE; break;
case 'c': rv_mode = RV_CAPS; break;
case 'b': rv_blank_char = setting[2] ? setting[2] : ' '; break;
default: return FALSE;
}
printf("Reverse-video mode %s, blanks reverse to '%c': ",
rv_names[rv_mode], rv_blank_char);
for (p = "sample reverse text"; *p; p++)
show_cell(make_cell(REVERSE_STYLE, *p));
putchar('\n');
for (i = 0; i < screen_cells; i++)
screen_changes[i] = (cell_style(screen_data[i]) == REVERSE_STYLE);
dumb_show_screen(show_cursor);
} else if (!strcmp(setting, "set")) {
printf("Compression Mode %s, hiding top %d lines\n",
compression_names[compression_mode], hide_lines);
printf("Picture Boxes display %s\n", show_pictures ? "ON" : "OFF");
printf("Visual Bell %s\n", visual_bell ? "ON" : "OFF");
os_beep(1); os_beep(2);
printf("Line Numbering %s\n", show_line_numbers ? "ON" : "OFF");
printf("Line-Type display %s\n", show_line_types ? "ON" : "OFF");
printf("Reverse-Video mode %s, Blanks reverse to '%c': ",
rv_names[rv_mode], rv_blank_char);
for (p = "sample reverse text"; *p; p++)
show_cell(make_cell(REVERSE_STYLE, *p));
putchar('\n');
} else
return FALSE;
return TRUE;
}
void dumb_init_output(void)
{
if (h_version == V3) {
h_config |= CONFIG_SPLITSCREEN;
h_flags &= ~OLD_SOUND_FLAG;
}
if (h_version >= V5) {
h_flags &= ~SOUND_FLAG;
}
h_screen_height = h_screen_rows;
h_screen_width = h_screen_cols;
screen_cells = h_screen_rows * h_screen_cols;
h_font_width = 1; h_font_height = 1;
if (show_line_types == -1)
show_line_types = h_version > 3;
screen_data = malloc(screen_cells * sizeof(cell));
screen_changes = malloc(screen_cells);
os_erase_area(1, 1, h_screen_rows, h_screen_cols);
memset(screen_changes, 0, screen_cells);
}

View file

@ -1,153 +0,0 @@
/* dumb-pic.c
* $Id: dumb-pic.c,v 1.1.1.1 2002/03/26 22:38:34 feedle Exp $
*
* Copyright 1997,1998 Alcibiades Petrofsky
* <alcibiades@petrofsky.berkeley.ca.us>.
* Any use permitted provided this notice stays intact.
*/
#include "dumb_frotz.h"
f_setup_t f_setup;
#define PIC_FILE_HEADER_FLAGS 1
#define PIC_FILE_HEADER_NUM_IMAGES 4
#define PIC_FILE_HEADER_ENTRY_SIZE 8
#define PIC_FILE_HEADER_VERSION 14
#define PIC_HEADER_NUMBER 0
#define PIC_HEADER_WIDTH 2
#define PIC_HEADER_HEIGHT 4
static struct {
int z_num;
int width;
int height;
int orig_width;
int orig_height;
} *pict_info;
static int num_pictures = 0;
static unsigned char lookupb(unsigned char *p, int n) {return p[n];}
static unsigned short lookupw(unsigned char *p, int n)
{
return (p[n + 1] << 8) | p[n];
}
void dumb_init_pictures (char *filename)
{
FILE *file = NULL;
int success = FALSE;
unsigned char gheader[16];
unsigned char *raw_info = NULL;
int i, entry_size, flags;
float x_scaler, y_scaler;
do {
if ((h_version != V6)
|| !filename
|| ((file = fopen (filename, "rb")) == NULL)
|| (fread(&gheader, sizeof (gheader), 1, file) != 1))
break;
num_pictures = lookupw(gheader, PIC_FILE_HEADER_NUM_IMAGES);
entry_size = lookupb(gheader, PIC_FILE_HEADER_ENTRY_SIZE);
flags = lookupb(gheader, PIC_FILE_HEADER_FLAGS);
raw_info = malloc(num_pictures * entry_size);
if (fread(raw_info, num_pictures * entry_size, 1, file) != 1)
break;
pict_info = malloc((num_pictures + 1) * sizeof(*pict_info));
pict_info[0].z_num = 0;
pict_info[0].height = num_pictures;
pict_info[0].width = lookupw(gheader, PIC_FILE_HEADER_VERSION);
y_scaler = h_screen_rows / 200.0;
x_scaler = h_screen_cols / ((flags & 0x08) ? 640.0 : 320.0);
/* Copy and scale. */
for (i = 1; i <= num_pictures; i++) {
unsigned char *p = raw_info + entry_size * (i - 1);
pict_info[i].z_num = lookupw(p, PIC_HEADER_NUMBER);
pict_info[i].orig_height = lookupw(p, PIC_HEADER_HEIGHT);
pict_info[i].orig_width = lookupw(p, PIC_HEADER_WIDTH);
pict_info[i].height = pict_info[i].orig_height * y_scaler + .5;
pict_info[i].width = pict_info[i].orig_width * x_scaler + .5;
}
success = TRUE;
} while (0);
if (file)
fclose(file);
if (raw_info)
free(raw_info);
if (success)
h_config |= CONFIG_PICTURES;
else
{
h_flags &= ~GRAPHICS_FLAG;
if (filename)
fprintf(stderr, "Warning: could not read graphics file %s\n", filename);
}
}
/* Convert a Z picture number to an index into pict_info. */
static int z_num_to_index(int n)
{
int i;
for (i = 0; i <= num_pictures; i++)
if (pict_info[i].z_num == n)
return i;
return -1;
}
bool os_picture_data(int num, int *height, int *width)
{
int index;
*height = 0;
*width = 0;
if (!pict_info)
return FALSE;
if ((index = z_num_to_index(num)) == -1)
return FALSE;
*height = pict_info[index].height;
*width = pict_info[index].width;
return TRUE;
}
void os_draw_picture (int num, int row, int col)
{
int width, height, r, c;
if (!os_picture_data(num, &height, &width) || !width || !height)
return;
col--, row--;
/* Draw corners */
dumb_set_picture_cell(row, col, '+');
dumb_set_picture_cell(row, col + width - 1, '+');
dumb_set_picture_cell(row + height - 1, col, '+');
dumb_set_picture_cell(row + height - 1, col + width - 1, '+');
/* sides */
for (c = col + 1; c < col + width - 1; c++) {
dumb_set_picture_cell(row, c, '-');
dumb_set_picture_cell(row + height - 1, c, '-');
}
for (r = row + 1; r < row + height - 1; r++) {
dumb_set_picture_cell(r, col, '|');
dumb_set_picture_cell(r, col + width - 1, '|');
}
/* body, but for last line */
for (r = row + 1; r < row + height - 2; r++)
for (c = col + 1; c < col + width - 1; c++)
dumb_set_picture_cell(r, c, ':');
/* Last line of body, including picture number. */
if (height >= 3)
for (c = col + width - 2; c > col; c--, (num /= 10))
dumb_set_picture_cell(row + height - 2, c, num ? (num % 10 + '0') : ':');
}
int os_peek_colour (void) {return BLACK_COLOUR; }

View file

@ -1,358 +0,0 @@
/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This example is free, and not covered by LGPL license. There is no
* restriction applied to their modification, redistribution, using and so on.
* You can study them, modify them, use them in your own program - either
* completely or partially. By using it you may give me some credits in your
* program, but you don't have to.
*/
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "Swiften/Swiften.h"
#include "Swiften/SwiftenCompat.h"
#include <boost/filesystem.hpp>
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
Swift::SimpleEventLoop *loop_;
using namespace boost::program_options;
using namespace Transport;
class FrotzNetworkPlugin;
FrotzNetworkPlugin * np = NULL;
#define PARENT_READ p.readpipe[0]
#define CHILD_WRITE p.readpipe[1]
#define CHILD_READ p.writepipe[0]
#define PARENT_WRITE p.writepipe[1]
typedef struct dfrotz_ {
pid_t pid;
std::string game;
int readpipe[2];
int writepipe[2];
} dfrotz;
using namespace boost::filesystem;
static const char *howtoplay = "To move around, just type the direction you want to go. Directions can be\n"
"abbreviated: NORTH to N, SOUTH to S, EAST to E, WEST to W, NORTHEAST to\n"
"NE, NORTHWEST to NW, SOUTHEAST to SE, SOUTHWEST to SW, UP to U, and DOWN\n"
"to D. IN and OUT will also work in certain places.\n"
"\n"
"There are many differnet kinds of sentences used in Interactive Fiction.\n"
"Here are some examples:\n"
"\n"
"> WALK TO THE NORTH\n"
"> WEST\n"
"> NE\n"
"> DOWN\n"
"> TAKE THE BIRDCAGE\n"
"> READ ABOUT DIMWIT FLATHEAD\n"
"> LOOK UP MEGABOZ IN THE ENCYCLOPEDIA\n"
"> LIE DOWN IN THE PINK SOFA\n"
"> EXAMINE THE SHINY COIN\n"
"> PUT THE RUSTY KEY IN THE CARDBOARD BOX\n"
"> SHOW MY BOW TIE TO THE BOUNCER\n"
"> HIT THE CRAWLING CRAB WITH THE GIANT NUTCRACKER\n"
"> ASK THE COWARDLY KING ABOUT THE CROWN JEWELS\n"
"\n"
"You can use multiple objects with certain verbs if you separate them by\n"
"the word \"AND\" or by a comma. Here are some examples:\n"
"\n"
"> TAKE THE BOOK AND THE FROG\n"
"> DROP THE JAR OF PEANUT BUTTER, THE SPOON, AND THE LEMMING FOOD\n"
"> PUT THE EGG AND THE PENCIL IN THE CABINET\n"
"\n"
"You can include several inputs on one line if you separate them by the\n"
"word \"THEN\" or by a period. Each input will be handled in order, as\n"
"though you had typed them individually at seperate prompts. For example,\n"
"you could type all of the following at once, before pressing the ENTER (or\n"
"RETURN) key:\n"
"\n"
"> TURN ON THE LIGHT. TAKE THE BOOK THEN READ ABOUT THE JESTER IN THE BOOK\n"
"\n"
"If the story doesn't understand one of the sentences on your input line,\n"
"or if an unusual event occurs, it will ignore the rest of your input line.\n"
"\n"
"The words \"IT\" and \"ALL\" can be very useful. For example:\n"
"\n"
"> EXAMINE THE APPLE. TAKE IT. EAT IT\n"
"> CLOSE THE HEAVY METAL DOOR. LOCK IT\n"
"> PICK UP THE GREEN BOOT. SMELL IT. PUT IT ON.\n"
"> TAKE ALL\n"
"> TAKE ALL THE TOOLS\n"
"> DROP ALL THE TOOLS EXCEPT THE WRENCH AND MINIATURE HAMMER\n"
"> TAKE ALL FROM THE CARTON\n"
"> GIVE ALL BUT THE RUBY SLIPPERS TO THE WICKED WITCH\n"
"\n"
"The word \"ALL\" refers to every visible object except those inside\n"
"something else. If there were an apple on the ground and an orange inside\n"
"a cabinet, \"TAKE ALL\" would take the apple but not the orange.\n"
"\n"
"There are three kinds of questions you can ask: \"WHERE IS (something)\",\n"
"\"WHAT IS (something)\", and \"WHO IS (someone)\". For example:\n"
"\n"
"> WHO IS LORD DIMWIT?\n"
"> WHAT IS A GRUE?\n"
"> WHERE IS EVERYBODY?\n"
"\n"
"When you meet intelligent creatures, you can talk to them by typing their\n"
"name, then a comma, then whatever you want to say to them. Here are some\n"
"examples:\n"
"\n"
"> JESTER, HELLO\n"
"> GUSTAR WOOMAX, TELL ME ABOUT THE COCONUT\n"
"> UNCLE OTTO, GIVE ME YOUR WALLET\n"
"> HORSE, WHERE IS YOUR SADDLE?\n"
"> BOY, RUN HOME THEN CALL THE POLICE\n"
"> MIGHTY WIZARD, TAKE THIS POISONED APPLE. EAT IT\n"
"\n"
"Notice that in the last two examples, you are giving the characters more\n"
"than one command on the same input line. Keep in mind, however, that many\n"
"creatures don't care for idle chatter; your actions will speak louder than\n"
"your words. \n";
static void start_dfrotz(dfrotz &p, const std::string &game) {
// p.writepipe[0] = -1;
if (pipe(p.readpipe) < 0 || pipe(p.writepipe) < 0) {
}
std::cout << "dfrotz -p " << game << "\n";
if ((p.pid = fork()) < 0) {
/* FATAL: cannot fork child */
}
else if (p.pid == 0) {
close(PARENT_WRITE);
close(PARENT_READ);
dup2(CHILD_READ, 0); close(CHILD_READ);
dup2(CHILD_WRITE, 1); close(CHILD_WRITE);
execlp("dfrotz", "-p", game.c_str(), NULL);
}
else {
close(CHILD_READ);
close(CHILD_WRITE);
}
}
class FrotzNetworkPlugin : public NetworkPlugin {
public:
Swift::BoostNetworkFactories *m_factories;
Swift::BoostIOServiceThread m_boostIOServiceThread;
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
FrotzNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
this->config = config;
m_factories = new Swift::BoostNetworkFactories(loop);
m_conn = m_factories->getConnectionFactory()->createConnection();
m_conn->onDataRead.connect(boost::bind(&FrotzNetworkPlugin::_handleDataRead, this, _1));
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
// m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
// m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
}
void sendData(const std::string &string) {
m_conn->write(Swift::createSafeByteArray(string));
}
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
std::string d(data->begin(), data->end());
handleDataRead(d);
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
np->handleConnected(user);
std::vector<std::string> groups;
groups.push_back("ZCode");
np->handleBuddyChanged(user, "zcode", "ZCode", groups, pbnetwork::STATUS_ONLINE);
// sleep(1);
// np->handleMessage(np->m_user, "zork", first_msg);
}
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
if (games.find(user) != games.end()) {
kill(games[user].pid, SIGTERM);
games.erase(user);
}
// exit(0);
}
void readMessage(const std::string &user) {
static char buf[15000];
buf[0] = 0;
int repeated = 0;
while (strlen(buf) == 0) {
ssize_t len = read(games[user].readpipe[0], buf, 15000);
if (len > 0) {
buf[len] = 0;
}
usleep(1000);
repeated++;
if (repeated > 30)
return;
}
np->handleMessage(user, "zcode", buf);
std::string msg = "save\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
msg = user + "_" + games[user].game + ".save\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
ignoreMessage(user);
}
void ignoreMessage(const std::string &user) {
usleep(1000000);
static char buf[15000];
buf[0] = 0;
int repeated = 0;
while (strlen(buf) == 0) {
ssize_t len = read(games[user].readpipe[0], buf, 15000);
if (len > 0) {
buf[len] = 0;
}
usleep(1000);
repeated++;
if (repeated > 30)
return;
}
std::cout << "ignoring: " << buf << "\n";
}
std::vector<std::string> getGames() {
std::vector<std::string> games;
path p(".");
directory_iterator end_itr;
for (directory_iterator itr(p); itr != end_itr; ++itr) {
if (extension(itr->path()) == ".z5") {
#if BOOST_FILESYSTEM_VERSION == 3
games.push_back(itr->path().filename().string());
#else
games.push_back(itr->path().leaf());
#endif
}
}
return games;
}
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
std::cout << "aaa\n";
if (message.find("start") == 0) {
std::string game = message.substr(6);
std::vector<std::string> lst = getGames();
if (std::find(lst.begin(), lst.end(), game) == lst.end()) {
np->handleMessage(user, "zcode", "Unknown game");
return;
}
np->handleMessage(user, "zcode", "Starting the game");
dfrotz d;
d.game = game;
start_dfrotz(d, game);
games[user] = d;
fcntl(games[user].readpipe[0], F_SETFL, O_NONBLOCK);
if (boost::filesystem::exists(user + "_" + games[user].game + ".save")) {
std::string msg = "restore\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
msg = user + "_" + games[user].game + ".save\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
ignoreMessage(user);
msg = "l\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
}
readMessage(user);
}
else if (message == "stop" && games.find(user) != games.end()) {
kill(games[user].pid, SIGTERM);
games.erase(user);
np->handleMessage(user, "zcode", "Game stopped");
}
else if (message == "howtoplay") {
np->handleMessage(user, "zcode", howtoplay);
}
else if (games.find(user) != games.end()) {
std::string msg = message + "\n";
write(games[user].writepipe[1], msg.c_str(), msg.size());
readMessage(user);
}
else {
std::string games;
BOOST_FOREACH(const std::string &game, getGames()) {
games += game + "\n";
}
np->handleMessage(user, "zcode", "Games are saved/loaded automatically. Use \"restart\" to restart existing game. Emulator commands are:\nstart <game>\nstop\nhowtoplay\n\nList of games:\n" + games);
}
}
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
}
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
}
std::map<std::string, dfrotz> games;
std::string first_msg;
private:
Config *config;
};
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
int main (int argc, char* argv[]) {
std::string host;
int port;
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
std::string error;
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
if (cfg == NULL) {
std::cerr << error;
return 1;
}
Swift::SimpleEventLoop eventLoop;
loop_ = &eventLoop;
np = new FrotzNetworkPlugin(cfg, &eventLoop, host, port);
loop_->run();
delete cfg;
return 0;
}

View file

@ -1,13 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp)
FILE(GLOB HEADERS *.h)
QT4_WRAP_CPP(SRC ${HEADERS} OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC})
if (NOT WIN32)
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport pthread)
else ()
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} Qt4::QtNetwork Qt4::QtCore transport)
endif()
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)

View file

@ -1,70 +0,0 @@
#include <QtCore>
#include <iostream>
#include <IrcCommand>
#include <IrcMessage>
namespace CommuniBackport {
bool parseColors(const QString& message, int pos, int* len, int* fg = 0, int* bg = 0)
{
// fg(,bg)
*len = 0;
if (fg)
*fg = -1;
if (bg)
*bg = -1;
QRegExp rx(QLatin1String("(\\d{1,2})(?:,(\\d{1,2}))?"));
int idx = rx.indexIn(message, pos);
if (idx == pos) {
*len = rx.matchedLength();
if (fg)
*fg = rx.cap(1).toInt();
if (bg) {
bool ok = false;
int tmp = rx.cap(2).toInt(&ok);
if (ok)
*bg = tmp;
}
}
return *len > 0;
}
/*!
Converts \a text to plain text. This function parses the text and
strips away IRC-style formatting like colors, bold and underline.
\sa toHtml()
*/
void toPlainText(QString& processed)
{
int pos = 0;
int len = 0;
while (pos < processed.size()) {
switch (processed.at(pos).unicode()) {
case '\x02': // bold
case '\x0f': // none
case '\x13': // strike-through
case '\x15': // underline
case '\x16': // inverse
case '\x1d': // italic
case '\x1f': // underline
processed.remove(pos, 1);
break;
case '\x03': // color
if (parseColors(processed, pos + 1, &len))
processed.remove(pos, len + 1);
else
processed.remove(pos, 1);
break;
default:
++pos;
break;
}
}
}
}

View file

@ -1,301 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <IrcCommand>
#include <IrcMessage>
#include "ircnetworkplugin.h"
#include "transport/Logging.h"
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) {
m_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(m_config, "service.irc_server", "");
if (!server.empty()) {
m_servers.push_back(server);
}
else {
std::list<std::string> list;
list = CONFIG_LIST_DEFAULTED(m_config, "service.irc_server", list);
m_servers.insert(m_servers.begin(), list.begin(), list.end());
}
if (CONFIG_HAS_KEY(m_config, "service.irc_identify")) {
m_identify = CONFIG_STRING(m_config, "service.irc_identify");
}
else {
m_identify = "NickServ identify $name $password";
}
}
void IRCNetworkPlugin::tryNextServer() {
if (!m_servers.empty()) {
int nextServer = (m_currentServer + 1) % m_servers.size();
LOG4CXX_INFO(logger, "Server " << m_servers[m_currentServer] << " disconnected user. Next server to try will be " << m_servers[nextServer]);
m_currentServer = nextServer;
}
}
void IRCNetworkPlugin::readData() {
size_t availableBytes = m_socket->bytesAvailable();
if (availableBytes == 0)
return;
if (m_firstPing) {
m_firstPing = false;
NetworkPlugin::PluginConfig cfg;
cfg.setNeedRegistration(false);
cfg.setSupportMUC(true);
cfg.disableJIDEscaping();
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());
}
MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix) {
MyIrcSession *session = new MyIrcSession(user, this, suffix);
session->setUserName(FROM_UTF8(nickname));
session->setNickName(FROM_UTF8(nickname));
session->setRealName(FROM_UTF8(nickname));
// session->setEncoding("UTF8");
std::vector<std::string> hostname_parts;
boost::split(hostname_parts, hostname, boost::is_any_of(":/"));
if (hostname_parts.size() == 2 && !hostname_parts[0].empty() && !hostname_parts[1].empty()) { // hostname was splitted
session->setHost(FROM_UTF8(hostname_parts[0])); // real hostname
int port = atoi(hostname_parts[1].c_str()); // user port
if (hostname_parts[1][0] == '+' || port == 6697) { // use SSL
port = (port < 1 || port > 65535) ? 6697 : port; // default to standard SSL port
session->setSecure(true);
} else { // use TCP
port = (port < 1 || port > 65535) ? 6667 : port; // default to standart TCP port
}
session->setPort(port);
} else { // hostname was not splitted: default to old behaviour
session->setHost(FROM_UTF8(hostname));
session->setPort(6667);
}
if (!password.empty()) {
std::string identify = m_identify;
boost::replace_all(identify, "$password", password);
boost::replace_all(identify, "$name", nickname);
if (CONFIG_BOOL_DEFAULTED(m_config, "service.irc_send_pass", false)) {
session->setPassword(FROM_UTF8(password)); // use IRC PASS
} else {
session->setIdentify(identify); // use identify supplied
}
}
session->createBufferModel();
LOG4CXX_INFO(logger, user << ": Connecting " << hostname << " as " << nickname << ", port=" << session->port() << ", suffix=" << suffix);
return session;
}
void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
if (!m_servers.empty()) {
// legacy name is user's nickname
if (m_sessions[user] != NULL) {
LOG4CXX_WARN(logger, user << ": Already logged in.");
return;
}
m_sessions[user] = createSession(user, m_servers[m_currentServer], legacyName, password, "");
m_sessions[user]->open();
}
else {
// We are waiting for first room join to connect user to IRC network, because we don't know which
// network he chooses...
LOG4CXX_INFO(logger, user << ": Ready for connections");
handleConnected(user);
}
}
void IRCNetworkPlugin::handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
handleVCard(user, id, legacyName, "", "", "");
}
void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
if (m_sessions[user] == NULL) {
LOG4CXX_WARN(logger, user << ": Already disconnected.");
return;
}
LOG4CXX_INFO(logger, user << ": Disconnecting.");
m_sessions[user]->close();
m_sessions[user]->deleteLater();
m_sessions.erase(user);
}
std::string IRCNetworkPlugin::getSessionName(const std::string &user, const std::string &legacyName) {
std::string u = user;
if (!CONFIG_BOOL(m_config, "service.server_mode") && m_servers.empty()) {
u = user + legacyName.substr(legacyName.find("@") + 1);
if (u.find("/") != std::string::npos) {
u = u.substr(0, u.find("/"));
}
}
return u;
}
std::string IRCNetworkPlugin::getTargetName(const std::string &legacyName) {
std::string r = legacyName;
if (legacyName.find("/") == std::string::npos) {
r = legacyName.substr(0, r.find("@"));
}
else {
r = legacyName.substr(legacyName.find("/") + 1);
}
return r;
}
void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/) {
std::string session = getSessionName(user, legacyName);
if (m_sessions[session] == NULL) {
LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user");
return;
}
std::string target = getTargetName(legacyName);
// We are sending PM message. On XMPP side, user is sending PM using the particular channel,
// for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message
// just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should
// be mapped to #room@irc.freenode.org/hanzz.
if (legacyName.find("/") != std::string::npos) {
m_sessions[session]->addPM(target, legacyName.substr(0, legacyName.find("@")));
}
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", message to " << target);
if (message.find("/me") == 0) {
m_sessions[session]->sendCommand(IrcCommand::createCtcpAction(FROM_UTF8(target), FROM_UTF8(message.substr(4))));
}
else if (message.find("/whois") == 0 || message.find(".whois") == 0) {
m_sessions[session]->sendWhoisCommand(target, message.substr(7));
return;
}
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()));
}
}
void IRCNetworkPlugin::handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message) {
std::string session = getSessionName(user, room);
if (m_sessions[session] == NULL) {
LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user");
return;
}
std::string target = getTargetName(room);
m_sessions[session]->sendCommand(IrcCommand::createTopic(FROM_UTF8(target), FROM_UTF8(message)));
}
void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
std::string session = getSessionName(user, room);
std::string target = getTargetName(room);
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Joining room " << target);
bool createdSession = false;
if (m_sessions[session] == NULL) {
if (m_servers.empty()) {
// in gateway mode we want to login this user to network according to legacyName
if (room.find("@") != std::string::npos) {
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
m_sessions[session] = createSession(user, room.substr(room.find("@") + 1), nickname, "", room.substr(room.find("@")));
createdSession = true;
}
else {
LOG4CXX_WARN(logger, user << ": There's no proper server defined in room to which this user wants to join: " << room);
return;
}
}
else {
LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user");
return;
}
}
m_sessions[session]->sendCommand(IrcCommand::createJoin(FROM_UTF8(target), FROM_UTF8(password)));
m_sessions[session]->rooms += 1;
if (createdSession) {
m_sessions[session]->open();
}
// update nickname, because we have nickname per session, no nickname per room.
if (nickname != TO_UTF8(m_sessions[session]->nickName())) {
handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[session]->nickName()));
handleParticipantChanged(user, nickname, room, 0, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m_sessions[session]->nickName()));
}
}
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
std::string session = getSessionName(user, room);
std::string target = getTargetName(room);
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", Leaving room " << target);
if (m_sessions[session] == NULL)
return;
m_sessions[session]->sendCommand(IrcCommand::createPart(FROM_UTF8(target)));
m_sessions[session]->rooms -= 1;
if (m_sessions[session]->rooms <= 0 && m_servers.empty()) {
LOG4CXX_INFO(logger, user << ": Session name: " << session << ", User is not in any room, disconnecting from network");
m_sessions[session]->close();
m_sessions[session]->deleteLater();
m_sessions.erase(session);
}
}
void IRCNetworkPlugin::handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) {
if (m_sessions[user] == NULL) {
return;
}
if (status == pbnetwork::STATUS_AWAY) {
LOG4CXX_INFO(logger, user << ": User is now away.");
m_sessions[user]->sendCommand(IrcCommand::createAway(statusMessage.empty() ? "Away" : FROM_UTF8(statusMessage)));
}
else {
LOG4CXX_INFO(logger, user << ": User is not away anymore.");
m_sessions[user]->sendCommand(IrcCommand::createAway(""));
}
}

View file

@ -1,77 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
#ifndef Q_MOC_RUN
#include "session.h"
#include <QtCore>
#include <QtNetwork>
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
#endif
class IRCNetworkPlugin : public QObject, public NetworkPlugin {
Q_OBJECT
public:
IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port);
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/);
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password);
void handleLeaveRoomRequest(const std::string &user, const std::string &room);
void handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message);
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id);
void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage);
void tryNextServer();
Config *getConfig() {
return m_config;
}
public slots:
void readData();
void sendData(const std::string &string);
private:
MyIrcSession *createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix = "");
std::string getSessionName(const std::string &user, const std::string &legacyName);
std::string getTargetName(const std::string &legacyName);
private:
Config *m_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;
};

View file

@ -1,53 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <QtCore>
#include <QtNetwork>
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "transport/Logging.h"
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
#include "ircnetworkplugin.h"
using namespace boost::program_options;
using namespace Transport;
NetworkPlugin * np = NULL;
int main (int argc, char* argv[]) {
std::string host;
int port;
std::string error;
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
if (cfg == NULL) {
std::cerr << error;
return 1;
}
Logging::initBackendLogging(cfg);
QCoreApplication app(argc, argv);
Swift::QtEventLoop eventLoop;
np = new IRCNetworkPlugin(cfg, &eventLoop, host, port);
return app.exec();
}

View file

@ -1,586 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "session.h"
#include <QtCore>
#include <iostream>
#include <IrcCommand>
#include <IrcMessage>
#include <IrcUser>
#include <IrcChannel>
#include "backports.h"
#include "ircnetworkplugin.h"
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
#include "transport/Logging.h"
DEFINE_LOGGER(logger, "IRCConnection");
MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcConnection(parent)
{
m_np = np;
m_user = user;
m_suffix = suffix;
m_connected = false;
rooms = 0;
m_bufferModel = NULL;
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
connect(this, SIGNAL(socketError(QAbstractSocket::SocketError)), SLOT(on_socketError(QAbstractSocket::SocketError)));
connect(this, SIGNAL(connected()), SLOT(on_connected()));
m_awayTimer = new QTimer(this);
connect(m_awayTimer, SIGNAL(timeout()), this, SLOT(awayTimeout()));
m_awayTimer->start(1 * 1000);
}
MyIrcSession::~MyIrcSession() {
delete m_awayTimer;
}
void MyIrcSession::createBufferModel() {
m_bufferModel = new IrcBufferModel(this);
connect(m_bufferModel, SIGNAL(added(IrcBuffer*)), this, SLOT(onBufferAdded(IrcBuffer*)));
connect(m_bufferModel, SIGNAL(removed(IrcBuffer*)), this, SLOT(onBufferRemoved(IrcBuffer*)));
// keep the command parser aware of the context
// connect(m_bufferModel, SIGNAL(channelsChanged(QStringList)), parser, SLOT(setChannels(QStringList)));
// create a server buffer for non-targeted messages...
IrcBuffer* serverBuffer = m_bufferModel->add(host());
// ...and connect it to IrcBufferModel::messageIgnored()
// TODO: Make this configurable, so users can show the MOTD and other stuff as in normal
// IRC client.
connect(m_bufferModel, SIGNAL(messageIgnored(IrcMessage*)), serverBuffer, SLOT(receiveMessage(IrcMessage*)));
}
void MyIrcSession::onBufferAdded(IrcBuffer* buffer) {
LOG4CXX_INFO(logger, m_user << ": Created IrcBuffer " << TO_UTF8(buffer->name()));
connect(buffer, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*)));
if (buffer->isChannel()) {
QVariantMap userData;
userData["awayCycle"] = boost::lexical_cast<int>(CONFIG_STRING_DEFAULTED(m_np->getConfig(), "service.irc_away_timeout", "60")) + m_userModels.size();
userData["awayTick"] = 0;
buffer->setUserData(userData);
}
// create a model for buffer users
IrcUserModel* userModel = new IrcUserModel(buffer);
connect(userModel, SIGNAL(added(IrcUser*)), this, SLOT(onIrcUserAdded(IrcUser*)));
connect(userModel, SIGNAL(removed(IrcUser*)), this, SLOT(onIrcUserRemoved(IrcUser*)));
m_userModels.insert(buffer, userModel);
}
void MyIrcSession::onBufferRemoved(IrcBuffer* buffer) {
LOG4CXX_INFO(logger, m_user << ": Removed IrcBuffer " << TO_UTF8(buffer->name()));
// the buffer specific models and documents are no longer needed
delete m_userModels.take(buffer);
}
bool MyIrcSession::hasIrcUser(const std::string &channel_, const std::string &name) {
std::string channel = channel_;
if (channel[0] != '#') {
channel = "#" + channel;
}
IrcBuffer *buffer = m_bufferModel->find(FROM_UTF8(channel));
if (!buffer) {
LOG4CXX_ERROR(logger, m_user << ": Cannot find IrcBuffer '" << channel << "'");
return false;
}
IrcUserModel *userModel = m_userModels.value(buffer);
if (!userModel) {
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << channel);
return false;
}
return userModel->contains(FROM_UTF8(name));
}
void MyIrcSession::sendUserToFrontend(IrcUser *user, pbnetwork::StatusType statusType, const std::string &statusMessage, const std::string &newNick) {
std::string target = "#" + TO_UTF8(user->channel()->name().toLower()) + m_suffix;
int op = user->mode() == "o";
if (statusType != pbnetwork::STATUS_NONE) {
if (user->isAway()) {
statusType = pbnetwork::STATUS_AWAY;
}
if (newNick.empty()) {
LOG4CXX_INFO(logger, m_user << ": IrcUser connected: " << target << "/" << TO_UTF8(user->name()));
}
else {
LOG4CXX_INFO(logger, m_user << ": IrcUser changed nickname: " << target << "/" << TO_UTF8(user->name()) << ", newNick=" << newNick);
}
}
else {
LOG4CXX_INFO(logger, m_user << ": IrcUser disconnected: " << target << "/" << TO_UTF8(user->name()));
}
m_np->handleParticipantChanged(m_user, TO_UTF8(user->name()), target, op, statusType, statusMessage, newNick);
}
void MyIrcSession::onIrcUserChanged(bool dummy) {
IrcUser *user = dynamic_cast<IrcUser *>(QObject::sender());
if (!user) {
return;
}
LOG4CXX_INFO(logger, m_user << ": IrcUser " << TO_UTF8(user->name()) << " changed.");
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
}
void MyIrcSession::onIrcUserChanged(const QString &) {
onIrcUserChanged(false);
}
void MyIrcSession::onIrcUserAdded(IrcUser *user) {
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
connect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
connect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
}
void MyIrcSession::onIrcUserRemoved(IrcUser *user) {
sendUserToFrontend(user, pbnetwork::STATUS_NONE);
disconnect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
disconnect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
}
void MyIrcSession::on_connected() {
m_connected = true;
if (m_suffix.empty()) {
m_np->handleConnected(m_user);
}
if (getIdentify().find(" ") != std::string::npos) {
std::string to = getIdentify().substr(0, getIdentify().find(" "));
std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
LOG4CXX_INFO(logger, m_user << ": Sending IDENTIFY message to " << to);
sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
}
}
void MyIrcSession::addPM(const std::string &name, const std::string &room) {
LOG4CXX_INFO(logger, m_user << ": Adding PM conversation " << name << " " << room);
m_pms[name] = room;
}
void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) {
std::string reason;
switch(error) {
case QAbstractSocket::ConnectionRefusedError: reason = "The connection was refused by the peer (or timed out)."; break;
case QAbstractSocket::RemoteHostClosedError: reason = "The remote host closed the connection."; break;
case QAbstractSocket::HostNotFoundError: reason = "The host address was not found."; break;
case QAbstractSocket::SocketAccessError: reason = "The socket operation failed because the application lacked the required privileges."; break;
case QAbstractSocket::SocketResourceError: reason = "The local system ran out of resources."; break;
case QAbstractSocket::SocketTimeoutError: reason = "The socket operation timed out."; break;
case QAbstractSocket::DatagramTooLargeError: reason = "The datagram was larger than the operating system's limit."; break;
case QAbstractSocket::NetworkError: reason = "An error occurred with the network."; break;
case QAbstractSocket::SslHandshakeFailedError: reason = "The SSL/TLS handshake failed, so the connection was closed"; break;
case QAbstractSocket::UnknownSocketError: reason = "An unidentified error occurred."; break;
default: reason= "Unknown error."; break;
};
if (!m_suffix.empty()) {
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
if (!buffer->isChannel()) {
continue;
}
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_ROOM_NOT_FOUND, pbnetwork::STATUS_NONE, reason);
}
}
else {
m_np->handleDisconnected(m_user, 0, reason);
m_np->tryNextServer();
}
LOG4CXX_INFO(logger, m_user << ": Disconnected from IRC network: " << reason);
m_connected = false;
}
void MyIrcSession::on_disconnected() {
if (m_suffix.empty()) {
m_np->handleDisconnected(m_user, 0, "");
m_np->tryNextServer();
}
m_connected = false;
}
void MyIrcSession::correctNickname(std::string &nick) {
if (nick.empty()) {
return;
}
switch(nick.at(0)) {
case '@':
case '+':
case '~':
case '&':
case '%':
nick.erase(0, 1);
break;
default: break;
}
}
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, std::string &nick) {
correctNickname(nick);
IrcUserModel *userModel = m_userModels.value(buffer);
if (!userModel) {
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
return NULL;
}
return userModel->find(FROM_UTF8(nick));
}
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, IrcMessage *message) {
std::string nick = TO_UTF8(message->nick());
return getIrcUser(buffer, nick);
}
void MyIrcSession::on_parted(IrcMessage *message) {
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
// part/quit message. We should use this method instead and write version
// of sendUserToFrontend which takes nickname instead of IrcUser just for
// part/quit messages.
// IrcPartMessage *m = (IrcPartMessage *) message;
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
// IrcUser *user = getIrcUser(buffer, message);
// if (!user) {
// LOG4CXX_ERROR(logger, m_user << ": Part: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
// return;
// }
//
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
void MyIrcSession::on_quit(IrcMessage *message) {
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
// part/quit message. We should use this method instead and write version
// of sendUserToFrontend which takes nickname instead of IrcUser just for
// part/quit messages.
// IrcQuitMessage *m = (IrcQuitMessage *) message;
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
// IrcUser *user = getIrcUser(buffer, message);
// if (!user) {
// LOG4CXX_ERROR(logger, m_user << ": Quit: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
// return;
// }
//
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
void MyIrcSession::on_nickChanged(IrcMessage *message) {
IrcNickMessage *m = (IrcNickMessage *) message;
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
IrcUser *user = getIrcUser(buffer, message);
if (!user) {
LOG4CXX_ERROR(logger, m_user << ": NickChanged: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
return;
}
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->newNick()));
}
void MyIrcSession::on_topicChanged(IrcMessage *message) {
IrcTopicMessage *m = (IrcTopicMessage *) message;
std::string nickname = TO_UTF8(m->nick());
correctNickname(nickname);
LOG4CXX_INFO(logger, m_user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
m_np->handleSubject(m_user, TO_UTF8(m->channel().toLower()) + m_suffix, TO_UTF8(m->topic()), nickname);
}
void MyIrcSession::sendWhoisCommand(const std::string &channel, const std::string &to) {
m_whois[to] = channel;
sendCommand(IrcCommand::createWhois(FROM_UTF8(to)));
}
void MyIrcSession::on_whoisMessageReceived(IrcMessage *message) {
IrcWhoisMessage *m = (IrcWhoisMessage *) message;
std::string nickname = TO_UTF8(m->nick());
if (m_whois.find(nickname) == m_whois.end()) {
LOG4CXX_INFO(logger, "Whois response received with unexpected nickname " << nickname);
return;
}
std::string msg = "";
msg += nickname + " is connected to " + TO_UTF8(m->server()) + " (" + TO_UTF8(m->realName()) + ")\n";
msg += nickname + " is a user on channels: " + TO_UTF8(m->channels().join(", "));
sendMessageToFrontend(m_whois[nickname], "whois", msg);
m_whois.erase(nickname);
}
void MyIrcSession::on_namesMessageReceived(IrcMessage *message) {
LOG4CXX_INFO(logger, m_user << ": NAMES received");
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
IrcUserModel *userModel = m_userModels.value(buffer);
if (!userModel) {
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
return;
}
foreach (IrcUser *user, userModel->users()) {
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
}
LOG4CXX_INFO(logger, m_user << "Asking /who for channel " << TO_UTF8(buffer->name()));
sendCommand(IrcCommand::createWho(buffer->name()));
}
void MyIrcSession::sendMessageToFrontend(const std::string &channel, const std::string &nick, const std::string &msg) {
QString html = "";//msg;
// CommuniBackport::toPlainText(msg);
// TODO: Communi produces invalid html now...
// if (html == msg) {
// html = "";
// }
// else {
// html = IrcUtil::messageToHtml(html);
// }
std::string nickname = nick;
if (channel.find("#") == 0) {
correctNickname(nickname);
m_np->handleMessage(m_user, channel + m_suffix, msg, nickname, TO_UTF8(html));
}
else {
correctNickname(nickname);
if (m_pms.find(nickname) != m_pms.end()) {
std::string room = m_pms[nickname].substr(0, m_pms[nickname].find("/"));
room = room.substr(0, room.find("@"));
if (hasIrcUser(room, nickname)) {
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
return;
}
else {
nickname = nickname + m_suffix;
}
}
else {
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
std::string room = "#" + TO_UTF8(buffer->name());
IrcUserModel *userModel = m_userModels.value(buffer);
if (!userModel) {
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
continue;
}
if (!userModel->contains(FROM_UTF8(nickname))) {
continue;
}
addPM(nickname, room + "/" + nickname);
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
return;
}
nickname = nickname + m_suffix;
}
m_np->handleMessage(m_user, nickname, msg, "", TO_UTF8(html));
}
}
void MyIrcSession::on_messageReceived(IrcMessage *message) {
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
if (m->isRequest()) {
QString request = m->content().split(" ", QString::SkipEmptyParts).value(0).toUpper();
if (request == "PING" || request == "TIME" || request == "VERSION") {
LOG4CXX_INFO(logger, m_user << ": " << TO_UTF8(request) << " received and has been answered");
return;
}
}
std::string msg = TO_UTF8(m->content());
if (m->isAction()) {
msg = "/me " + msg;
}
std::string target = TO_UTF8(m->target().toLower());
std::string nickname = TO_UTF8(m->nick());
sendMessageToFrontend(target, nickname, msg);
}
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
QString channel;
QStringList members;
std::string nick;
IrcNumericMessage *m = (IrcNumericMessage *) message;
QStringList parameters = m->parameters();
switch (m->code()) {
case Irc::RPL_TOPIC:
m_topicData = TO_UTF8(parameters[2]);
break;
case Irc::RPL_TOPICWHOTIME:
nick = TO_UTF8(parameters[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("/"));
}
m_np->handleSubject(m_user, TO_UTF8(parameters[1].toLower()) + m_suffix, m_topicData, nick);
break;
case Irc::ERR_NOSUCHNICK:
case Irc::ERR_NOSUCHSERVER:
nick = TO_UTF8(parameters[1]);
if (m_whois.find(nick) != m_whois.end()) {
sendMessageToFrontend(m_whois[nick], "whois", nick + ": No such client");
m_whois.erase(nick);
}
break;
case Irc::ERR_ERRONEUSNICKNAME:
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
break;
case Irc::ERR_NICKNAMEINUSE:
case Irc::ERR_NICKCOLLISION:
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
if (!buffer->isChannel()) {
continue;
}
m_np->handleRoomNicknameChanged(m_user, TO_UTF8(buffer->title()) + m_suffix, TO_UTF8(nickName() + "_"));
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, 0, pbnetwork::STATUS_ONLINE, "", TO_UTF8(nickName() + "_"));
}
setNickName(nickName() + "_");
open();
// for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), it->second->getChannel() + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
// }
// if (m_suffix.empty()) {
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname is already in use");
// }
break;
// foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
// if (!buffer->isChannel()) {
// continue;
// }
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
// }
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname collision KILL");
// break;
case Irc::ERR_PASSWDMISMATCH:
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
if (!buffer->isChannel()) {
continue;
}
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_NOT_AUTHORIZED);
}
if (m_suffix.empty()) {
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Password incorrect");
}
case 321:
m_rooms.clear();
m_names.clear();
break;
case 322:
m_rooms.push_back(TO_UTF8(parameters[1]));
m_names.push_back(TO_UTF8(parameters[1]));
break;
case 323:
m_np->handleRoomList("", m_rooms, m_names);
break;
default:
break;
}
if (m->code() >= 400 && m->code() < 500) {
LOG4CXX_INFO(logger, m_user << ": Error message received: " << message->toData().data());
}
else {
LOG4CXX_INFO(logger, m_user << ": Numeric message received: " << message->toData().data());
}
}
void MyIrcSession::awayTimeout() {
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
if (!buffer->isChannel()) {
continue;
}
QVariantMap userData = buffer->userData();
int awayCycle = userData["awayCycle"].toInt();
int awayTick = userData["awayTick"].toInt();
if (awayTick == awayCycle) {
LOG4CXX_INFO(logger, m_user << ": The time has come. Asking /who " << TO_UTF8(buffer->title()) << " again to get current away states.");
sendCommand(IrcCommand::createWho(buffer->title()));
awayTick = 0;
}
awayTick++;
userData["awayCycle"] = awayCycle;
userData["awayTick"] = awayTick;
buffer->setUserData(userData);
}
}
void MyIrcSession::on_noticeMessageReceived(IrcMessage *message) {
IrcNoticeMessage *m = (IrcNoticeMessage *) message;
LOG4CXX_INFO(logger, m_user << ": NOTICE " << TO_UTF8(m->content()));
std::string msg = TO_UTF8(m->content());
std::string target = TO_UTF8(m->target().toLower());
std::string nickname = TO_UTF8(m->nick());
sendMessageToFrontend(target, nickname, msg);
}
void MyIrcSession::onMessageReceived(IrcMessage *message) {
switch (message->type()) {
case IrcMessage::Part:
on_parted(message);
break;
case IrcMessage::Quit:
on_quit(message);
break;
case IrcMessage::Nick:
on_nickChanged(message);
break;
case IrcMessage::Topic:
on_topicChanged(message);
break;
case IrcMessage::Private:
on_messageReceived(message);
break;
case IrcMessage::Numeric:
on_numericMessageReceived(message);
break;
case IrcMessage::Notice:
on_noticeMessageReceived(message);
break;
case IrcMessage::Whois:
on_whoisMessageReceived(message);
break;
case IrcMessage::Names:
on_namesMessageReceived(message);
break;
default:break;
}
}

View file

@ -1,119 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef SESSION_H
#define SESSION_H
#ifndef Q_MOC_RUN
#include <IrcConnection>
#include <IrcBufferModel>
#include <IrcBuffer>
#include <IrcUserModel>
#include <transport/NetworkPlugin.h>
#include "Swiften/Swiften.h"
#include <boost/smart_ptr/make_shared.hpp>
#include <QTimer>
#endif
using namespace Transport;
class IRCNetworkPlugin;
class MyIrcSession : public IrcConnection
{
Q_OBJECT
public:
MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
virtual ~MyIrcSession();
void createBufferModel();
// We are sending PM message. On XMPP side, user is sending PM using the particular channel,
// for example #room@irc.freenode.org/hanzz. On IRC side, we are forwarding this message
// just to "hanzz". Therefore we have to somewhere store, that message from "hanzz" should
// be mapped to #room@irc.freenode.org/hanzz.
void addPM(const std::string &name, const std::string &room);
void setIdentify(const std::string &identify) {
m_identify = identify;
}
const std::string &getIdentify() {
return m_identify;
}
bool hasIrcUser(const std::string &channel, const std::string &name);
void correctNickname(std::string &nick);
IrcUser *getIrcUser(IrcBuffer *buffer, IrcMessage *message);
IrcUser *getIrcUser(IrcBuffer *buffer, std::string &nick);
void sendWhoisCommand(const std::string &channel, const std::string &to);
void sendMessageToFrontend(const std::string &channel, const std::string &nickname, const std::string &msg);
void sendUserToFrontend(IrcUser *user, pbnetwork::StatusType statusType, const std::string &statusMessage = "", const std::string &newNick = "");
void on_joined(IrcMessage *message);
void on_parted(IrcMessage *message);
void on_quit(IrcMessage *message);
void on_nickChanged(IrcMessage *message);
void on_topicChanged(IrcMessage *message);
void on_messageReceived(IrcMessage *message);
void on_numericMessageReceived(IrcMessage *message);
void on_noticeMessageReceived(IrcMessage *message);
void on_whoisMessageReceived(IrcMessage *message);
void on_namesMessageReceived(IrcMessage *message);
int rooms;
protected Q_SLOTS:
void on_connected();
void on_disconnected();
void on_socketError(QAbstractSocket::SocketError error);
void onBufferAdded(IrcBuffer* buffer);
void onBufferRemoved(IrcBuffer* buffer);
void onIrcUserAdded(IrcUser *user);
void onIrcUserChanged(const QString &);
void onIrcUserChanged(bool);
void onIrcUserRemoved(IrcUser *user);
void onMessageReceived(IrcMessage* message);
void awayTimeout();
protected:
IRCNetworkPlugin *m_np;
IrcBufferModel *m_bufferModel;
std::string m_user;
std::string m_identify;
std::string m_topicData;
bool m_connected;
std::list<std::string> m_rooms;
std::list<std::string> m_names;
std::map<std::string, std::string> m_pms;
QTimer *m_awayTimer;
std::string m_suffix;
std::map<std::string, std::string> m_whois;
QHash<IrcBuffer*, IrcUserModel*> m_userModels;
};
#endif // SESSION_H

View file

@ -1,17 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp)
ADD_EXECUTABLE(spectrum2_libpurple_backend ${SRC})
if(MSVC)
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${LIBXML2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin ${PROTOBUF_LIBRARY})
else()
if (NOT WIN32)
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin pthread)
else()
target_link_libraries(spectrum2_libpurple_backend transport ${PURPLE_LIBRARY} ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport-plugin)
endif()
endif()
INSTALL(TARGETS spectrum2_libpurple_backend RUNTIME DESTINATION bin)

View file

@ -1,251 +0,0 @@
import sys
import os
# intialize for methods used in libpurple macros
methods = ["purple_connection_get_state(", "purple_conversation_get_im_data(",
"purple_conversation_get_chat_data(", "purple_blist_node_get_type("]
macros = ["PURPLE_CONV_IM", "PURPLE_CONV_CHAT", "PURPLE_BLIST_NODE_IS_BUDDY", "PURPLE_CONNECTION_IS_CONNECTED"]
definitions = []
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "<path_to_libpurple_dir_containing_libpurple_headers>"
sys.exit(1)
def handle_file(cpp):
global methods
global macros
sys.stdout.write("getting used methods in " + cpp + ": ")
sys.stdout.flush()
counter = 0
new_file = ""
f = open(cpp, "r")
for line in f.readlines():
new_line = ""
index = 0
while index < len(line):
new_line += line[index]
if line[index:].startswith("purple_") or line[index:].startswith("wpurple_") or line[index:].startswith("serv_"):
if line[index:].find("=") != -1 and line[index:].find("=") < line[index:].find("("):
index += 1
continue
if line[index-1] == "_" or line[index:].find("(") == -1 or line[index:].startswith("purple_commands_init") or line[index:].startswith("serv_addr"):
index += 1
continue
m = line[index:line[index:].find("(")+index]
index += len(m)
if m.find("_wrapped") != -1:
new_line += m[1:] + "("
m = m.replace("_wrapped", "")
else:
new_line += m[1:] + "_wrapped("
if not m + "(" in methods and len(m) != 0:
methods += [m + "("]
counter += 1
index += 1
for x in macros:
if new_line.find(x + "_WRAPPED") == -1:
new_line = new_line.replace(x, x + "_WRAPPED")
new_file += new_line
f.close()
print counter, "new methods found"
return new_file
def handle_header(header, method):
global definitions
f = open(os.path.join(sys.argv[1], header), "r")
lines = f.readlines()
for i in range(len(lines)):
line = lines[i]
if line.find(method) != -1:
if line.startswith(method):
line = lines[i-1][:-1] + line
m = line[:-1]
l = unicode(m).strip()
if l.endswith(")"):
continue
if m.find("/*") > m.find(";"):
m = m[:m.find("/*")]
m.rstrip()
if len(m) != 0:
while m[-1] == " ":
m = m[:-1]
index = i;
while not m.endswith(";"):
index += 1
m += " " + lines[index][:-1].lstrip()
l = unicode(m).strip()
if (l.startswith("#") or l.startswith("*") or l.startswith("/*") or l.count("***") != 0 or l.count("&&") != 0
or l.endswith(")")):
continue;
m = m.replace("G_GNUC_NULL_TERMINATE", "")
if not m in definitions:
print "found", method[:-1], "in", header
definitions += [m]
break
f.close()
def get_raw_args(d):
return d[d.find("(")+1:-2]
def get_args(d):
x = d[d.find("(")+1:-2]
x = x.split(",")
args = []
for arg in x:
y = arg.split(" ")
if len(y) == 1:
continue
args += [y[-1].replace("*", "")]
return args
def get_name(d):
x = d[:d.find("(")+1].lstrip()
if x.find("wpurple_") != -1:
return x[x.find("wpurple_"):]
if x.find("serv_") != -1:
return x[x.find("serv_"):]
return x[x.find("purple_"):]
def get_rtype(d):
if d.find("wpurple_") != -1:
return d[:d.find("wpurple_")].lstrip()
if d.find("serv_") != -1:
return d[:d.find("serv_")].lstrip()
return d[:d.find("purple_")].lstrip()
def output():
global definitions
header = open("purple_defs.h", "w")
print >> header, "#pragma once"
print >> header, "#if PURPLE_RUNTIME"
print >> header, """
#include <Windows.h>
#include <purple.h>
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE)
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE)
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE)
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE)
#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c))
#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c))
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) \
(purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED)
"""
for d in definitions:
#typedef void (_cdecl * purple_util_set_user_wrapped_func)(const char *dir);
print >> header, "typedef", get_rtype(d), "(_cdecl *", get_name(d)[:-1] + "_wrapped_fnc)(" + get_raw_args(d) + ");"
#extern purple_util_set_user_wrapped_func purple_util_set_user_wrapped;
print >> header, "extern", get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped;"
print >> header, ""
print >> header, ""
print >> header, "#else"
print >> header, ""
print >> header, """
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP
#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM
#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED
"""
for d in definitions:
#define purple_util_set_user_wrapped purple_util_set_user
print >> header, "#define", get_name(d)[:-1] + "_wrapped", get_name(d)[:-1]
print >> header, "#endif"
print >> header, ""
print >> header, "bool resolvePurpleFunctions();"
print >> header, ""
cpp = open("purple_defs.cpp", "w")
print >> cpp, "#include \"purple_defs.h\""
print >> cpp, ""
print >> cpp, "#if PURPLE_RUNTIME"
print >> cpp, "static HMODULE f_hPurple = NULL;"
for d in definitions:
#purple_util_set_user_wrapped_fnc purple_util_set_user_wrapped = NULL;
print >> cpp, get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped = NULL;"
print >> cpp, "#endif"
print >> cpp, "bool resolvePurpleFunctions() {"
print >> cpp, "#if PURPLE_RUNTIME"
print >> cpp, "\tf_hPurple = LoadLibrary(L\"libpurple.dll\");"
print >> cpp, "\tif (!f_hPurple)"
print >> cpp, "\t\t\treturn false;"
for d in definitions:
#purple_util_set_user_wrapped = (purple_util_set_user_wrapped_func)GetProcAddress(f_hPurple, "purple_util_set_user_dir");
print >> cpp, "\t" + get_name(d)[:-1] + "_wrapped = (" + get_name(d)[:-1] + "_wrapped_fnc)GetProcAddress(f_hPurple, \"" + get_name(d)[:-1] + "\");"
#if (!purple_util_set_user_wrapped)
print >> cpp, "\tif (!" + get_name(d)[:-1] + "_wrapped)"
print >> cpp, "\t\treturn false;"
print >> cpp, ""
print >> cpp, "#endif"
print >> cpp, "\treturn true;"
print >> cpp, "}"
print >> cpp, ""
cpp.close()
header.close()
for f in os.listdir("."):
if not f.endswith(".cpp") or f.startswith("purple_defs"):
continue
new_file = handle_file(f)
print "updating", f
fd = open(f, "w")
fd.write(new_file)
fd.close()
for f in os.listdir(sys.argv[1]):
if not f.endswith(".h"):
continue
for m in methods:
handle_header(f, m)
sys.argv[1] = sys.argv[1] + "/win32"
for f in os.listdir(sys.argv[1]):
if not f.endswith(".h"):
continue
for m in methods:
handle_header(f, m)
for m in methods:
found = False
for d in definitions:
if d.find(m[:-1]) != -1:
found = True
break
if not found:
print "NOT FOUND:", m
output()

View file

@ -1,265 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "geventloop.h"
#ifdef _WIN32
#include "win32/win32dep.h"
#undef read
#undef write
#endif
#ifdef WITH_LIBEVENT
#include "event.h"
#endif
#include "purple_defs.h"
#include "transport/Logging.h"
DEFINE_LOGGER(logger, "EventLoop");
typedef struct _PurpleIOClosure {
PurpleInputFunction function;
guint result;
gpointer data;
#ifdef WITH_LIBEVENT
GSourceFunc function2;
struct timeval timeout;
struct event evfifo;
#endif
} PurpleIOClosure;
static gboolean io_invoke(GIOChannel *source,
GIOCondition condition,
gpointer data)
{
PurpleIOClosure *closure = (PurpleIOClosure* )data;
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
int tmp = 0;
if (condition & READ_COND)
{
tmp |= PURPLE_INPUT_READ;
purple_cond = (PurpleInputCondition)tmp;
}
if (condition & WRITE_COND)
{
tmp |= PURPLE_INPUT_WRITE;
purple_cond = (PurpleInputCondition)tmp;
}
closure->function(closure->data, g_io_channel_unix_get_fd(source), purple_cond);
return TRUE;
}
static void io_destroy(gpointer data)
{
g_free(data);
}
static guint input_add(gint fd,
PurpleInputCondition condition,
PurpleInputFunction function,
gpointer data)
{
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
GIOChannel *channel;
GIOCondition cond = (GIOCondition)0;
closure->function = function;
closure->data = data;
int tmp = 0;
if (condition & PURPLE_INPUT_READ)
{
tmp |= READ_COND;
cond = (GIOCondition)tmp;
}
if (condition & PURPLE_INPUT_WRITE)
{
tmp |= WRITE_COND;
cond = (GIOCondition)tmp;
}
#ifdef WIN32
channel = wpurple_g_io_channel_win32_new_socket_wrapped(fd);
#else
channel = g_io_channel_unix_new(fd);
#endif
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
io_invoke, closure, io_destroy);
g_io_channel_unref(channel);
return closure->result;
}
static PurpleEventLoopUiOps eventLoopOps =
{
g_timeout_add,
g_source_remove,
input_add,
g_source_remove,
NULL,
#if GLIB_CHECK_VERSION(2,14,0)
g_timeout_add_seconds,
#else
NULL,
#endif
NULL,
NULL,
NULL
};
#ifdef WITH_LIBEVENT
static GHashTable *events = NULL;
static unsigned long id = 0;
static void event_io_destroy(gpointer data)
{
PurpleIOClosure *closure = (PurpleIOClosure* )data;
event_del(&closure->evfifo);
g_free(data);
}
static void event_io_invoke(int fd, short event, void *data)
{
PurpleIOClosure *closure = (PurpleIOClosure* )data;
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
int tmp = 0;
if (event & EV_READ)
{
tmp |= PURPLE_INPUT_READ;
purple_cond = (PurpleInputCondition)tmp;
}
if (event & EV_WRITE)
{
tmp |= PURPLE_INPUT_WRITE;
purple_cond = (PurpleInputCondition)tmp;
}
if (event & EV_TIMEOUT)
{
// tmp |= PURPLE_INPUT_WRITE;
// purple_cond = (PurpleInputCondition)tmp;
LOG4CXX_INFO(logger, "before timer callback " << closure->function2);
if (closure->function2(closure->data))
evtimer_add(&closure->evfifo, &closure->timeout);
LOG4CXX_INFO(logger, "after timer callback" << closure->function2);
// else
// event_io_destroy(data);
return;
}
LOG4CXX_INFO(logger, "before callback " << closure->function);
closure->function(closure->data, fd, purple_cond);
LOG4CXX_INFO(logger, "after callback" << closure->function);
}
static gboolean event_input_remove(guint handle)
{
PurpleIOClosure *closure = (PurpleIOClosure *) g_hash_table_lookup(events, &handle);
if (closure)
event_io_destroy(closure);
return TRUE;
}
static guint event_input_add(gint fd,
PurpleInputCondition condition,
PurpleInputFunction function,
gpointer data)
{
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
GIOChannel *channel;
GIOCondition cond = (GIOCondition)0;
closure->function = function;
closure->data = data;
int tmp = EV_PERSIST;
if (condition & PURPLE_INPUT_READ)
{
tmp |= EV_READ;
}
if (condition & PURPLE_INPUT_WRITE)
{
tmp |= EV_WRITE;
}
event_set(&closure->evfifo, fd, tmp, event_io_invoke, closure);
event_add(&closure->evfifo, NULL);
int *f = (int *) g_malloc(sizeof(int));
*f = id;
id++;
g_hash_table_replace(events, f, closure);
return *f;
}
static guint event_timeout_add (guint interval, GSourceFunc function, gpointer data) {
struct timeval timeout;
PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
closure->function2 = function;
closure->data = data;
timeout.tv_sec = interval/1000;
timeout.tv_usec = (interval%1000)*1000;
evtimer_set(&closure->evfifo, event_io_invoke, closure);
evtimer_add(&closure->evfifo, &timeout);
closure->timeout = timeout;
guint *f = (guint *) g_malloc(sizeof(guint));
*f = id;
id++;
g_hash_table_replace(events, f, closure);
return *f;
}
static PurpleEventLoopUiOps libEventLoopOps =
{
event_timeout_add,
event_input_remove,
event_input_add,
event_input_remove,
NULL,
// #if GLIB_CHECK_VERSION(2,14,0)
// g_timeout_add_seconds,
// #else
NULL,
// #endif
NULL,
NULL,
NULL
};
#endif /* WITH_LIBEVENT*/
PurpleEventLoopUiOps * getEventLoopUiOps(bool libev){
#ifdef WITH_LIBEVENT
if (libev) {
event_init();
events = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
return &libEventLoopOps;
}
else {
return &eventLoopOps;
}
#endif
return &eventLoopOps;
}

View file

@ -1,33 +0,0 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef _HI_EVENTLOOP_H
#define _HI_EVENTLOOP_H
#include <glib.h>
#include "purple.h"
#include "eventloop.h"
#define READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
#define WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
PurpleEventLoopUiOps * getEventLoopUiOps(bool libev);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,739 +0,0 @@
#include "purple_defs.h"
#if PURPLE_RUNTIME
static HMODULE f_hPurple = NULL;
purple_account_set_bool_wrapped_fnc purple_account_set_bool_wrapped = NULL;
purple_account_get_protocol_id_wrapped_fnc purple_account_get_protocol_id_wrapped = NULL;
purple_account_set_int_wrapped_fnc purple_account_set_int_wrapped = NULL;
purple_account_set_string_wrapped_fnc purple_account_set_string_wrapped = NULL;
purple_account_get_username_wrapped_fnc purple_account_get_username_wrapped = NULL;
purple_account_set_username_wrapped_fnc purple_account_set_username_wrapped = NULL;
purple_account_set_proxy_info_wrapped_fnc purple_account_set_proxy_info_wrapped = NULL;
purple_accounts_find_wrapped_fnc purple_accounts_find_wrapped = NULL;
purple_account_new_wrapped_fnc purple_account_new_wrapped = NULL;
purple_accounts_add_wrapped_fnc purple_accounts_add_wrapped = NULL;
purple_account_get_password_wrapped_fnc purple_account_get_password_wrapped = NULL;
purple_account_set_password_wrapped_fnc purple_account_set_password_wrapped = NULL;
purple_account_set_enabled_wrapped_fnc purple_account_set_enabled_wrapped = NULL;
purple_account_set_privacy_type_wrapped_fnc purple_account_set_privacy_type_wrapped = NULL;
purple_account_get_status_type_with_primitive_wrapped_fnc purple_account_get_status_type_with_primitive_wrapped = NULL;
purple_account_set_status_wrapped_fnc purple_account_set_status_wrapped = NULL;
purple_account_get_int_wrapped_fnc purple_account_get_int_wrapped = NULL;
purple_account_disconnect_wrapped_fnc purple_account_disconnect_wrapped = NULL;
purple_accounts_delete_wrapped_fnc purple_accounts_delete_wrapped = NULL;
purple_account_get_connection_wrapped_fnc purple_account_get_connection_wrapped = NULL;
purple_account_set_alias_wrapped_fnc purple_account_set_alias_wrapped = NULL;
purple_account_set_public_alias_wrapped_fnc purple_account_set_public_alias_wrapped = NULL;
purple_account_remove_buddy_wrapped_fnc purple_account_remove_buddy_wrapped = NULL;
purple_account_add_buddy_wrapped_fnc purple_account_add_buddy_wrapped = NULL;
purple_account_get_name_for_display_wrapped_fnc purple_account_get_name_for_display_wrapped = NULL;
purple_accounts_set_ui_ops_wrapped_fnc purple_accounts_set_ui_ops_wrapped = NULL;
purple_account_option_get_type_wrapped_fnc purple_account_option_get_type_wrapped = NULL;
purple_account_option_get_setting_wrapped_fnc purple_account_option_get_setting_wrapped = NULL;
purple_blist_node_get_type_wrapped_fnc purple_blist_node_get_type_wrapped = NULL;
purple_buddy_get_alias_wrapped_fnc purple_buddy_get_alias_wrapped = NULL;
purple_buddy_get_server_alias_wrapped_fnc purple_buddy_get_server_alias_wrapped = NULL;
purple_find_buddy_wrapped_fnc purple_find_buddy_wrapped = NULL;
purple_buddy_get_group_wrapped_fnc purple_buddy_get_group_wrapped = NULL;
purple_blist_remove_buddy_wrapped_fnc purple_blist_remove_buddy_wrapped = NULL;
purple_blist_alias_buddy_wrapped_fnc purple_blist_alias_buddy_wrapped = NULL;
purple_blist_server_alias_buddy_wrapped_fnc purple_blist_server_alias_buddy_wrapped = NULL;
purple_find_group_wrapped_fnc purple_find_group_wrapped = NULL;
purple_group_new_wrapped_fnc purple_group_new_wrapped = NULL;
purple_blist_add_contact_wrapped_fnc purple_blist_add_contact_wrapped = NULL;
purple_buddy_get_contact_wrapped_fnc purple_buddy_get_contact_wrapped = NULL;
purple_buddy_new_wrapped_fnc purple_buddy_new_wrapped = NULL;
purple_blist_add_buddy_wrapped_fnc purple_blist_add_buddy_wrapped = NULL;
purple_blist_find_chat_wrapped_fnc purple_blist_find_chat_wrapped = NULL;
purple_chat_get_components_wrapped_fnc purple_chat_get_components_wrapped = NULL;
purple_buddy_get_presence_wrapped_fnc purple_buddy_get_presence_wrapped = NULL;
purple_buddy_get_account_wrapped_fnc purple_buddy_get_account_wrapped = NULL;
purple_buddy_get_name_wrapped_fnc purple_buddy_get_name_wrapped = NULL;
purple_find_buddies_wrapped_fnc purple_find_buddies_wrapped = NULL;
purple_group_get_name_wrapped_fnc purple_group_get_name_wrapped = NULL;
purple_blist_set_ui_ops_wrapped_fnc purple_blist_set_ui_ops_wrapped = NULL;
purple_set_blist_wrapped_fnc purple_set_blist_wrapped = NULL;
purple_blist_new_wrapped_fnc purple_blist_new_wrapped = NULL;
purple_blist_load_wrapped_fnc purple_blist_load_wrapped = NULL;
purple_blist_get_handle_wrapped_fnc purple_blist_get_handle_wrapped = NULL;
purple_buddy_icons_set_account_icon_wrapped_fnc purple_buddy_icons_set_account_icon_wrapped = NULL;
purple_buddy_icons_find_wrapped_fnc purple_buddy_icons_find_wrapped = NULL;
purple_buddy_icon_get_full_path_wrapped_fnc purple_buddy_icon_get_full_path_wrapped = NULL;
purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped = NULL;
purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped = NULL;
purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped = NULL;
purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped = NULL;
purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped = NULL;
purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped = NULL;
purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped = NULL;
purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped = NULL;
purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped = NULL;
purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped = NULL;
purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped = NULL;
purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped = NULL;
purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped = NULL;
purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped = NULL;
purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped = NULL;
purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped = NULL;
purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped = NULL;
purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped = NULL;
purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped = NULL;
purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped = NULL;
purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped = NULL;
purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped = NULL;
purple_core_init_wrapped_fnc purple_core_init_wrapped = NULL;
purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped = NULL;
purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped = NULL;
purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped = NULL;
purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped = NULL;
purple_input_add_wrapped_fnc purple_input_add_wrapped = NULL;
purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped = NULL;
purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped = NULL;
purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped = NULL;
purple_input_remove_wrapped_fnc purple_input_remove_wrapped = NULL;
purple_xfer_ui_ready_wrapped_fnc purple_xfer_ui_ready_wrapped = NULL;
purple_xfer_request_accepted_wrapped_fnc purple_xfer_request_accepted_wrapped = NULL;
purple_xfer_request_denied_wrapped_fnc purple_xfer_request_denied_wrapped = NULL;
purple_xfer_get_account_wrapped_fnc purple_xfer_get_account_wrapped = NULL;
purple_xfer_get_filename_wrapped_fnc purple_xfer_get_filename_wrapped = NULL;
purple_xfer_get_size_wrapped_fnc purple_xfer_get_size_wrapped = NULL;
purple_xfer_unref_wrapped_fnc purple_xfer_unref_wrapped = NULL;
purple_xfer_ref_wrapped_fnc purple_xfer_ref_wrapped = NULL;
purple_xfers_set_ui_ops_wrapped_fnc purple_xfers_set_ui_ops_wrapped = NULL;
purple_xfers_get_handle_wrapped_fnc purple_xfers_get_handle_wrapped = NULL;
purple_roomlist_set_ui_ops_wrapped_fnc purple_roomlist_set_ui_ops_wrapped = NULL;
purple_roomlist_get_list_wrapped_fnc purple_roomlist_get_list_wrapped = NULL;
purple_imgstore_get_data_wrapped_fnc purple_imgstore_get_data_wrapped = NULL;
purple_imgstore_get_size_wrapped_fnc purple_imgstore_get_size_wrapped = NULL;
purple_imgstore_unref_wrapped_fnc purple_imgstore_unref_wrapped = NULL;
purple_notify_user_info_new_wrapped_fnc purple_notify_user_info_new_wrapped = NULL;
purple_notify_user_info_destroy_wrapped_fnc purple_notify_user_info_destroy_wrapped = NULL;
purple_notify_user_info_get_entries_wrapped_fnc purple_notify_user_info_get_entries_wrapped = NULL;
purple_notify_user_info_entry_get_label_wrapped_fnc purple_notify_user_info_entry_get_label_wrapped = NULL;
purple_notify_user_info_entry_get_value_wrapped_fnc purple_notify_user_info_entry_get_value_wrapped = NULL;
purple_notify_set_ui_ops_wrapped_fnc purple_notify_set_ui_ops_wrapped = NULL;
purple_plugins_add_search_path_wrapped_fnc purple_plugins_add_search_path_wrapped = NULL;
purple_plugin_action_free_wrapped_fnc purple_plugin_action_free_wrapped = NULL;
purple_prefs_load_wrapped_fnc purple_prefs_load_wrapped = NULL;
purple_prefs_set_bool_wrapped_fnc purple_prefs_set_bool_wrapped = NULL;
purple_prefs_set_string_wrapped_fnc purple_prefs_set_string_wrapped = NULL;
purple_privacy_deny_wrapped_fnc purple_privacy_deny_wrapped = NULL;
purple_privacy_allow_wrapped_fnc purple_privacy_allow_wrapped = NULL;
purple_privacy_check_wrapped_fnc purple_privacy_check_wrapped = NULL;
purple_proxy_info_new_wrapped_fnc purple_proxy_info_new_wrapped = NULL;
purple_proxy_info_set_type_wrapped_fnc purple_proxy_info_set_type_wrapped = NULL;
purple_proxy_info_set_host_wrapped_fnc purple_proxy_info_set_host_wrapped = NULL;
purple_proxy_info_set_port_wrapped_fnc purple_proxy_info_set_port_wrapped = NULL;
purple_proxy_info_set_username_wrapped_fnc purple_proxy_info_set_username_wrapped = NULL;
purple_proxy_info_set_password_wrapped_fnc purple_proxy_info_set_password_wrapped = NULL;
purple_find_prpl_wrapped_fnc purple_find_prpl_wrapped = NULL;
purple_prpl_send_attention_wrapped_fnc purple_prpl_send_attention_wrapped = NULL;
purple_request_set_ui_ops_wrapped_fnc purple_request_set_ui_ops_wrapped = NULL;
serv_get_info_wrapped_fnc serv_get_info_wrapped = NULL;
serv_alias_buddy_wrapped_fnc serv_alias_buddy_wrapped = NULL;
serv_send_typing_wrapped_fnc serv_send_typing_wrapped = NULL;
serv_join_chat_wrapped_fnc serv_join_chat_wrapped = NULL;
purple_signal_connect_wrapped_fnc purple_signal_connect_wrapped = NULL;
purple_status_type_get_id_wrapped_fnc purple_status_type_get_id_wrapped = NULL;
purple_presence_get_active_status_wrapped_fnc purple_presence_get_active_status_wrapped = NULL;
purple_status_type_get_primitive_wrapped_fnc purple_status_type_get_primitive_wrapped = NULL;
purple_status_get_type_wrapped_fnc purple_status_get_type_wrapped = NULL;
purple_status_get_attr_string_wrapped_fnc purple_status_get_attr_string_wrapped = NULL;
purple_markup_escape_text_wrapped_fnc purple_markup_escape_text_wrapped = NULL;
purple_markup_strip_html_wrapped_fnc purple_markup_strip_html_wrapped = NULL;
purple_strdup_withhtml_wrapped_fnc purple_strdup_withhtml_wrapped = NULL;
purple_markup_html_to_xhtml_wrapped_fnc purple_markup_html_to_xhtml_wrapped = NULL;
purple_normalize_wrapped_fnc purple_normalize_wrapped = NULL;
purple_utf8_try_convert_wrapped_fnc purple_utf8_try_convert_wrapped = NULL;
purple_util_set_user_dir_wrapped_fnc purple_util_set_user_dir_wrapped = NULL;
wpurple_g_io_channel_win32_new_socket_wrapped_fnc wpurple_g_io_channel_win32_new_socket_wrapped = NULL;
#endif
bool resolvePurpleFunctions() {
#if PURPLE_RUNTIME
f_hPurple = LoadLibrary(L"libpurple.dll");
if (!f_hPurple)
return false;
purple_account_set_bool_wrapped = (purple_account_set_bool_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_bool");
if (!purple_account_set_bool_wrapped)
return false;
purple_account_get_protocol_id_wrapped = (purple_account_get_protocol_id_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_protocol_id");
if (!purple_account_get_protocol_id_wrapped)
return false;
purple_account_set_int_wrapped = (purple_account_set_int_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_int");
if (!purple_account_set_int_wrapped)
return false;
purple_account_set_string_wrapped = (purple_account_set_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_string");
if (!purple_account_set_string_wrapped)
return false;
purple_account_get_username_wrapped = (purple_account_get_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_username");
if (!purple_account_get_username_wrapped)
return false;
purple_account_set_username_wrapped = (purple_account_set_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_username");
if (!purple_account_set_username_wrapped)
return false;
purple_account_set_proxy_info_wrapped = (purple_account_set_proxy_info_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_proxy_info");
if (!purple_account_set_proxy_info_wrapped)
return false;
purple_accounts_find_wrapped = (purple_accounts_find_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_find");
if (!purple_accounts_find_wrapped)
return false;
purple_account_new_wrapped = (purple_account_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_new");
if (!purple_account_new_wrapped)
return false;
purple_accounts_add_wrapped = (purple_accounts_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_add");
if (!purple_accounts_add_wrapped)
return false;
purple_account_get_password_wrapped = (purple_account_get_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_password");
if (!purple_account_get_password_wrapped)
return false;
purple_account_set_password_wrapped = (purple_account_set_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_password");
if (!purple_account_set_password_wrapped)
return false;
purple_account_set_enabled_wrapped = (purple_account_set_enabled_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_enabled");
if (!purple_account_set_enabled_wrapped)
return false;
purple_account_set_privacy_type_wrapped = (purple_account_set_privacy_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_privacy_type");
if (!purple_account_set_privacy_type_wrapped)
return false;
purple_account_get_status_type_with_primitive_wrapped = (purple_account_get_status_type_with_primitive_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_status_type_with_primitive");
if (!purple_account_get_status_type_with_primitive_wrapped)
return false;
purple_account_set_status_wrapped = (purple_account_set_status_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_status");
if (!purple_account_set_status_wrapped)
return false;
purple_account_get_int_wrapped = (purple_account_get_int_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_int");
if (!purple_account_get_int_wrapped)
return false;
purple_account_disconnect_wrapped = (purple_account_disconnect_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_disconnect");
if (!purple_account_disconnect_wrapped)
return false;
purple_accounts_delete_wrapped = (purple_accounts_delete_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_delete");
if (!purple_accounts_delete_wrapped)
return false;
purple_account_get_connection_wrapped = (purple_account_get_connection_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_connection");
if (!purple_account_get_connection_wrapped)
return false;
purple_account_set_alias_wrapped = (purple_account_set_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_alias");
if (!purple_account_set_alias_wrapped)
return false;
purple_account_set_public_alias_wrapped = (purple_account_set_public_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_set_public_alias");
if (!purple_account_set_public_alias_wrapped)
return false;
purple_account_remove_buddy_wrapped = (purple_account_remove_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_remove_buddy");
if (!purple_account_remove_buddy_wrapped)
return false;
purple_account_add_buddy_wrapped = (purple_account_add_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_add_buddy");
if (!purple_account_add_buddy_wrapped)
return false;
purple_account_get_name_for_display_wrapped = (purple_account_get_name_for_display_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_get_name_for_display");
if (!purple_account_get_name_for_display_wrapped)
return false;
purple_accounts_set_ui_ops_wrapped = (purple_accounts_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_accounts_set_ui_ops");
if (!purple_accounts_set_ui_ops_wrapped)
return false;
purple_account_option_get_type_wrapped = (purple_account_option_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_option_get_type");
if (!purple_account_option_get_type_wrapped)
return false;
purple_account_option_get_setting_wrapped = (purple_account_option_get_setting_wrapped_fnc)GetProcAddress(f_hPurple, "purple_account_option_get_setting");
if (!purple_account_option_get_setting_wrapped)
return false;
purple_blist_node_get_type_wrapped = (purple_blist_node_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_node_get_type");
if (!purple_blist_node_get_type_wrapped)
return false;
purple_buddy_get_alias_wrapped = (purple_buddy_get_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_alias");
if (!purple_buddy_get_alias_wrapped)
return false;
purple_buddy_get_server_alias_wrapped = (purple_buddy_get_server_alias_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_server_alias");
if (!purple_buddy_get_server_alias_wrapped)
return false;
purple_find_buddy_wrapped = (purple_find_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_buddy");
if (!purple_find_buddy_wrapped)
return false;
purple_buddy_get_group_wrapped = (purple_buddy_get_group_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_group");
if (!purple_buddy_get_group_wrapped)
return false;
purple_blist_remove_buddy_wrapped = (purple_blist_remove_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_remove_buddy");
if (!purple_blist_remove_buddy_wrapped)
return false;
purple_blist_alias_buddy_wrapped = (purple_blist_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_alias_buddy");
if (!purple_blist_alias_buddy_wrapped)
return false;
purple_blist_server_alias_buddy_wrapped = (purple_blist_server_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_server_alias_buddy");
if (!purple_blist_server_alias_buddy_wrapped)
return false;
purple_find_group_wrapped = (purple_find_group_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_group");
if (!purple_find_group_wrapped)
return false;
purple_group_new_wrapped = (purple_group_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_group_new");
if (!purple_group_new_wrapped)
return false;
purple_blist_add_contact_wrapped = (purple_blist_add_contact_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_add_contact");
if (!purple_blist_add_contact_wrapped)
return false;
purple_buddy_get_contact_wrapped = (purple_buddy_get_contact_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_contact");
if (!purple_buddy_get_contact_wrapped)
return false;
purple_buddy_new_wrapped = (purple_buddy_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_new");
if (!purple_buddy_new_wrapped)
return false;
purple_blist_add_buddy_wrapped = (purple_blist_add_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_add_buddy");
if (!purple_blist_add_buddy_wrapped)
return false;
purple_blist_find_chat_wrapped = (purple_blist_find_chat_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_find_chat");
if (!purple_blist_find_chat_wrapped)
return false;
purple_chat_get_components_wrapped = (purple_chat_get_components_wrapped_fnc)GetProcAddress(f_hPurple, "purple_chat_get_components");
if (!purple_chat_get_components_wrapped)
return false;
purple_buddy_get_presence_wrapped = (purple_buddy_get_presence_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_presence");
if (!purple_buddy_get_presence_wrapped)
return false;
purple_buddy_get_account_wrapped = (purple_buddy_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_account");
if (!purple_buddy_get_account_wrapped)
return false;
purple_buddy_get_name_wrapped = (purple_buddy_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_get_name");
if (!purple_buddy_get_name_wrapped)
return false;
purple_find_buddies_wrapped = (purple_find_buddies_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_buddies");
if (!purple_find_buddies_wrapped)
return false;
purple_group_get_name_wrapped = (purple_group_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_group_get_name");
if (!purple_group_get_name_wrapped)
return false;
purple_blist_set_ui_ops_wrapped = (purple_blist_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_set_ui_ops");
if (!purple_blist_set_ui_ops_wrapped)
return false;
purple_set_blist_wrapped = (purple_set_blist_wrapped_fnc)GetProcAddress(f_hPurple, "purple_set_blist");
if (!purple_set_blist_wrapped)
return false;
purple_blist_new_wrapped = (purple_blist_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_new");
if (!purple_blist_new_wrapped)
return false;
purple_blist_load_wrapped = (purple_blist_load_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_load");
if (!purple_blist_load_wrapped)
return false;
purple_blist_get_handle_wrapped = (purple_blist_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_blist_get_handle");
if (!purple_blist_get_handle_wrapped)
return false;
purple_buddy_icons_set_account_icon_wrapped = (purple_buddy_icons_set_account_icon_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_set_account_icon");
if (!purple_buddy_icons_set_account_icon_wrapped)
return false;
purple_buddy_icons_find_wrapped = (purple_buddy_icons_find_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_find");
if (!purple_buddy_icons_find_wrapped)
return false;
purple_buddy_icon_get_full_path_wrapped = (purple_buddy_icon_get_full_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_get_full_path");
if (!purple_buddy_icon_get_full_path_wrapped)
return false;
purple_buddy_icon_unref_wrapped = (purple_buddy_icon_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_unref");
if (!purple_buddy_icon_unref_wrapped)
return false;
purple_buddy_icons_find_account_icon_wrapped = (purple_buddy_icons_find_account_icon_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icons_find_account_icon");
if (!purple_buddy_icons_find_account_icon_wrapped)
return false;
purple_buddy_icon_get_data_wrapped = (purple_buddy_icon_get_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_buddy_icon_get_data");
if (!purple_buddy_icon_get_data_wrapped)
return false;
purple_certificate_add_ca_search_path_wrapped = (purple_certificate_add_ca_search_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_certificate_add_ca_search_path");
if (!purple_certificate_add_ca_search_path_wrapped)
return false;
purple_connection_get_state_wrapped = (purple_connection_get_state_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_state");
if (!purple_connection_get_state_wrapped)
return false;
purple_connection_get_account_wrapped = (purple_connection_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_account");
if (!purple_connection_get_account_wrapped)
return false;
purple_connection_get_display_name_wrapped = (purple_connection_get_display_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_display_name");
if (!purple_connection_get_display_name_wrapped)
return false;
purple_connections_set_ui_ops_wrapped = (purple_connections_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_set_ui_ops");
if (!purple_connections_set_ui_ops_wrapped)
return false;
purple_connections_get_handle_wrapped = (purple_connections_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_get_handle");
if (!purple_connections_get_handle_wrapped)
return false;
purple_conversation_get_im_data_wrapped = (purple_conversation_get_im_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_im_data");
if (!purple_conversation_get_im_data_wrapped)
return false;
purple_conversation_get_chat_data_wrapped = (purple_conversation_get_chat_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_chat_data");
if (!purple_conversation_get_chat_data_wrapped)
return false;
purple_find_conversation_with_account_wrapped = (purple_find_conversation_with_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_conversation_with_account");
if (!purple_find_conversation_with_account_wrapped)
return false;
purple_conversation_new_wrapped = (purple_conversation_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_new");
if (!purple_conversation_new_wrapped)
return false;
purple_conversation_get_type_wrapped = (purple_conversation_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_type");
if (!purple_conversation_get_type_wrapped)
return false;
purple_conv_im_send_wrapped = (purple_conv_im_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_im_send");
if (!purple_conv_im_send_wrapped)
return false;
purple_conv_chat_send_wrapped = (purple_conv_chat_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_chat_send");
if (!purple_conv_chat_send_wrapped)
return false;
purple_conversation_destroy_wrapped = (purple_conversation_destroy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_destroy");
if (!purple_conversation_destroy_wrapped)
return false;
purple_conversation_get_account_wrapped = (purple_conversation_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_account");
if (!purple_conversation_get_account_wrapped)
return false;
purple_conversation_get_name_wrapped = (purple_conversation_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_name");
if (!purple_conversation_get_name_wrapped)
return false;
purple_conversations_set_ui_ops_wrapped = (purple_conversations_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_set_ui_ops");
if (!purple_conversations_set_ui_ops_wrapped)
return false;
purple_conversations_get_handle_wrapped = (purple_conversations_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_get_handle");
if (!purple_conversations_get_handle_wrapped)
return false;
purple_core_set_ui_ops_wrapped = (purple_core_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_set_ui_ops");
if (!purple_core_set_ui_ops_wrapped)
return false;
purple_core_init_wrapped = (purple_core_init_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_init");
if (!purple_core_init_wrapped)
return false;
purple_debug_set_ui_ops_wrapped = (purple_debug_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_ui_ops");
if (!purple_debug_set_ui_ops_wrapped)
return false;
purple_debug_set_verbose_wrapped = (purple_debug_set_verbose_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_verbose");
if (!purple_debug_set_verbose_wrapped)
return false;
purple_dnsquery_set_ui_ops_wrapped = (purple_dnsquery_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_dnsquery_set_ui_ops");
if (!purple_dnsquery_set_ui_ops_wrapped)
return false;
purple_timeout_remove_wrapped = (purple_timeout_remove_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_remove");
if (!purple_timeout_remove_wrapped)
return false;
purple_input_add_wrapped = (purple_input_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_input_add");
if (!purple_input_add_wrapped)
return false;
purple_timeout_add_wrapped = (purple_timeout_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_add");
if (!purple_timeout_add_wrapped)
return false;
purple_timeout_add_seconds_wrapped = (purple_timeout_add_seconds_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_add_seconds");
if (!purple_timeout_add_seconds_wrapped)
return false;
purple_eventloop_set_ui_ops_wrapped = (purple_eventloop_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_eventloop_set_ui_ops");
if (!purple_eventloop_set_ui_ops_wrapped)
return false;
purple_input_remove_wrapped = (purple_input_remove_wrapped_fnc)GetProcAddress(f_hPurple, "purple_input_remove");
if (!purple_input_remove_wrapped)
return false;
purple_xfer_ui_ready_wrapped = (purple_xfer_ui_ready_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_ui_ready");
if (!purple_xfer_ui_ready_wrapped)
return false;
purple_xfer_request_accepted_wrapped = (purple_xfer_request_accepted_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_request_accepted");
if (!purple_xfer_request_accepted_wrapped)
return false;
purple_xfer_request_denied_wrapped = (purple_xfer_request_denied_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_request_denied");
if (!purple_xfer_request_denied_wrapped)
return false;
purple_xfer_get_account_wrapped = (purple_xfer_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_account");
if (!purple_xfer_get_account_wrapped)
return false;
purple_xfer_get_filename_wrapped = (purple_xfer_get_filename_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_filename");
if (!purple_xfer_get_filename_wrapped)
return false;
purple_xfer_get_size_wrapped = (purple_xfer_get_size_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_get_size");
if (!purple_xfer_get_size_wrapped)
return false;
purple_xfer_unref_wrapped = (purple_xfer_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_unref");
if (!purple_xfer_unref_wrapped)
return false;
purple_xfer_ref_wrapped = (purple_xfer_ref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfer_ref");
if (!purple_xfer_ref_wrapped)
return false;
purple_xfers_set_ui_ops_wrapped = (purple_xfers_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfers_set_ui_ops");
if (!purple_xfers_set_ui_ops_wrapped)
return false;
purple_xfers_get_handle_wrapped = (purple_xfers_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_xfers_get_handle");
if (!purple_xfers_get_handle_wrapped)
return false;
purple_roomlist_set_ui_ops_wrapped = (purple_roomlist_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_roomlist_set_ui_ops");
if (!purple_roomlist_set_ui_ops_wrapped)
return false;
purple_roomlist_get_list_wrapped = (purple_roomlist_get_list_wrapped_fnc)GetProcAddress(f_hPurple, "purple_roomlist_get_list");
if (!purple_roomlist_get_list_wrapped)
return false;
purple_imgstore_get_data_wrapped = (purple_imgstore_get_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_get_data");
if (!purple_imgstore_get_data_wrapped)
return false;
purple_imgstore_get_size_wrapped = (purple_imgstore_get_size_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_get_size");
if (!purple_imgstore_get_size_wrapped)
return false;
purple_imgstore_unref_wrapped = (purple_imgstore_unref_wrapped_fnc)GetProcAddress(f_hPurple, "purple_imgstore_unref");
if (!purple_imgstore_unref_wrapped)
return false;
purple_notify_user_info_new_wrapped = (purple_notify_user_info_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_new");
if (!purple_notify_user_info_new_wrapped)
return false;
purple_notify_user_info_destroy_wrapped = (purple_notify_user_info_destroy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_destroy");
if (!purple_notify_user_info_destroy_wrapped)
return false;
purple_notify_user_info_get_entries_wrapped = (purple_notify_user_info_get_entries_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_get_entries");
if (!purple_notify_user_info_get_entries_wrapped)
return false;
purple_notify_user_info_entry_get_label_wrapped = (purple_notify_user_info_entry_get_label_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_entry_get_label");
if (!purple_notify_user_info_entry_get_label_wrapped)
return false;
purple_notify_user_info_entry_get_value_wrapped = (purple_notify_user_info_entry_get_value_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_user_info_entry_get_value");
if (!purple_notify_user_info_entry_get_value_wrapped)
return false;
purple_notify_set_ui_ops_wrapped = (purple_notify_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_notify_set_ui_ops");
if (!purple_notify_set_ui_ops_wrapped)
return false;
purple_plugins_add_search_path_wrapped = (purple_plugins_add_search_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_plugins_add_search_path");
if (!purple_plugins_add_search_path_wrapped)
return false;
purple_plugin_action_free_wrapped = (purple_plugin_action_free_wrapped_fnc)GetProcAddress(f_hPurple, "purple_plugin_action_free");
if (!purple_plugin_action_free_wrapped)
return false;
purple_prefs_load_wrapped = (purple_prefs_load_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_load");
if (!purple_prefs_load_wrapped)
return false;
purple_prefs_set_bool_wrapped = (purple_prefs_set_bool_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_set_bool");
if (!purple_prefs_set_bool_wrapped)
return false;
purple_prefs_set_string_wrapped = (purple_prefs_set_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prefs_set_string");
if (!purple_prefs_set_string_wrapped)
return false;
purple_privacy_deny_wrapped = (purple_privacy_deny_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_deny");
if (!purple_privacy_deny_wrapped)
return false;
purple_privacy_allow_wrapped = (purple_privacy_allow_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_allow");
if (!purple_privacy_allow_wrapped)
return false;
purple_privacy_check_wrapped = (purple_privacy_check_wrapped_fnc)GetProcAddress(f_hPurple, "purple_privacy_check");
if (!purple_privacy_check_wrapped)
return false;
purple_proxy_info_new_wrapped = (purple_proxy_info_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_new");
if (!purple_proxy_info_new_wrapped)
return false;
purple_proxy_info_set_type_wrapped = (purple_proxy_info_set_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_type");
if (!purple_proxy_info_set_type_wrapped)
return false;
purple_proxy_info_set_host_wrapped = (purple_proxy_info_set_host_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_host");
if (!purple_proxy_info_set_host_wrapped)
return false;
purple_proxy_info_set_port_wrapped = (purple_proxy_info_set_port_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_port");
if (!purple_proxy_info_set_port_wrapped)
return false;
purple_proxy_info_set_username_wrapped = (purple_proxy_info_set_username_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_username");
if (!purple_proxy_info_set_username_wrapped)
return false;
purple_proxy_info_set_password_wrapped = (purple_proxy_info_set_password_wrapped_fnc)GetProcAddress(f_hPurple, "purple_proxy_info_set_password");
if (!purple_proxy_info_set_password_wrapped)
return false;
purple_find_prpl_wrapped = (purple_find_prpl_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_prpl");
if (!purple_find_prpl_wrapped)
return false;
purple_prpl_send_attention_wrapped = (purple_prpl_send_attention_wrapped_fnc)GetProcAddress(f_hPurple, "purple_prpl_send_attention");
if (!purple_prpl_send_attention_wrapped)
return false;
purple_request_set_ui_ops_wrapped = (purple_request_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_request_set_ui_ops");
if (!purple_request_set_ui_ops_wrapped)
return false;
serv_get_info_wrapped = (serv_get_info_wrapped_fnc)GetProcAddress(f_hPurple, "serv_get_info");
if (!serv_get_info_wrapped)
return false;
serv_alias_buddy_wrapped = (serv_alias_buddy_wrapped_fnc)GetProcAddress(f_hPurple, "serv_alias_buddy");
if (!serv_alias_buddy_wrapped)
return false;
serv_send_typing_wrapped = (serv_send_typing_wrapped_fnc)GetProcAddress(f_hPurple, "serv_send_typing");
if (!serv_send_typing_wrapped)
return false;
serv_join_chat_wrapped = (serv_join_chat_wrapped_fnc)GetProcAddress(f_hPurple, "serv_join_chat");
if (!serv_join_chat_wrapped)
return false;
purple_signal_connect_wrapped = (purple_signal_connect_wrapped_fnc)GetProcAddress(f_hPurple, "purple_signal_connect");
if (!purple_signal_connect_wrapped)
return false;
purple_status_type_get_id_wrapped = (purple_status_type_get_id_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_type_get_id");
if (!purple_status_type_get_id_wrapped)
return false;
purple_presence_get_active_status_wrapped = (purple_presence_get_active_status_wrapped_fnc)GetProcAddress(f_hPurple, "purple_presence_get_active_status");
if (!purple_presence_get_active_status_wrapped)
return false;
purple_status_type_get_primitive_wrapped = (purple_status_type_get_primitive_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_type_get_primitive");
if (!purple_status_type_get_primitive_wrapped)
return false;
purple_status_get_type_wrapped = (purple_status_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_get_type");
if (!purple_status_get_type_wrapped)
return false;
purple_status_get_attr_string_wrapped = (purple_status_get_attr_string_wrapped_fnc)GetProcAddress(f_hPurple, "purple_status_get_attr_string");
if (!purple_status_get_attr_string_wrapped)
return false;
purple_markup_escape_text_wrapped = (purple_markup_escape_text_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_escape_text");
if (!purple_markup_escape_text_wrapped)
return false;
purple_markup_strip_html_wrapped = (purple_markup_strip_html_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_strip_html");
if (!purple_markup_strip_html_wrapped)
return false;
purple_strdup_withhtml_wrapped = (purple_strdup_withhtml_wrapped_fnc)GetProcAddress(f_hPurple, "purple_strdup_withhtml");
if (!purple_strdup_withhtml_wrapped)
return false;
purple_markup_html_to_xhtml_wrapped = (purple_markup_html_to_xhtml_wrapped_fnc)GetProcAddress(f_hPurple, "purple_markup_html_to_xhtml");
if (!purple_markup_html_to_xhtml_wrapped)
return false;
purple_normalize_wrapped = (purple_normalize_wrapped_fnc)GetProcAddress(f_hPurple, "purple_normalize");
if (!purple_normalize_wrapped)
return false;
purple_utf8_try_convert_wrapped = (purple_utf8_try_convert_wrapped_fnc)GetProcAddress(f_hPurple, "purple_utf8_try_convert");
if (!purple_utf8_try_convert_wrapped)
return false;
purple_util_set_user_dir_wrapped = (purple_util_set_user_dir_wrapped_fnc)GetProcAddress(f_hPurple, "purple_util_set_user_dir");
if (!purple_util_set_user_dir_wrapped)
return false;
wpurple_g_io_channel_win32_new_socket_wrapped = (wpurple_g_io_channel_win32_new_socket_wrapped_fnc)GetProcAddress(f_hPurple, "wpurple_g_io_channel_win32_new_socket");
if (!wpurple_g_io_channel_win32_new_socket_wrapped)
return false;
#endif
return true;
}

View file

@ -1,622 +0,0 @@
#pragma once
#if PURPLE_RUNTIME
#include <Windows.h>
#include <purple.h>
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE)
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE)
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE)
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE)
#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c))
#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c))
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) (purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED)
typedef void (_cdecl * purple_account_set_bool_wrapped_fnc)(PurpleAccount *account, const char *name, gboolean value);
extern purple_account_set_bool_wrapped_fnc purple_account_set_bool_wrapped;
typedef const char * (_cdecl * purple_account_get_protocol_id_wrapped_fnc)(const PurpleAccount *account);
extern purple_account_get_protocol_id_wrapped_fnc purple_account_get_protocol_id_wrapped;
typedef void (_cdecl * purple_account_set_int_wrapped_fnc)(PurpleAccount *account, const char *name, int value);
extern purple_account_set_int_wrapped_fnc purple_account_set_int_wrapped;
typedef void (_cdecl * purple_account_set_string_wrapped_fnc)(PurpleAccount *account, const char *name, const char *value);
extern purple_account_set_string_wrapped_fnc purple_account_set_string_wrapped;
typedef const char * (_cdecl * purple_account_get_username_wrapped_fnc)(const PurpleAccount *account);
extern purple_account_get_username_wrapped_fnc purple_account_get_username_wrapped;
typedef void (_cdecl * purple_account_set_username_wrapped_fnc)(PurpleAccount *account, const char *username);
extern purple_account_set_username_wrapped_fnc purple_account_set_username_wrapped;
typedef void (_cdecl * purple_account_set_proxy_info_wrapped_fnc)(PurpleAccount *account, PurpleProxyInfo *info);
extern purple_account_set_proxy_info_wrapped_fnc purple_account_set_proxy_info_wrapped;
typedef PurpleAccount * (_cdecl * purple_accounts_find_wrapped_fnc)(const char *name, const char *protocol);
extern purple_accounts_find_wrapped_fnc purple_accounts_find_wrapped;
typedef PurpleAccount * (_cdecl * purple_account_new_wrapped_fnc)(const char *username, const char *protocol_id);
extern purple_account_new_wrapped_fnc purple_account_new_wrapped;
typedef void (_cdecl * purple_accounts_add_wrapped_fnc)(PurpleAccount *account);
extern purple_accounts_add_wrapped_fnc purple_accounts_add_wrapped;
typedef const char * (_cdecl * purple_account_get_password_wrapped_fnc)(const PurpleAccount *account);
extern purple_account_get_password_wrapped_fnc purple_account_get_password_wrapped;
typedef void (_cdecl * purple_account_set_password_wrapped_fnc)(PurpleAccount *account, const char *password);
extern purple_account_set_password_wrapped_fnc purple_account_set_password_wrapped;
typedef void (_cdecl * purple_account_set_enabled_wrapped_fnc)(PurpleAccount *account, const char *ui, gboolean value);
extern purple_account_set_enabled_wrapped_fnc purple_account_set_enabled_wrapped;
typedef void (_cdecl * purple_account_set_privacy_type_wrapped_fnc)(PurpleAccount *account, PurplePrivacyType privacy_type);
extern purple_account_set_privacy_type_wrapped_fnc purple_account_set_privacy_type_wrapped;
typedef PurpleStatusType * (_cdecl * purple_account_get_status_type_with_primitive_wrapped_fnc)( const PurpleAccount *account, PurpleStatusPrimitive primitive);
extern purple_account_get_status_type_with_primitive_wrapped_fnc purple_account_get_status_type_with_primitive_wrapped;
typedef void (_cdecl * purple_account_set_status_wrapped_fnc)(PurpleAccount *account, const char *status_id, gboolean active, ...);
extern purple_account_set_status_wrapped_fnc purple_account_set_status_wrapped;
typedef int (_cdecl * purple_account_get_int_wrapped_fnc)(const PurpleAccount *account, const char *name, int default_value);
extern purple_account_get_int_wrapped_fnc purple_account_get_int_wrapped;
typedef void (_cdecl * purple_account_disconnect_wrapped_fnc)(PurpleAccount *account);
extern purple_account_disconnect_wrapped_fnc purple_account_disconnect_wrapped;
typedef void (_cdecl * purple_accounts_delete_wrapped_fnc)(PurpleAccount *account);
extern purple_accounts_delete_wrapped_fnc purple_accounts_delete_wrapped;
typedef PurpleConnection * (_cdecl * purple_account_get_connection_wrapped_fnc)(const PurpleAccount *account);
extern purple_account_get_connection_wrapped_fnc purple_account_get_connection_wrapped;
typedef void (_cdecl * purple_account_set_alias_wrapped_fnc)(PurpleAccount *account, const char *alias);
extern purple_account_set_alias_wrapped_fnc purple_account_set_alias_wrapped;
typedef void (_cdecl * purple_account_set_public_alias_wrapped_fnc)(PurpleAccount *account, const char *alias, PurpleSetPublicAliasSuccessCallback success_cb, PurpleSetPublicAliasFailureCallback failure_cb);
extern purple_account_set_public_alias_wrapped_fnc purple_account_set_public_alias_wrapped;
typedef void (_cdecl * purple_account_remove_buddy_wrapped_fnc)(PurpleAccount *account, PurpleBuddy *buddy, PurpleGroup *group);
extern purple_account_remove_buddy_wrapped_fnc purple_account_remove_buddy_wrapped;
typedef void (_cdecl * purple_account_add_buddy_wrapped_fnc)(PurpleAccount *account, PurpleBuddy *buddy);
extern purple_account_add_buddy_wrapped_fnc purple_account_add_buddy_wrapped;
typedef const gchar * (_cdecl * purple_account_get_name_for_display_wrapped_fnc)(const PurpleAccount *account);
extern purple_account_get_name_for_display_wrapped_fnc purple_account_get_name_for_display_wrapped;
typedef void (_cdecl * purple_accounts_set_ui_ops_wrapped_fnc)(PurpleAccountUiOps *ops);
extern purple_accounts_set_ui_ops_wrapped_fnc purple_accounts_set_ui_ops_wrapped;
typedef PurplePrefType (_cdecl * purple_account_option_get_type_wrapped_fnc)(const PurpleAccountOption *option);
extern purple_account_option_get_type_wrapped_fnc purple_account_option_get_type_wrapped;
typedef const char * (_cdecl * purple_account_option_get_setting_wrapped_fnc)(const PurpleAccountOption *option);
extern purple_account_option_get_setting_wrapped_fnc purple_account_option_get_setting_wrapped;
typedef PurpleBlistNodeType (_cdecl * purple_blist_node_get_type_wrapped_fnc)(PurpleBlistNode *node);
extern purple_blist_node_get_type_wrapped_fnc purple_blist_node_get_type_wrapped;
typedef const char * (_cdecl * purple_buddy_get_alias_wrapped_fnc)(PurpleBuddy *buddy);
extern purple_buddy_get_alias_wrapped_fnc purple_buddy_get_alias_wrapped;
typedef const char * (_cdecl * purple_buddy_get_server_alias_wrapped_fnc)(PurpleBuddy *buddy);
extern purple_buddy_get_server_alias_wrapped_fnc purple_buddy_get_server_alias_wrapped;
typedef PurpleBuddy * (_cdecl * purple_find_buddy_wrapped_fnc)(PurpleAccount *account, const char *name);
extern purple_find_buddy_wrapped_fnc purple_find_buddy_wrapped;
typedef PurpleGroup * (_cdecl * purple_buddy_get_group_wrapped_fnc)(PurpleBuddy *buddy);
extern purple_buddy_get_group_wrapped_fnc purple_buddy_get_group_wrapped;
typedef void (_cdecl * purple_blist_remove_buddy_wrapped_fnc)(PurpleBuddy *buddy);
extern purple_blist_remove_buddy_wrapped_fnc purple_blist_remove_buddy_wrapped;
typedef void (_cdecl * purple_blist_alias_buddy_wrapped_fnc)(PurpleBuddy *buddy, const char *alias);
extern purple_blist_alias_buddy_wrapped_fnc purple_blist_alias_buddy_wrapped;
typedef void (_cdecl * purple_blist_server_alias_buddy_wrapped_fnc)(PurpleBuddy *buddy, const char *alias);
extern purple_blist_server_alias_buddy_wrapped_fnc purple_blist_server_alias_buddy_wrapped;
typedef PurpleGroup * (_cdecl * purple_find_group_wrapped_fnc)(const char *name);
extern purple_find_group_wrapped_fnc purple_find_group_wrapped;
typedef PurpleGroup * (_cdecl * purple_group_new_wrapped_fnc)(const char *name);
extern purple_group_new_wrapped_fnc purple_group_new_wrapped;
typedef void (_cdecl * purple_blist_add_contact_wrapped_fnc)(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node);
extern purple_blist_add_contact_wrapped_fnc purple_blist_add_contact_wrapped;
typedef PurpleContact * (_cdecl * purple_buddy_get_contact_wrapped_fnc)(PurpleBuddy *buddy);
extern purple_buddy_get_contact_wrapped_fnc purple_buddy_get_contact_wrapped;
typedef PurpleBuddy * (_cdecl * purple_buddy_new_wrapped_fnc)(PurpleAccount *account, const char *name, const char *alias);
extern purple_buddy_new_wrapped_fnc purple_buddy_new_wrapped;
typedef void (_cdecl * purple_blist_add_buddy_wrapped_fnc)(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node);
extern purple_blist_add_buddy_wrapped_fnc purple_blist_add_buddy_wrapped;
typedef PurpleChat * (_cdecl * purple_blist_find_chat_wrapped_fnc)(PurpleAccount *account, const char *name);
extern purple_blist_find_chat_wrapped_fnc purple_blist_find_chat_wrapped;
typedef GHashTable * (_cdecl * purple_chat_get_components_wrapped_fnc)(PurpleChat *chat);
extern purple_chat_get_components_wrapped_fnc purple_chat_get_components_wrapped;
typedef PurplePresence * (_cdecl * purple_buddy_get_presence_wrapped_fnc)(const PurpleBuddy *buddy);
extern purple_buddy_get_presence_wrapped_fnc purple_buddy_get_presence_wrapped;
typedef PurpleAccount * (_cdecl * purple_buddy_get_account_wrapped_fnc)(const PurpleBuddy *buddy);
extern purple_buddy_get_account_wrapped_fnc purple_buddy_get_account_wrapped;
typedef const char * (_cdecl * purple_buddy_get_name_wrapped_fnc)(const PurpleBuddy *buddy);
extern purple_buddy_get_name_wrapped_fnc purple_buddy_get_name_wrapped;
typedef GSList * (_cdecl * purple_find_buddies_wrapped_fnc)(PurpleAccount *account, const char *name);
extern purple_find_buddies_wrapped_fnc purple_find_buddies_wrapped;
typedef const char * (_cdecl * purple_group_get_name_wrapped_fnc)(PurpleGroup *group);
extern purple_group_get_name_wrapped_fnc purple_group_get_name_wrapped;
typedef void (_cdecl * purple_blist_set_ui_ops_wrapped_fnc)(PurpleBlistUiOps *ops);
extern purple_blist_set_ui_ops_wrapped_fnc purple_blist_set_ui_ops_wrapped;
typedef void (_cdecl * purple_set_blist_wrapped_fnc)(PurpleBuddyList *blist);
extern purple_set_blist_wrapped_fnc purple_set_blist_wrapped;
typedef PurpleBuddyList * (_cdecl * purple_blist_new_wrapped_fnc)(void);
extern purple_blist_new_wrapped_fnc purple_blist_new_wrapped;
typedef void (_cdecl * purple_blist_load_wrapped_fnc)(void);
extern purple_blist_load_wrapped_fnc purple_blist_load_wrapped;
typedef void * (_cdecl * purple_blist_get_handle_wrapped_fnc)(void);
extern purple_blist_get_handle_wrapped_fnc purple_blist_get_handle_wrapped;
typedef PurpleStoredImage * (_cdecl * purple_buddy_icons_set_account_icon_wrapped_fnc)(PurpleAccount *account, guchar *icon_data, size_t icon_len);
extern purple_buddy_icons_set_account_icon_wrapped_fnc purple_buddy_icons_set_account_icon_wrapped;
typedef PurpleBuddyIcon * (_cdecl * purple_buddy_icons_find_wrapped_fnc)(PurpleAccount *account, const char *username);
extern purple_buddy_icons_find_wrapped_fnc purple_buddy_icons_find_wrapped;
typedef char * (_cdecl * purple_buddy_icon_get_full_path_wrapped_fnc)(PurpleBuddyIcon *icon);
extern purple_buddy_icon_get_full_path_wrapped_fnc purple_buddy_icon_get_full_path_wrapped;
typedef PurpleBuddyIcon * (_cdecl * purple_buddy_icon_unref_wrapped_fnc)(PurpleBuddyIcon *icon);
extern purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped;
typedef PurpleStoredImage * (_cdecl * purple_buddy_icons_find_account_icon_wrapped_fnc)(PurpleAccount *account);
extern purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped;
typedef gconstpointer (_cdecl * purple_buddy_icon_get_data_wrapped_fnc)(const PurpleBuddyIcon *icon, size_t *len);
extern purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped;
typedef void (_cdecl * purple_certificate_add_ca_search_path_wrapped_fnc)(const char *path);
extern purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped;
typedef PurpleConnectionState (_cdecl * purple_connection_get_state_wrapped_fnc)(const PurpleConnection *gc);
extern purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped;
typedef PurpleAccount * (_cdecl * purple_connection_get_account_wrapped_fnc)(const PurpleConnection *gc);
extern purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped;
typedef const char * (_cdecl * purple_connection_get_display_name_wrapped_fnc)(const PurpleConnection *gc);
extern purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped;
typedef void (_cdecl * purple_connections_set_ui_ops_wrapped_fnc)(PurpleConnectionUiOps *ops);
extern purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped;
typedef void * (_cdecl * purple_connections_get_handle_wrapped_fnc)(void);
extern purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped;
typedef PurpleConvIm * (_cdecl * purple_conversation_get_im_data_wrapped_fnc)(const PurpleConversation *conv);
extern purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped;
typedef PurpleConvChat * (_cdecl * purple_conversation_get_chat_data_wrapped_fnc)(const PurpleConversation *conv);
extern purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped;
typedef PurpleConversation * (_cdecl * purple_find_conversation_with_account_wrapped_fnc)( PurpleConversationType type, const char *name, const PurpleAccount *account);
extern purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped;
typedef PurpleConversation * (_cdecl * purple_conversation_new_wrapped_fnc)(PurpleConversationType type, PurpleAccount *account, const char *name);
extern purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped;
typedef PurpleConversationType (_cdecl * purple_conversation_get_type_wrapped_fnc)(const PurpleConversation *conv);
extern purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped;
typedef void (_cdecl * purple_conversation_set_data_wrapped_func)(const PurpleConversation *conv, const char *key, gpointer data);
extern purple_conversation_set_data_wrapped_func purple_conversation_set_data_wrapped;
typedef void (_cdecl * purple_conversation_update_wrapped_func)(const PurpleConversation *conv, PurpleConversationUpdateType type);
extern purple_conversation_update_wrapped_func purple_conversation_update_wrapped;
typedef void (_cdecl * purple_conv_im_send_wrapped_fnc)(PurpleConvIm *im, const char *message);
extern purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped;
typedef void (_cdecl * purple_conv_chat_send_wrapped_fnc)(PurpleConvChat *chat, const char *message);
extern purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped;
typedef void (_cdecl * purple_conversation_destroy_wrapped_fnc)(PurpleConversation *conv);
extern purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped;
typedef PurpleAccount * (_cdecl * purple_conversation_get_account_wrapped_fnc)(const PurpleConversation *conv);
extern purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped;
typedef const char * (_cdecl * purple_conversation_get_name_wrapped_fnc)(const PurpleConversation *conv);
extern purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped;
typedef void (_cdecl * purple_conversations_set_ui_ops_wrapped_fnc)(PurpleConversationUiOps *ops);
extern purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped;
typedef void * (_cdecl * purple_conversations_get_handle_wrapped_fnc)(void);
extern purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped;
typedef void (_cdecl * purple_core_set_ui_ops_wrapped_fnc)(PurpleCoreUiOps *ops);
extern purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped;
typedef gboolean (_cdecl * purple_core_init_wrapped_fnc)(const char *ui);
extern purple_core_init_wrapped_fnc purple_core_init_wrapped;
typedef void (_cdecl * purple_debug_set_ui_ops_wrapped_fnc)(PurpleDebugUiOps *ops);
extern purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped;
typedef void (_cdecl * purple_debug_set_verbose_wrapped_fnc)(gboolean verbose);
extern purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped;
typedef void (_cdecl * purple_dnsquery_set_ui_ops_wrapped_fnc)(PurpleDnsQueryUiOps *ops);
extern purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped;
typedef gboolean (_cdecl * purple_timeout_remove_wrapped_fnc)(guint handle);
extern purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped;
typedef guint (_cdecl * purple_input_add_wrapped_fnc)(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data);
extern purple_input_add_wrapped_fnc purple_input_add_wrapped;
typedef guint (_cdecl * purple_timeout_add_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
extern purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped;
typedef guint (_cdecl * purple_timeout_add_seconds_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
extern purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped;
typedef void (_cdecl * purple_eventloop_set_ui_ops_wrapped_fnc)(PurpleEventLoopUiOps *ops);
extern purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped;
typedef gboolean (_cdecl * purple_input_remove_wrapped_fnc)(guint handle);
extern purple_input_remove_wrapped_fnc purple_input_remove_wrapped;
typedef void (_cdecl * purple_xfer_ui_ready_wrapped_fnc)(PurpleXfer *xfer);
extern purple_xfer_ui_ready_wrapped_fnc purple_xfer_ui_ready_wrapped;
typedef void (_cdecl * purple_xfer_request_accepted_wrapped_fnc)(PurpleXfer *xfer, const char *filename);
extern purple_xfer_request_accepted_wrapped_fnc purple_xfer_request_accepted_wrapped;
typedef void (_cdecl * purple_xfer_request_denied_wrapped_fnc)(PurpleXfer *xfer);
extern purple_xfer_request_denied_wrapped_fnc purple_xfer_request_denied_wrapped;
typedef PurpleAccount * (_cdecl * purple_xfer_get_account_wrapped_fnc)(const PurpleXfer *xfer);
extern purple_xfer_get_account_wrapped_fnc purple_xfer_get_account_wrapped;
typedef const char * (_cdecl * purple_xfer_get_filename_wrapped_fnc)(const PurpleXfer *xfer);
extern purple_xfer_get_filename_wrapped_fnc purple_xfer_get_filename_wrapped;
typedef size_t (_cdecl * purple_xfer_get_size_wrapped_fnc)(const PurpleXfer *xfer);
extern purple_xfer_get_size_wrapped_fnc purple_xfer_get_size_wrapped;
typedef void (_cdecl * purple_xfer_unref_wrapped_fnc)(PurpleXfer *xfer);
extern purple_xfer_unref_wrapped_fnc purple_xfer_unref_wrapped;
typedef void (_cdecl * purple_xfer_ref_wrapped_fnc)(PurpleXfer *xfer);
extern purple_xfer_ref_wrapped_fnc purple_xfer_ref_wrapped;
typedef void (_cdecl * purple_xfers_set_ui_ops_wrapped_fnc)(PurpleXferUiOps *ops);
extern purple_xfers_set_ui_ops_wrapped_fnc purple_xfers_set_ui_ops_wrapped;
typedef void * (_cdecl * purple_xfers_get_handle_wrapped_fnc)(void);
extern purple_xfers_get_handle_wrapped_fnc purple_xfers_get_handle_wrapped;
typedef void (_cdecl * purple_roomlist_set_ui_ops_wrapped_fnc)(PurpleRoomlistUiOps *ops);
extern purple_roomlist_set_ui_ops_wrapped_fnc purple_roomlist_set_ui_ops_wrapped;
typedef PurpleRoomlist * (_cdecl * purple_roomlist_get_list_wrapped_fnc)(PurpleConnection *con);
extern purple_roomlist_get_list_wrapped_fnc purple_roomlist_get_list_wrapped;
typedef gconstpointer (_cdecl * purple_imgstore_get_data_wrapped_fnc)(PurpleStoredImage *img);
extern purple_imgstore_get_data_wrapped_fnc purple_imgstore_get_data_wrapped;
typedef size_t (_cdecl * purple_imgstore_get_size_wrapped_fnc)(PurpleStoredImage *img);
extern purple_imgstore_get_size_wrapped_fnc purple_imgstore_get_size_wrapped;
typedef PurpleStoredImage * (_cdecl * purple_imgstore_unref_wrapped_fnc)(PurpleStoredImage *img);
extern purple_imgstore_unref_wrapped_fnc purple_imgstore_unref_wrapped;
typedef PurpleNotifyUserInfo * (_cdecl * purple_notify_user_info_new_wrapped_fnc)(void);
extern purple_notify_user_info_new_wrapped_fnc purple_notify_user_info_new_wrapped;
typedef void (_cdecl * purple_notify_user_info_destroy_wrapped_fnc)(PurpleNotifyUserInfo *user_info);
extern purple_notify_user_info_destroy_wrapped_fnc purple_notify_user_info_destroy_wrapped;
typedef GList * (_cdecl * purple_notify_user_info_get_entries_wrapped_fnc)(PurpleNotifyUserInfo *user_info);
extern purple_notify_user_info_get_entries_wrapped_fnc purple_notify_user_info_get_entries_wrapped;
typedef const gchar * (_cdecl * purple_notify_user_info_entry_get_label_wrapped_fnc)(PurpleNotifyUserInfoEntry *user_info_entry);
extern purple_notify_user_info_entry_get_label_wrapped_fnc purple_notify_user_info_entry_get_label_wrapped;
typedef const gchar * (_cdecl * purple_notify_user_info_entry_get_value_wrapped_fnc)(PurpleNotifyUserInfoEntry *user_info_entry);
extern purple_notify_user_info_entry_get_value_wrapped_fnc purple_notify_user_info_entry_get_value_wrapped;
typedef void (_cdecl * purple_notify_set_ui_ops_wrapped_fnc)(PurpleNotifyUiOps *ops);
extern purple_notify_set_ui_ops_wrapped_fnc purple_notify_set_ui_ops_wrapped;
typedef void (_cdecl * purple_plugins_add_search_path_wrapped_fnc)(const char *path);
extern purple_plugins_add_search_path_wrapped_fnc purple_plugins_add_search_path_wrapped;
typedef void (_cdecl * purple_plugin_action_free_wrapped_fnc)(PurplePluginAction *action);
extern purple_plugin_action_free_wrapped_fnc purple_plugin_action_free_wrapped;
typedef gboolean (_cdecl * purple_prefs_load_wrapped_fnc)(void);
extern purple_prefs_load_wrapped_fnc purple_prefs_load_wrapped;
typedef void (_cdecl * purple_prefs_set_bool_wrapped_fnc)(const char *name, gboolean value);
extern purple_prefs_set_bool_wrapped_fnc purple_prefs_set_bool_wrapped;
typedef void (_cdecl * purple_prefs_set_string_wrapped_fnc)(const char *name, const char *value);
extern purple_prefs_set_string_wrapped_fnc purple_prefs_set_string_wrapped;
typedef void (_cdecl * purple_privacy_deny_wrapped_fnc)(PurpleAccount *account, const char *who, gboolean local, gboolean restore);
extern purple_privacy_deny_wrapped_fnc purple_privacy_deny_wrapped;
typedef void (_cdecl * purple_privacy_allow_wrapped_fnc)(PurpleAccount *account, const char *who, gboolean local, gboolean restore);
extern purple_privacy_allow_wrapped_fnc purple_privacy_allow_wrapped;
typedef gboolean (_cdecl * purple_privacy_check_wrapped_fnc)(PurpleAccount *account, const char *who);
extern purple_privacy_check_wrapped_fnc purple_privacy_check_wrapped;
typedef PurpleProxyInfo * (_cdecl * purple_proxy_info_new_wrapped_fnc)(void);
extern purple_proxy_info_new_wrapped_fnc purple_proxy_info_new_wrapped;
typedef void (_cdecl * purple_proxy_info_set_type_wrapped_fnc)(PurpleProxyInfo *info, PurpleProxyType type);
extern purple_proxy_info_set_type_wrapped_fnc purple_proxy_info_set_type_wrapped;
typedef void (_cdecl * purple_proxy_info_set_host_wrapped_fnc)(PurpleProxyInfo *info, const char *host);
extern purple_proxy_info_set_host_wrapped_fnc purple_proxy_info_set_host_wrapped;
typedef void (_cdecl * purple_proxy_info_set_port_wrapped_fnc)(PurpleProxyInfo *info, int port);
extern purple_proxy_info_set_port_wrapped_fnc purple_proxy_info_set_port_wrapped;
typedef void (_cdecl * purple_proxy_info_set_username_wrapped_fnc)(PurpleProxyInfo *info, const char *username);
extern purple_proxy_info_set_username_wrapped_fnc purple_proxy_info_set_username_wrapped;
typedef void (_cdecl * purple_proxy_info_set_password_wrapped_fnc)(PurpleProxyInfo *info, const char *password);
extern purple_proxy_info_set_password_wrapped_fnc purple_proxy_info_set_password_wrapped;
typedef PurplePlugin * (_cdecl * purple_find_prpl_wrapped_fnc)(const char *id);
extern purple_find_prpl_wrapped_fnc purple_find_prpl_wrapped;
typedef void (_cdecl * purple_prpl_send_attention_wrapped_fnc)(PurpleConnection *gc, const char *who, guint type_code);
extern purple_prpl_send_attention_wrapped_fnc purple_prpl_send_attention_wrapped;
typedef void (_cdecl * purple_request_set_ui_ops_wrapped_fnc)(PurpleRequestUiOps *ops);
extern purple_request_set_ui_ops_wrapped_fnc purple_request_set_ui_ops_wrapped;
typedef void (_cdecl * serv_get_info_wrapped_fnc)(PurpleConnection *, const char *);
extern serv_get_info_wrapped_fnc serv_get_info_wrapped;
typedef void (_cdecl * serv_alias_buddy_wrapped_fnc)(PurpleBuddy *);
extern serv_alias_buddy_wrapped_fnc serv_alias_buddy_wrapped;
typedef unsigned int (_cdecl * serv_send_typing_wrapped_fnc)(PurpleConnection *gc, const char *name, PurpleTypingState state);
extern serv_send_typing_wrapped_fnc serv_send_typing_wrapped;
typedef void (_cdecl * serv_join_chat_wrapped_fnc)(PurpleConnection *, GHashTable *data);
extern serv_join_chat_wrapped_fnc serv_join_chat_wrapped;
typedef gulong (_cdecl * purple_signal_connect_wrapped_fnc)(void *instance, const char *signal, void *handle, PurpleCallback func, void *data);
extern purple_signal_connect_wrapped_fnc purple_signal_connect_wrapped;
typedef const char * (_cdecl * purple_status_type_get_id_wrapped_fnc)(const PurpleStatusType *status_type);
extern purple_status_type_get_id_wrapped_fnc purple_status_type_get_id_wrapped;
typedef PurpleStatus * (_cdecl * purple_presence_get_active_status_wrapped_fnc)(const PurplePresence *presence);
extern purple_presence_get_active_status_wrapped_fnc purple_presence_get_active_status_wrapped;
typedef PurpleStatusPrimitive (_cdecl * purple_status_type_get_primitive_wrapped_fnc)( const PurpleStatusType *status_type);
extern purple_status_type_get_primitive_wrapped_fnc purple_status_type_get_primitive_wrapped;
typedef PurpleStatusType * (_cdecl * purple_status_get_type_wrapped_fnc)(const PurpleStatus *status);
extern purple_status_get_type_wrapped_fnc purple_status_get_type_wrapped;
typedef const char * (_cdecl * purple_status_get_attr_string_wrapped_fnc)(const PurpleStatus *status, const char *id);
extern purple_status_get_attr_string_wrapped_fnc purple_status_get_attr_string_wrapped;
typedef gchar * (_cdecl * purple_markup_escape_text_wrapped_fnc)(const gchar *text, gssize length);
extern purple_markup_escape_text_wrapped_fnc purple_markup_escape_text_wrapped;
typedef char * (_cdecl * purple_markup_strip_html_wrapped_fnc)(const char *str);
extern purple_markup_strip_html_wrapped_fnc purple_markup_strip_html_wrapped;
typedef gchar * (_cdecl * purple_strdup_withhtml_wrapped_fnc)(const gchar *src);
extern purple_strdup_withhtml_wrapped_fnc purple_strdup_withhtml_wrapped;
typedef void (_cdecl * purple_markup_html_to_xhtml_wrapped_fnc)(const char *html, char **dest_xhtml, char **dest_plain);
extern purple_markup_html_to_xhtml_wrapped_fnc purple_markup_html_to_xhtml_wrapped;
typedef const char * (_cdecl * purple_normalize_wrapped_fnc)(const PurpleAccount *account, const char *str);
extern purple_normalize_wrapped_fnc purple_normalize_wrapped;
typedef gchar * (_cdecl * purple_utf8_try_convert_wrapped_fnc)(const char *str);
extern purple_utf8_try_convert_wrapped_fnc purple_utf8_try_convert_wrapped;
typedef void (_cdecl * purple_util_set_user_dir_wrapped_fnc)(const char *dir);
extern purple_util_set_user_dir_wrapped_fnc purple_util_set_user_dir_wrapped;
typedef GIOChannel * (_cdecl * wpurple_g_io_channel_win32_new_socket_wrapped_fnc)(int socket);
extern wpurple_g_io_channel_win32_new_socket_wrapped_fnc wpurple_g_io_channel_win32_new_socket_wrapped;
#else
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP
#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM
#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED
#define purple_account_set_bool_wrapped purple_account_set_bool
#define purple_account_get_protocol_id_wrapped purple_account_get_protocol_id
#define purple_account_set_int_wrapped purple_account_set_int
#define purple_account_set_string_wrapped purple_account_set_string
#define purple_account_get_username_wrapped purple_account_get_username
#define purple_account_set_username_wrapped purple_account_set_username
#define purple_account_set_proxy_info_wrapped purple_account_set_proxy_info
#define purple_accounts_find_wrapped purple_accounts_find
#define purple_account_new_wrapped purple_account_new
#define purple_accounts_add_wrapped purple_accounts_add
#define purple_account_get_password_wrapped purple_account_get_password
#define purple_account_set_password_wrapped purple_account_set_password
#define purple_account_set_enabled_wrapped purple_account_set_enabled
#define purple_account_set_privacy_type_wrapped purple_account_set_privacy_type
#define purple_account_get_status_type_with_primitive_wrapped purple_account_get_status_type_with_primitive
#define purple_account_set_status_wrapped purple_account_set_status
#define purple_account_get_int_wrapped purple_account_get_int
#define purple_account_disconnect_wrapped purple_account_disconnect
#define purple_accounts_delete_wrapped purple_accounts_delete
#define purple_account_get_connection_wrapped purple_account_get_connection
#define purple_account_set_alias_wrapped purple_account_set_alias
#define purple_account_set_public_alias_wrapped purple_account_set_public_alias
#define purple_account_remove_buddy_wrapped purple_account_remove_buddy
#define purple_account_add_buddy_wrapped purple_account_add_buddy
#define purple_account_get_name_for_display_wrapped purple_account_get_name_for_display
#define purple_accounts_set_ui_ops_wrapped purple_accounts_set_ui_ops
#define purple_account_option_get_type_wrapped purple_account_option_get_type
#define purple_account_option_get_setting_wrapped purple_account_option_get_setting
#define purple_blist_node_get_type_wrapped purple_blist_node_get_type
#define purple_buddy_get_alias_wrapped purple_buddy_get_alias
#define purple_buddy_get_server_alias_wrapped purple_buddy_get_server_alias
#define purple_find_buddy_wrapped purple_find_buddy
#define purple_buddy_get_group_wrapped purple_buddy_get_group
#define purple_blist_remove_buddy_wrapped purple_blist_remove_buddy
#define purple_blist_alias_buddy_wrapped purple_blist_alias_buddy
#define purple_blist_server_alias_buddy_wrapped purple_blist_server_alias_buddy
#define purple_find_group_wrapped purple_find_group
#define purple_group_new_wrapped purple_group_new
#define purple_blist_add_contact_wrapped purple_blist_add_contact
#define purple_buddy_get_contact_wrapped purple_buddy_get_contact
#define purple_buddy_new_wrapped purple_buddy_new
#define purple_blist_add_buddy_wrapped purple_blist_add_buddy
#define purple_blist_find_chat_wrapped purple_blist_find_chat
#define purple_chat_get_components_wrapped purple_chat_get_components
#define purple_buddy_get_presence_wrapped purple_buddy_get_presence
#define purple_buddy_get_account_wrapped purple_buddy_get_account
#define purple_buddy_get_name_wrapped purple_buddy_get_name
#define purple_find_buddies_wrapped purple_find_buddies
#define purple_group_get_name_wrapped purple_group_get_name
#define purple_blist_set_ui_ops_wrapped purple_blist_set_ui_ops
#define purple_set_blist_wrapped purple_set_blist
#define purple_blist_new_wrapped purple_blist_new
#define purple_blist_load_wrapped purple_blist_load
#define purple_blist_get_handle_wrapped purple_blist_get_handle
#define purple_buddy_icons_set_account_icon_wrapped purple_buddy_icons_set_account_icon
#define purple_buddy_icons_find_wrapped purple_buddy_icons_find
#define purple_buddy_icon_get_full_path_wrapped purple_buddy_icon_get_full_path
#define purple_buddy_icon_unref_wrapped purple_buddy_icon_unref
#define purple_buddy_icons_find_account_icon_wrapped purple_buddy_icons_find_account_icon
#define purple_buddy_icon_get_data_wrapped purple_buddy_icon_get_data
#define purple_certificate_add_ca_search_path_wrapped purple_certificate_add_ca_search_path
#define purple_connection_get_state_wrapped purple_connection_get_state
#define purple_connection_get_account_wrapped purple_connection_get_account
#define purple_connection_get_display_name_wrapped purple_connection_get_display_name
#define purple_connections_set_ui_ops_wrapped purple_connections_set_ui_ops
#define purple_connections_get_handle_wrapped purple_connections_get_handle
#define purple_conversation_get_im_data_wrapped purple_conversation_get_im_data
#define purple_conversation_get_chat_data_wrapped purple_conversation_get_chat_data
#define purple_find_conversation_with_account_wrapped purple_find_conversation_with_account
#define purple_conversation_new_wrapped purple_conversation_new
#define purple_conversation_get_type_wrapped purple_conversation_get_type
#define purple_conversation_set_data_wrapped purple_conversation_set_data
#define purple_conversation_update_wrapped purple_conversation_update
#define purple_conv_im_send_wrapped purple_conv_im_send
#define purple_conv_chat_send_wrapped purple_conv_chat_send
#define purple_conversation_destroy_wrapped purple_conversation_destroy
#define purple_conversation_get_account_wrapped purple_conversation_get_account
#define purple_conversation_get_name_wrapped purple_conversation_get_name
#define purple_conversations_set_ui_ops_wrapped purple_conversations_set_ui_ops
#define purple_conversations_get_handle_wrapped purple_conversations_get_handle
#define purple_core_set_ui_ops_wrapped purple_core_set_ui_ops
#define purple_core_init_wrapped purple_core_init
#define purple_debug_set_ui_ops_wrapped purple_debug_set_ui_ops
#define purple_debug_set_verbose_wrapped purple_debug_set_verbose
#define purple_dnsquery_set_ui_ops_wrapped purple_dnsquery_set_ui_ops
#define purple_timeout_remove_wrapped purple_timeout_remove
#define purple_input_add_wrapped purple_input_add
#define purple_timeout_add_wrapped purple_timeout_add
#define purple_timeout_add_seconds_wrapped purple_timeout_add_seconds
#define purple_eventloop_set_ui_ops_wrapped purple_eventloop_set_ui_ops
#define purple_input_remove_wrapped purple_input_remove
#define purple_xfer_ui_ready_wrapped purple_xfer_ui_ready
#define purple_xfer_request_accepted_wrapped purple_xfer_request_accepted
#define purple_xfer_request_denied_wrapped purple_xfer_request_denied
#define purple_xfer_get_account_wrapped purple_xfer_get_account
#define purple_xfer_get_filename_wrapped purple_xfer_get_filename
#define purple_xfer_get_size_wrapped purple_xfer_get_size
#define purple_xfer_unref_wrapped purple_xfer_unref
#define purple_xfer_ref_wrapped purple_xfer_ref
#define purple_xfers_set_ui_ops_wrapped purple_xfers_set_ui_ops
#define purple_xfers_get_handle_wrapped purple_xfers_get_handle
#define purple_roomlist_set_ui_ops_wrapped purple_roomlist_set_ui_ops
#define purple_roomlist_get_list_wrapped purple_roomlist_get_list
#define purple_imgstore_get_data_wrapped purple_imgstore_get_data
#define purple_imgstore_get_size_wrapped purple_imgstore_get_size
#define purple_imgstore_unref_wrapped purple_imgstore_unref
#define purple_notify_user_info_new_wrapped purple_notify_user_info_new
#define purple_notify_user_info_destroy_wrapped purple_notify_user_info_destroy
#define purple_notify_user_info_get_entries_wrapped purple_notify_user_info_get_entries
#define purple_notify_user_info_entry_get_label_wrapped purple_notify_user_info_entry_get_label
#define purple_notify_user_info_entry_get_value_wrapped purple_notify_user_info_entry_get_value
#define purple_notify_set_ui_ops_wrapped purple_notify_set_ui_ops
#define purple_plugins_add_search_path_wrapped purple_plugins_add_search_path
#define purple_plugin_action_free_wrapped purple_plugin_action_free
#define purple_prefs_load_wrapped purple_prefs_load
#define purple_prefs_set_bool_wrapped purple_prefs_set_bool
#define purple_prefs_set_string_wrapped purple_prefs_set_string
#define purple_privacy_deny_wrapped purple_privacy_deny
#define purple_privacy_allow_wrapped purple_privacy_allow
#define purple_privacy_check_wrapped purple_privacy_check
#define purple_proxy_info_new_wrapped purple_proxy_info_new
#define purple_proxy_info_set_type_wrapped purple_proxy_info_set_type
#define purple_proxy_info_set_host_wrapped purple_proxy_info_set_host
#define purple_proxy_info_set_port_wrapped purple_proxy_info_set_port
#define purple_proxy_info_set_username_wrapped purple_proxy_info_set_username
#define purple_proxy_info_set_password_wrapped purple_proxy_info_set_password
#define purple_find_prpl_wrapped purple_find_prpl
#define purple_prpl_send_attention_wrapped purple_prpl_send_attention
#define purple_request_set_ui_ops_wrapped purple_request_set_ui_ops
#define serv_get_info_wrapped serv_get_info
#define serv_alias_buddy_wrapped serv_alias_buddy
#define serv_send_typing_wrapped serv_send_typing
#define serv_join_chat_wrapped serv_join_chat
#define purple_signal_connect_wrapped purple_signal_connect
#define purple_status_type_get_id_wrapped purple_status_type_get_id
#define purple_presence_get_active_status_wrapped purple_presence_get_active_status
#define purple_status_type_get_primitive_wrapped purple_status_type_get_primitive
#define purple_status_get_type_wrapped purple_status_get_type
#define purple_status_get_attr_string_wrapped purple_status_get_attr_string
#define purple_markup_escape_text_wrapped purple_markup_escape_text
#define purple_markup_strip_html_wrapped purple_markup_strip_html
#define purple_strdup_withhtml_wrapped purple_strdup_withhtml
#define purple_markup_html_to_xhtml_wrapped purple_markup_html_to_xhtml
#define purple_normalize_wrapped purple_normalize
#define purple_utf8_try_convert_wrapped purple_utf8_try_convert
#define purple_util_set_user_dir_wrapped purple_util_set_user_dir
#define wpurple_g_io_channel_win32_new_socket_wrapped wpurple_g_io_channel_win32_new_socket
#endif
bool resolvePurpleFunctions();

View file

@ -1,11 +0,0 @@
[service]
jid = icq.localhost
password = secret
server = 127.0.0.1
port = 5347
protocol=prpl-jabber
#server_mode=1
[database]
database = test.sql
prefix=icq

View file

@ -1,197 +0,0 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
// win32/libc_interface.h defines its own socket(), read() and so on.
// We don't want to use it here.
#define _LIBC_INTERFACE_H_ 1
#include "utils.h"
#include "glib.h"
#include "purple.h"
#include <algorithm>
#include <iostream>
#include <vector>
#include "errno.h"
#include <string.h>
#ifndef WIN32
#include "sys/wait.h"
#include "sys/signal.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
#include "win32/win32dep.h"
#define close closesocket
#endif
#include "purple_defs.h"
#include <boost/numeric/conversion/cast.hpp>
using std::vector;
static GHashTable *ui_info = NULL;
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name) {
PurplePlugin *plugin = gc && PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) ? gc->prpl : NULL;
if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
PurplePluginAction *action = NULL;
GList *actions, *l;
actions = PURPLE_PLUGIN_ACTIONS(plugin, gc);
for (l = actions; l != NULL; l = l->next) {
if (l->data) {
action = (PurplePluginAction *) l->data;
action->plugin = plugin;
action->context = gc;
if ((std::string) action->label == name) {
action->callback(action);
}
purple_plugin_action_free_wrapped(action);
}
}
}
}
GHashTable *spectrum_ui_get_info(void)
{
if(NULL == ui_info) {
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
/*
* This is the client key for "Pidgin." It is owned by the AIM
* account "markdoliner." Please don't use this key for other
* applications. You can either not specify a client key, in
* which case the default "libpurple" key will be used, or you
* can register for your own client key at
* http://developer.aim.com/manageKeys.jsp
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
/*
* This is the distid for Pidgin, given to us by AOL. Please
* don't use this for other applications. You can just not
* specify a distid and libpurple will use a default.
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
}
return ui_info;
}
#ifndef WIN32
void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
#endif
int create_socket(const char *host, int portno) {
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
return 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;
}
return SocketFD;
}
#ifdef _WIN32
std::wstring utf8ToUtf16(const std::string& str)
{
try
{
if (str.empty())
return L"";
// First request the size of the required UTF-16 buffer
int numRequiredBytes = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), boost::numeric_cast<int>(str.size()), NULL, 0);
if (!numRequiredBytes)
return L"";
// Allocate memory for the UTF-16 string
std::vector<wchar_t> utf16Str(numRequiredBytes);
int numConverted = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), boost::numeric_cast<int>(str.size()), &utf16Str[0], numRequiredBytes);
if (!numConverted)
return L"";
std::wstring wstr(&utf16Str[0], numConverted);
return wstr;
}
catch (...)
{
// I don't believe libtransport is exception-safe so we'll just return an empty string instead
return L"";
}
}
#endif // _WIN32

View file

@ -1,37 +0,0 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
#include "purple.h"
#include <string>
#ifndef WIN32
void spectrum_sigchld_handler(int sig);
#endif
int create_socket(const char *host, int portno);
GHashTable *spectrum_ui_get_info(void);
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name);
#ifdef _WIN32
std::wstring utf8ToUtf16(const std::string& str);
#endif

View file

@ -1,10 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum2_smstools3_backend ${SRC})
target_link_libraries(spectrum2_smstools3_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
INSTALL(TARGETS spectrum2_smstools3_backend RUNTIME DESTINATION bin)

View file

@ -1,292 +0,0 @@
/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This example is free, and not covered by LGPL license. There is no
* restriction applied to their modification, redistribution, using and so on.
* You can study them, modify them, use them in your own program - either
* completely or partially. By using it you may give me some credits in your
* program, but you don't have to.
*/
#include "transport/Config.h"
#include "transport/Logging.h"
#include "transport/NetworkPlugin.h"
#include "transport/SQLite3Backend.h"
#include "transport/MySQLBackend.h"
#include "transport/PQXXBackend.h"
#include "transport/StorageBackend.h"
#include "Swiften/Swiften.h"
#include "Swiften/SwiftenCompat.h"
#include <boost/filesystem.hpp>
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
#include <fstream>
#include <streambuf>
Swift::SimpleEventLoop *loop_;
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
DEFINE_LOGGER(logger, "SMSNetworkPlugin");
#define INTERNAL_USER "/sms@backend@internal@user"
class SMSNetworkPlugin;
SMSNetworkPlugin * np = NULL;
class SMSNetworkPlugin : public NetworkPlugin {
public:
Swift::BoostNetworkFactories *m_factories;
Swift::BoostIOServiceThread m_boostIOServiceThread;
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
Swift::Timer::ref m_timer;
int m_internalUser;
StorageBackend *storageBackend;
SMSNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port) : NetworkPlugin() {
this->config = config;
this->storageBackend = storagebackend;
m_factories = new Swift::BoostNetworkFactories(loop);
m_conn = m_factories->getConnectionFactory()->createConnection();
m_conn->onDataRead.connect(boost::bind(&SMSNetworkPlugin::_handleDataRead, this, _1));
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
// m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
// m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
LOG4CXX_INFO(logger, "Starting the plugin.");
m_timer = m_factories->getTimerFactory()->createTimer(5000);
m_timer->onTick.connect(boost::bind(&SMSNetworkPlugin::handleSMSDir, this));
m_timer->start();
// We're reusing our database model here. Buddies of user with JID INTERNAL_USER are there
// to match received GSM messages from number N with the XMPP users who sent message to number N.
// BuddyName = GSM number
// Alias = XMPP user JID to which the messages from this number is sent to.
// TODO: This should be per Modem!!!
UserInfo info;
info.jid = INTERNAL_USER;
info.password = "";
storageBackend->setUser(info);
storageBackend->getUser(INTERNAL_USER, info);
m_internalUser = info.id;
}
void handleSMS(const std::string &sms) {
LOG4CXX_INFO(logger, "Handling SMS " << sms << ".");
std::ifstream t(sms.c_str());
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
std::string from = "";
std::string msg = "";
while(str.find("\n") != std::string::npos) {
std::string line = str.substr(0, str.find("\n"));
if (line.find("From: ") == 0) {
from = line.substr(strlen("From: "));
}
else if (line.empty()) {
msg = str.substr(1);
break;
}
str = str.substr(str.find("\n") + 1);
}
std::list<BuddyInfo> roster;
storageBackend->getBuddies(m_internalUser, roster);
std::string to;
BOOST_FOREACH(BuddyInfo &b, roster) {
if (b.legacyName == from) {
to = b.alias;
}
}
if (to.empty()) {
LOG4CXX_WARN(logger, "Received SMS from " << from << ", but this number is not associated with any XMPP user.");
}
LOG4CXX_INFO(logger, "Forwarding SMS from " << from << " to " << to << ".");
handleMessage(to, from, msg);
}
void handleSMSDir() {
std::string dir = "/var/spool/sms/incoming/";
if (CONFIG_HAS_KEY(config, "backend.incoming_dir")) {
dir = CONFIG_STRING(config, "backend.incoming_dir");
}
LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS.");
path p(dir);
directory_iterator end_itr;
for (directory_iterator itr(p); itr != end_itr; ++itr) {
try {
if (is_regular(itr->path())) {
handleSMS(itr->path().string());
remove(itr->path());
}
}
catch (const filesystem_error& ex) {
LOG4CXX_ERROR(logger, "Error when removing the SMS: " << ex.what() << ".");
}
}
m_timer->start();
}
void sendSMS(const std::string &to, const std::string &msg) {
// TODO: Probably
std::string data = "To: " + to + "\n";
data += "\n";
data += msg;
// generate random string here...
std::string bucket = "abcdefghijklmnopqrstuvwxyz";
std::string uuid;
for (int i = 0; i < 10; i++) {
uuid += bucket[rand() % bucket.size()];
}
std::ofstream myfile;
myfile.open (std::string("/var/spool/sms/outgoing/spectrum." + uuid).c_str());
myfile << data;
myfile.close();
}
void sendData(const std::string &string) {
m_conn->write(Swift::createSafeByteArray(string));
}
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
std::string d(data->begin(), data->end());
handleDataRead(d);
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
UserInfo info;
if (!storageBackend->getUser(user, info)) {
handleDisconnected(user, 0, "Not registered user.");
return;
}
std::list<BuddyInfo> roster;
storageBackend->getBuddies(info.id, roster);
// Send available presence to every number in the roster.
BOOST_FOREACH(BuddyInfo &b, roster) {
handleBuddyChanged(user, b.legacyName, b.alias, b.groups, pbnetwork::STATUS_ONLINE);
}
np->handleConnected(user);
}
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
}
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
// Remove trailing +, because smstools doesn't use it in "From: " field for received messages.
std::string n = legacyName;
if (n.find("+") == 0) {
n = n.substr(1);
}
// Create GSM Number - XMPP user pair to match the potential response and send it to the proper JID.
BuddyInfo info;
info.legacyName = n;
info.alias = user;
info.id = -1;
info.subscription = "both";
info.flags = 0;
storageBackend->addBuddy(m_internalUser, info);
LOG4CXX_INFO(logger, "Sending SMS from " << user << " to " << n << ".");
sendSMS(n, message);
}
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
}
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
}
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
}
private:
Config *config;
};
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
int main (int argc, char* argv[]) {
std::string host;
int port;
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
std::string error;
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
if (cfg == NULL) {
std::cerr << error;
return 1;
}
Logging::initBackendLogging(cfg);
StorageBackend *storageBackend = StorageBackend::createBackend(cfg, 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;
}
Swift::SimpleEventLoop eventLoop;
loop_ = &eventLoop;
np = new SMSNetworkPlugin(cfg, &eventLoop, storageBackend, host, port);
loop_->run();
return 0;
}

View file

@ -1,14 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp)
ADD_EXECUTABLE(spectrum2_swiften_backend ${SRC})
IF (NOT WIN32)
target_link_libraries(spectrum2_swiften_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else()
target_link_libraries(spectrum2_swiften_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
endif()
INSTALL(TARGETS spectrum2_swiften_backend RUNTIME DESTINATION bin)

View file

@ -1,461 +0,0 @@
// Transport includes
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "transport/Logging.h"
#include "boost/date_time/posix_time/posix_time.hpp"
// Swiften
#include "Swiften/Swiften.h"
#include "Swiften/SwiftenCompat.h"
#include <Swiften/Version.h>
#define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000)
#ifndef WIN32
// for signal handler
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
#endif
#ifndef __FreeBSD__
#ifndef __MACH__
// malloc_trim
#include "malloc.h"
#endif
#endif
// Boost
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
DEFINE_LOGGER(logger, "Swiften");
DEFINE_LOGGER(logger_xml, "backend.xml");
// eventloop
Swift::SimpleEventLoop *loop_;
// Plugins
class SwiftenPlugin;
NetworkPlugin *np = NULL;
Swift::XMPPSerializer *serializer;
class ForwardIQHandler : public Swift::IQHandler {
public:
std::map <std::string, std::string> m_id2resource;
ForwardIQHandler(NetworkPlugin *np, const std::string &user) {
m_np = np;
m_user = user;
}
bool handleIQ(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq) {
if (iq->getPayload<Swift::RosterPayload>() != NULL) {
return false;
}
if (iq->getType() == Swift::IQ::Get) {
m_id2resource[iq->getID()] = iq->getFrom().getResource();
}
iq->setTo(m_user);
std::string xml = safeByteArrayToString(serializer->serializeElement(iq));
m_np->sendRawXML(xml);
return true;
}
private:
NetworkPlugin *m_np;
std::string m_user;
};
class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient {
public:
Swift::BoostNetworkFactories *m_factories;
Swift::BoostIOServiceThread m_boostIOServiceThread;
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
bool m_firstPing;
Swift::FullPayloadSerializerCollection collection;
Swift::XMPPParser *m_xmppParser;
Swift::FullPayloadParserFactoryCollection m_collection2;
SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
this->config = config;
m_firstPing = true;
m_factories = new Swift::BoostNetworkFactories(loop);
m_conn = m_factories->getConnectionFactory()->createConnection();
m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1));
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
#if HAVE_SWIFTEN_3
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType, false);
#else
serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType);
#endif
m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory());
m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
LOG4CXX_INFO(logger, "Starting the plugin.");
}
// NetworkPlugin uses this method to send the data to networkplugin server
void sendData(const std::string &string) {
m_conn->write(Swift::createSafeByteArray(string));
}
// This method has to call handleDataRead with all received data from network plugin server
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
if (m_firstPing) {
m_firstPing = false;
NetworkPlugin::PluginConfig cfg;
cfg.setRawXML(true);
cfg.setNeedRegistration(false);
sendConfig(cfg);
}
std::string d(data->begin(), data->end());
handleDataRead(d);
}
void handleStreamStart(const Swift::ProtocolHeader&) {}
#if HAVE_SWIFTEN_3
void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ToplevelElement> element) {
#else
void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Element> element) {
#endif
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Stanza> stanza = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Stanza>(element);
if (!stanza) {
return;
}
std::string user = stanza->getFrom().toBare();
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
if (!client)
return;
stanza->setFrom(client->getJID());
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Message>(stanza);
if (message) {
client->sendMessage(message);
return;
}
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Presence> presence = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::Presence>(stanza);
if (presence) {
client->sendPresence(presence);
return;
}
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Swift::IQ>(stanza);
if (iq) {
if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) {
std::string resource = m_handlers[user]->m_id2resource[stanza->getID()];
if (resource.empty()) {
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain()));
} else {
iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), resource));
}
m_handlers[user]->m_id2resource.erase(stanza->getID());
}
client->getIQRouter()->sendIQ(iq);
return;
}
}
void handleStreamEnd() {}
void handleRawXML(const std::string &xml) {
m_xmppParser->parse(xml);
}
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"); 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"); 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;
case Swift::ClientError::SessionStartError: message = ("Error starting session"); break;
case Swift::ClientError::StreamError: message = ("Stream error"); break;
case Swift::ClientError::TLSError: message = ("Encryption error"); break;
case Swift::ClientError::ClientCertificateLoadError: message = ("Error loading certificate (Invalid password?)"); break;
case Swift::ClientError::ClientCertificateError: message = ("Certificate not authorized"); break;
case Swift::ClientError::UnknownCertificateError: message = ("Unknown certificate"); break;
case Swift::ClientError::CertificateExpiredError: message = ("Certificate has expired"); break;
case Swift::ClientError::CertificateNotYetValidError: message = ("Certificate is not yet valid"); break;
case Swift::ClientError::CertificateSelfSignedError: message = ("Certificate is self-signed"); break;
case Swift::ClientError::CertificateRejectedError: message = ("Certificate has been rejected"); break;
case Swift::ClientError::CertificateUntrustedError: message = ("Certificate is not trusted"); break;
case Swift::ClientError::InvalidCertificatePurposeError: message = ("Certificate cannot be used for encrypting your connection"); break;
case Swift::ClientError::CertificatePathLengthExceededError: message = ("Certificate path length constraint exceeded"); break;
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, reconnect ? 0 : 3, message);
SWIFTEN_SHRPTR_NAMESPACE::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);
m_handlers.erase(user);
}
#ifndef WIN32
#ifndef __FreeBSD__
#ifndef __MACH__
// force returning of memory chunks allocated by libxml2 to kernel
malloc_trim(0);
#endif
#endif
#endif
}
void handleSwiftConnected(const std::string &user) {
LOG4CXX_INFO(logger, user << ": Connected to XMPP server.");
handleConnected(user);
m_users[user]->requestRoster();
Swift::Presence::ref response = Swift::Presence::create();
response->setFrom(m_users[user]->getJID());
m_users[user]->sendPresence(response);
}
void handleSwiftRosterReceived(const std::string &user) {
Swift::PresenceOracle *oracle = m_users[user]->getPresenceOracle();
BOOST_FOREACH(const Swift::XMPPRosterItem &item, m_users[user]->getRoster()->getItems()) {
Swift::Presence::ref lastPresence = oracle->getLastPresence(item.getJID());
pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE;
handleBuddyChanged(user, item.getJID().toBare().toString(),
item.getName(), item.getGroups(), status);
}
}
void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) {
// SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) {
// return;
// }
//
// if (presence->getPayload<Swift::MUCUserPayload>() != NULL || presence->getPayload<Swift::MUCPayload>() != NULL) {
// return;
// }
//
// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed");
//
// std::string message = presence->getStatus();
// std::string photo = "";
//
// SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::VCardUpdate> update = presence->getPayload<Swift::VCardUpdate>();
// if (update) {
// photo = update->getPhotoHash();
// }
//
// boost::optional<Swift::XMPPRosterItem> item = m_users[user]->getRoster()->getItem(presence->getFrom());
// if (item) {
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo);
// }
// else {
// std::vector<std::string> groups;
// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo);
// }
presence->setTo(user);
std::string xml = safeByteArrayToString(serializer->serializeElement(presence));
sendRawXML(xml);
}
void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) {
message->setTo(user);
std::string xml = safeByteArrayToString(serializer->serializeElement(message));
sendRawXML(xml);
}
void handleSwiftenDataRead(const Swift::SafeByteArray &data) {
std::string d = safeByteArrayToString(data);
if (!boost::starts_with(d, "<auth")) {
LOG4CXX_INFO(logger_xml, "XML IN " << d);
}
}
void handleSwiftenDataWritten(const Swift::SafeByteArray &data) {
LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
LOG4CXX_INFO(logger, user << ": connecting as " << legacyName);
Swift::JID jid(legacyName);
if (legacyName.find("/") == std::string::npos) {
jid = Swift::JID(legacyName + "/Spectrum");
}
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::Client>(jid, password, m_factories);
m_users[user] = client;
client->setAlwaysTrustCertificates();
client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1));
client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1));
client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3));
client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2));
Swift::ClientOptions opt;
opt.allowPLAINWithoutTLS = true;
client->connect(opt);
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ForwardIQHandler> handler = SWIFTEN_SHRPTR_NAMESPACE::make_shared<ForwardIQHandler>(this, user);
client->getIQRouter()->addHandler(handler);
m_handlers[user] = handler;
}
void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) {
handleSwiftPresenceChanged(user, presence);
}
void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) {
Swift::Presence::ref presence = Swift::Presence::create();
presence->setTo(user);
presence->setFrom(jid);
presence->setType(Swift::Presence::Unsubscribe);
handleSwiftPresenceChanged(user, presence);
}
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
SWIFTEN_SHRPTR_NAMESPACE::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));
client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
client->disconnect();
}
}
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
}
void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
}
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
if (client) {
LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) {
Swift::RosterItemPayload item;
item.setName(alias);
item.setJID(buddyName);
item.setGroups(groups);
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
roster->addItem(item);
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
client->getSubscriptionManager()->requestSubscription(buddyName);
}
else {
Swift::JID contact(buddyName);
Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact));
item.setGroups(groups);
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
roster->addItem(item);
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
}
}
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> client = m_users[user];
if (client) {
Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove);
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RosterPayload> roster(new Swift::RosterPayload());
roster->addItem(item);
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter());
// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
}
}
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
}
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
}
private:
Config *config;
std::map<std::string, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Client> > m_users;
std::map<std::string, SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<ForwardIQHandler> > m_handlers;
};
#ifndef WIN32
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
#endif
int main (int argc, char* argv[]) {
std::string host;
int port;
#ifndef WIN32
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
#endif
std::string error;
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
if (cfg == NULL) {
std::cerr << error;
return 1;
}
Logging::initBackendLogging(cfg);
Swift::SimpleEventLoop eventLoop;
loop_ = &eventLoop;
np = new SwiftenPlugin(cfg, &eventLoop, host, port);
loop_->run();
return 0;
}

View file

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum2_template_backend ${SRC})
if (CMAKE_COMPILER_IS_GNUCXX)
if (NOT WIN32)
target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else()
target_link_libraries(spectrum2_template_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
endif()
else()
target_link_libraries(spectrum2_template_backend transport ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
endif()
#INSTALL(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin)

View file

@ -1 +0,0 @@
This is just template for creating new generic spectrum2 backends. It does not do anything!

View file

@ -1,68 +0,0 @@
#include "plugin.h"
// Transport includes
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "transport/Logging.h"
// Swiften
#include "Swiften/Swiften.h"
#ifndef _WIN32
// for signal handler
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
#endif
// Boost
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
#ifndef _WIN32
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
#endif
int main (int argc, char* argv[]) {
std::string host;
int port;
#ifndef _WIN32
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
#endif
std::string error;
Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
if (cfg == NULL) {
std::cerr << error;
return 1;
}
Logging::initBackendLogging(cfg);
Swift::SimpleEventLoop eventLoop;
Plugin p(cfg, &eventLoop, host, port);
eventLoop.run();
return 0;
}

View file

@ -1,62 +0,0 @@
#include "plugin.h"
// Transport includes
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
#include "transport/Logging.h"
// Swiften
#include "Swiften/Swiften.h"
// Boost
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
DEFINE_LOGGER(logger, "Backend Template");
Plugin::Plugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
this->config = config;
m_factories = new Swift::BoostNetworkFactories(loop);
m_conn = m_factories->getConnectionFactory()->createConnection();
m_conn->onDataRead.connect(boost::bind(&Plugin::_handleDataRead, this, _1));
m_conn->connect(Swift::HostAddressPort(SWIFT_HOSTADDRESS(host), port));
LOG4CXX_INFO(logger, "Starting the plugin.");
}
// NetworkPlugin uses this method to send the data to networkplugin server
void Plugin::sendData(const std::string &string) {
m_conn->write(Swift::createSafeByteArray(string));
}
// This method has to call handleDataRead with all received data from network plugin server
void Plugin::_handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data) {
std::string d(data->begin(), data->end());
handleDataRead(d);
}
void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
handleConnected(user);
LOG4CXX_INFO(logger, user << ": Added buddy - Echo.");
handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
}
void Plugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
}
void Plugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
if (legacyName == "echo") {
handleMessage(user, legacyName, message);
}
}
void Plugin::handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
}
void Plugin::handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
}

View file

@ -1,35 +0,0 @@
#pragma once
#include "Swiften/Swiften.h"
#include "Swiften/SwiftenCompat.h"
#include "transport/Config.h"
#include "transport/NetworkPlugin.h"
class Plugin : public Transport::NetworkPlugin {
public:
Plugin(Transport::Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port);
// NetworkPlugin uses this method to send the data to networkplugin server
void sendData(const std::string &string);
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
void handleLogoutRequest(const std::string &user, const std::string &legacyName);
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
private:
// This method has to call handleDataRead with all received data from network plugin server
void _handleDataRead(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::SafeByteArray> data);
private:
Swift::BoostNetworkFactories *m_factories;
Swift::BoostIOServiceThread m_boostIOServiceThread;
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> m_conn;
Transport::Config *config;
};

View file

@ -1,103 +0,0 @@
#!/usr/bin/python
import asyncore, argparse, protocol_pb2, socket, logging
from NetworkPlugin import NetworkPlugin
np = None
logger = logging.getLogger('Template Backend')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
def handleTransportData(data):
"""
This function is called when data is received from the NetworkPlugin server
"""
np.handleDataRead(data)
class SpectrumPlugin(NetworkPlugin):
global logger
def __init__(self, iochannel):
NetworkPlugin.__init__(self)
self.iochannel = iochannel
logger.info("Starting plugin.")
def sendData(self, string):
"""
NetworkPlugin uses this method to send the data to networkplugin server
"""
self.iochannel.sendData(string)
logger.info("Starting plugin.")
def handleLoginRequest(self, user, legacyName, password):
self.handleConnected(user)
logger.info("Added Echo Buddy")
self.handleBuddyChanged(user, "echo", "Echo", [], protocol_pb2.STATUS_ONLINE)
def handleLogoutRequest(self, user, legacyName):
pass
def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""):
logger.info("Message sent from " + user + ' to ' + legacyName)
if(legacyName == "echo"):
logger.info("Message Echoed: " + message)
self.handleMessage(user, legacyName, message)
def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups):
logger.info("Added Buddy " + buddyName)
self.handleBuddyChanged(user, buddyName, alias, groups, protocol_pb2.STATUS_ONLINE)
def handleBuddyRemovedRequest(self, user, buddyName, groups):
pass
class IOChannel(asyncore.dispatcher):
def __init__(self, host, port, readCallBack):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
self.handleReceivedData = readCallBack
self.send_buffer = ""
def sendData(self, data):
self.send_buffer += data
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
data = self.recv(65536)
self.handleReceivedData(data)
def handle_write(self):
sent = self.send(self.send_buffer)
self.send_buffer = self.send_buffer[sent:]
def writable(self):
return (len(self.send_buffer) > 0)
def readable(self):
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--host', type=str, required=True)
parser.add_argument('--port', type=int, required=True)
parser.add_argument('config_file', type=str)
args = parser.parse_args()
io = IOChannel(args.host, args.port, handleTransportData)
np = SpectrumPlugin(io)
asyncore.loop()

View file

@ -1,15 +0,0 @@
include_directories (${libtransport_SOURCE_DIR}/backends/twitter/libtwitcurl)
FILE(GLOB SRC *.cpp libtwitcurl/*.cpp Requests/*.cpp)
add_executable(spectrum2_twitter_backend ${SRC})
find_package(CURL)
if(CURL_FOUND)
message(STATUS "Using curl ${CURL_VERSION_STRING}: ${CURL_INCLUDE_DIRS} ${CURL_LIBRARIES}")
include_directories (${CURL_INCLUDE_DIRS})
target_link_libraries(spectrum2_twitter_backend transport ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else()
message(FATAL_ERROR "curl not found")
endif()
INSTALL(TARGETS spectrum2_twitter_backend RUNTIME DESTINATION bin)

View file

@ -1,72 +0,0 @@
#include "HTTPRequest.h"
DEFINE_LOGGER(logger, "HTTPRequest")
bool HTTPRequest::init()
{
curlhandle = curl_easy_init();
if(curlhandle) {
curlhandle = curl_easy_init();
curl_easy_setopt(curlhandle, CURLOPT_PROXY, NULL);
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, NULL);
curl_easy_setopt(curlhandle, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
return true;
}
LOG4CXX_ERROR(logger, "Couldn't Initialize curl!");
return false;
}
void HTTPRequest::setProxy(std::string IP, std::string port, std::string username, std::string password)
{
if(curlhandle) {
std::string proxyIpPort = IP + ":" + port;
curl_easy_setopt(curlhandle, CURLOPT_PROXY, proxyIpPort.c_str());
if(username.length() && password.length()) {
std::string proxyUserPass = username + ":" + password;
curl_easy_setopt(curlhandle, CURLOPT_PROXYUSERPWD, proxyUserPass.c_str());
}
} else {
LOG4CXX_ERROR(logger, "Trying to set proxy while CURL isn't initialized");
}
}
int HTTPRequest::curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest* obj)
{
int writtenSize = 0;
if(obj && data) {
obj->callbackdata.append(data, size*nmemb);
writtenSize = (int)(size*nmemb);
}
return writtenSize;
}
bool HTTPRequest::GET(std::string url, std::string &data)
{
if(curlhandle) {
curl_easy_setopt(curlhandle, CURLOPT_CUSTOMREQUEST, NULL);
curl_easy_setopt(curlhandle, CURLOPT_ENCODING, "");
data = "";
callbackdata = "";
memset(curl_errorbuffer, 0, 1024);
curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, curl_errorbuffer);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, curlCallBack);
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this);
/* Set http request and url */
curl_easy_setopt(curlhandle, CURLOPT_HTTPGET, 1);
// curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
/* Send http request and return status*/
if(CURLE_OK == curl_easy_perform(curlhandle)) {
data = callbackdata;
return true;
}
} else {
LOG4CXX_ERROR(logger, "CURL not initialized!");
strcpy(curl_errorbuffer, "CURL not initialized!");
}
return false;
}

View file

@ -1,37 +0,0 @@
#ifndef HTTPREQ_H
#define HTTPREQ_H
#include "curl/curl.h"
#include "transport/Logging.h"
#include <iostream>
#include <sstream>
#include <string.h>
class HTTPRequest
{
CURL *curlhandle;
char curl_errorbuffer[1024];
std::string error;
std::string callbackdata;
static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj);
public:
HTTPRequest() {
curlhandle = NULL;
}
~HTTPRequest() {
if(curlhandle) {
curl_easy_cleanup(curlhandle);
curlhandle = NULL;
}
}
bool init();
void setProxy(std::string, std::string, std::string, std::string);
bool GET(std::string, std::string &);
std::string getCurlError() {return std::string(curl_errorbuffer);}
};
#endif

Some files were not shown because too many files have changed in this diff Show more